基于STM32F103HAL库的声音定位系统

2023-11-01

在这里插入图片描述
这是一道学校出的电赛题目,要求在100*100cm的平面上实现定位实现声音定位。由于一米太大了,我们就做了40cm的,下面的讲解我按照40厘米的写。用到的处理器是stm32f103c8t6接下来分享一下调试心得。
硬件部分需要制作发声装置和接收装置,详细可以参考这个文章.
需要知道的是,扬声器发出的声音经过接收装置,得到的是一个方波信号,所以单片机需要根据这些方波求出距离

解题思路

一.直线

既然我们说,接收模块得到的是方波信号,那么单片机肯定可以检测到方波的下降沿和上升沿,在直线上,声源距离接收模块越近,声音先到达,就先接收到下降沿,相反,声源距离接收模块远,就后接受到下降沿,这样我们可以得到时间差。接下来就是小学数学了(手动狗头),根据两个时间可以算出距离。请添加图片描述
用C语言描述就是这样

传入参数:两个下降沿分别到两个接收器之间的时间差
传出参数:距离
float Find_Line(float ltime)
{
	float S=0,timeall=0,timefst=0;
	timeall=0.0012;        //单位是秒,根据ltime单位做调整     0.4/346
	timefst=(timeall+ltime)/2;
	S=0.4*(timefst/timeall);
	
	return S;
}

二.平面

在平面上,就需要三个接收模块,这样就能得出两个时间差。
像下面这幅图
请添加图片描述

用C语言描述是这样,得到的arv1和arv2就是坐标值,
整个函数就是解方程的思路,用穷举法求出合适的值,我在后面又对得到的值做了求平均处理。

//传入参数:两个时间差
void Find_Square(float ctime1,float ctime2)
{
	int count,i=0;

   for(x=0.0; x<=40.0; x++)
    {
        for(y=0.0; y<=40.0;y++)
        {
            if(fabs(sqrt(x*x+(y-40)*(y-40))-sqrt(x*x +y*y)-34000*ctime1)<3 && fabs(sqrt(x*x +y*y)-sqrt((40-x)*(40-x)+y*y)-34000*ctime2)<3)  
             {  
                    a[i]=x;
                    b[i]=y;
                    i++;
                    count =i;
                printf("x=%.2f  y=%.2f count=%d\n",x,y,count);
             }  
            else{printf("方程无解");}
        }
    }
//		count=Del_Zero(a,count);
//		Del_Zero(b,count);
        for(int i=0; i< count; i++)
        {
            sum1=sum1+a[i];
            sum2=sum2+b[i];
            arv1=sum1/count;
            arv2=sum2/count;
						
             printf("a[i]=%.2f  b[i]=%.2f count=%d  %f\n",a[i],b[i],count,sum1);
        }
        printf("arv1=%.2f arv2=%.2f\n",arv1,arv2);
				sum1=0;sum2=0;
}

二.单片机获取时间

其实解题思路不难,难点就在于获取到准确的时间,我使用的获取方法是外部中断,当单片机的一个IO口检测到下降沿,定时器开始计时,另一个IO口检测到下降沿停止计时,这样就得到时间差

1.cubemx配置

1.外部中断
在这里插入图片描述
在这里插入图片描述
2.定时器
由于晶振是72MHZ,而且接收到下降沿的时间在微秒级别,所以将单位时间设置为100us(72000000/72/100=10000hz)(1/10000=100us)
在这里插入图片描述

/**
  * 函数功能: 按键外部中断回调函数
  * 输入参数: GPIO_Pin:中断引脚
  * 返 回 值: 无
  * 说    明: 无
  */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	
  if(GPIO_Pin==GPIO_PIN_0)//A
  {
		if(time1==0)
		{
			wosignA=0;
			HAL_TIM_Base_Start_IT(&htim2); //使能刚刚配置的定时器
		}
		else
		{
			wosignA=time1+255*time2;
			//HAL_TIM_Base_Stop_IT(&htim2);
		}
				signA=1; 
	}
		 if(GPIO_Pin==GPIO_PIN_1)//B
		{
			if(time1==0)
			{
				wosignB=0;
				HAL_TIM_Base_Start_IT(&htim2); //使能刚刚配置的定时器
			}
			else
			{
				wosignB=time1+255*time2;
				//HAL_TIM_Base_Stop_IT(&htim2);
			}
			signB=1;
			//EXTI->IMR &= ~(GPIO_PIN_1); 
		}
		 if(GPIO_Pin==GPIO_PIN_11)//B
		{
			if(time1==0)
			{
				wosignC=0;
				HAL_TIM_Base_Start_IT(&htim2); //使能刚刚配置的定时器
			}
			else
			{
				wosignC=time1+255*time2;
				//HAL_TIM_Base_Stop_IT(&htim2); //使能刚刚配置的定时器
			}
			signC=1;
			//EXTI->IMR &= ~(GPIO_PIN_1); 
		}

}
/**
  * 函数功能: 定时器中断回调函数
  * 输入参数: 
  * 返 回 值: 无
  * 说    明: 无
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

		 if (htim->Instance == htim2.Instance)
		 {

					time1++;	 
					if(time1==255){time2++;time1=0;}//定时器计数255次溢出一次
		 }
		 if (htim->Instance == htim1.Instance)
		 {

		 }
}
		key=read_key();
		if(key==1) {mode=1;OLED_Clear();}
		if(key==2) {mode=2;OLED_Clear();}
		if(key==3) {mode=3;OLED_Clear();}
		if(mode==1)
		{
				if(signA&&signB)
			{
				EXTI->IMR &= ~(GPIO_PIN_0);//关闭外部中断
				EXTI->IMR &= ~(GPIO_PIN_1);
				HAL_TIM_Base_Stop_IT(&htim2);
				if(wosignA<wosignB){t1=wosignB;}
				else	{t1=wosignA;}
				if(t1>11){t1=11;}
				s=Find_Line(fabs((float)(t1))*100/1000000);
				printf("%d   %d    %f   %d   %d  %d %d\n",time1,time2,s,wosignA,wosignB,wosignC,t1);
				OLED_ShowFloat(0,0,s,2,4,16);
				HAL_Delay(100);
				EXTI->IMR |= GPIO_PIN_0; //开启外部中断
				EXTI->IMR |= GPIO_PIN_1;
				signA=0;signB=0;
				time1=0;time2=0;
			}
		}
//printf("%d   %d   %d    %d  %d  %d\n",signA,signB,signC,wosignC,wosignA,wosignB);
			if(mode==2)
			{
						if(signA&&signB&&signC)
					{
						EXTI->IMR &= ~(GPIO_PIN_0);
						EXTI->IMR &= ~(GPIO_PIN_1);
						EXTI->IMR &= ~(GPIO_PIN_11);
						HAL_TIM_Base_Stop_IT(&htim2);
						if((wosignA<wosignB)&&(wosignB<wosignC)){t2=wosignB;t3=wosignC;}
						if((wosignA<wosignC)&&(wosignB>wosignC)){t2=wosignC;t3=wosignB;}
						if((wosignB<wosignA)&&(wosignA<wosignC)){t2=wosignA;t3=wosignC;}
						if((wosignB<wosignC)&&(wosignC<wosignA)){t2=wosignC;t3=wosignA;}
						if((wosignC<wosignA)&&(wosignA<wosignB)){t2=wosignA;t3=wosignB;}
						if((wosignC<wosignB)&&(wosignB<wosignA)){t2=wosignB;t3=wosignA;}
						if(t2>11){t2=11;}
						if(t3>11){t3=11;}
//						t2=wosignA-wosignB;
//						t3=wosignB-wosignC;
						printf("%d   %d    %f   %d   %d  %d %d %d\n",time1,time2,s,wosignA,wosignB,wosignC,t2,t3);
						Find_Square((float)t2/10000,(float)t3/10000);
						OLED_ShowFloat(0,0,arv1,2,4,16);
						OLED_ShowFloat(0,2,arv2,2,4,16);
						//HAL_Delay(100);
						EXTI->IMR |= GPIO_PIN_0; 
						EXTI->IMR |= GPIO_PIN_1;
						EXTI->IMR |= GPIO_PIN_11;
						signA=0;signB=0;signC=0;
						time1=0;time2=0;
					}
				}
			if(mode==3){goto MENU;}
			}

可以用自己的按键,设置标志位做两个模式,完成持续监测。

成品的误差稍微有些大,不乏温度,湿度,以及硬件误差,和单片机检测误差,没有滤波等等,总的来说,大体方向是对的,我们的作品还能进一步完善。
在调试的时候,单片机PB10引脚接收不到方波信号,拆了板子打电表,查不出问题,结果换了个引脚,好了,,,,,

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32F103HAL库的声音定位系统 的相关文章

  • 手臂 g++ 中缺少一些东西

    我安装了 CodeSourcery g 工具链并尝试编译一个简单的 hello world 程序 include
  • ARM 汇编 SOS 中的 64 位除法

    我正在计算 16 个 64 位数字相加的平均值 我认为我已经正确完成了所有加法 但现在我需要弄清楚如何将 64 位数字除以 16 但我被困住了 任何帮助都会非常感谢你 到目前为止 这是我的代码 tableSize EQU 16 sum EQ
  • 如何在 ARM 架构上从 RAM 运行代码

    我正在对 ARM Cortex R4 进行编程 并且有一些二进制文件 我想从 TCRAM 执行它们 只是为了看看性能的提升是否足够好 我知道我必须编写一个函数来将二进制文件复制到 RAM 这可以通过链接器脚本来完成 并且知道二进制文件的大小
  • 嵌入式 C++ (ARM9) 单元测试

    我来自 Java 和 JUnit 的世界 我演示了 Hudson 以及我使用 JUnit 取得的所有成果 我想在嵌入式设备上对 C 代码执行相同的操作 但找不到从哪里开始 该项目使用 iccarm exe IAR 编译器 进行编译 现在使用
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • 如何使用 gcc 编译代码和 ARM Cortex A8 目标进行调用图分析?

    我对这个已经咬牙切齿了 我需要在 ARM 板上进行分析并需要查看调用图 我尝试使用 OProfile Kernel perf 和 Google 性能工具 一切正常 但不输出任何调用图信息 这使我得出结论 我没有正确编译代码 我在编译 C 代
  • Linux malloc() 在 ARM 和 x86 上的行为是否不同?

    这个网站上有很多关于内存分配的问题 但是我 找不到专门解决我的问题的人 这 问题 https stackoverflow com questions 19148296 linux memory overcommit details似乎最接近
  • 如何在 Android 设备上运行 VS Code [重复]

    这个问题在这里已经有答案了 我有 Galaxy Tab S6 它具有替代笔记本电脑的很酷的功能 例如连接鼠标和键盘 但不幸的是它运行 Android 操作系统 并且没有很多开发应用程序可用于 Android 所以我想是否有一个选项可以在至少
  • M1 MacBook Pro 上的 Android Studio 无法使用 ABI armeabi-v7a 模拟系统映像

    我的 M1 Macbook Pro 上的 Android Studio 可以很好地模拟 ABI arm64 v8a 的所有系统映像 API 24 29 30 31 但是 它无法使用 ABI armeabi v7a 运行所有映像 例如 API
  • 分析 Cortex-M7 (stm32f7) 上的 memcpy 性能

    简洁版本 从 GNU ARM 工具链中提取的 memcpy 的性能指标在 ARM Cortex M7 上对于不同的副本大小似乎差异很大 即使复制数据的代码始终保持不变 这可能是什么原因造成的 长版 我是使用 GNU Arm 工具链 11 2
  • 如何使用 Neon SIMD 将无符号字符转换为有符号整数

    如何转换变量的数据类型uint8 t to int32 t使用霓虹灯 我找不到执行此操作的任何内在因素 假设您想要将 16 x 8 位整数的向量转换为 4 个 4 x 32 位整数的向量 您可以通过首先解压缩为 16 位 然后再次解压缩为
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 在 Intel 机器上构建 Apple Silicon 二进制文件

    如何在 macOS 11 Intel 上编译 C 项目以在 Silicon 上运行 我当前的构建脚本很简单 configure make sudo make install 我尝试过使用 host and target标志与aarch64
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • 了解 U-Boot 内存占用

    我不明白加载 U Boot 时 RAM 中发生了什么 我正在开发 Xilinx Zynq ZC702 评估套件 并尝试使用 U Boot 在其上加载 Linux 内核 于是我使用Xilinx工具Vivado和SDK生成了一个BOOT bin
  • AOSP 的“午餐”组合是什么意思?我需要选择什么?

    我是 Android 设备 ROM 开发的新手 无论如何 我现在正在为具有 64 位处理器的中国设备构建 AOSP 我按照 source android com 上的菜单进行操作 当我运行 午餐 命令时 终端显示 午餐菜单 选择一个组合 我
  • 什么是遗留中断?

    我正在开发一个项目 试图弄清楚 ARM 架构的全局中断控制器中如何处理中断 我正在使用 pl390 中断控制器 我看到有一条线被称为传统中断 它绕过了分配器逻辑 假设有 2 个中断可以被编程为传统中断 任何人都可以帮助解释一下什么是遗留中断
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加
  • 为arm构建WebRTC

    我想为我的带有arm926ej s处理器的小机器构建webrtc 安装 depot tools 后 我执行了以下步骤 gclient config http webrtc googlecode com svn trunk gclient s
  • ARM NEON 矢量化失败

    我想在 ARM cortex a9 上启用 NEON 矢量化 但在编译时得到以下输出 未矢量化 不支持相关 stmt D 14140 82 D 14143 77 D 14141 81 这是我的循环 void my mul float32 t

随机推荐

  • Robotframework 入门教程(一)

    最近工作中用Robot Framework框架来做自动化 所以 花时间学习了一下 网上好的文档不多 大多都是复制粘贴如何安装环境 要么就是介绍了一堆RIDE的界面 活活把这么强大的一个工具讲成了个photoshop 我目前用了1个多月 这个
  • GMT、UTC、DST、CST时区

    GMT Greenwich Mean Time 格林威治标准时间 UTC Coordinated Universal Time 世界协调时间 DST Daylight Saving Time 夏季节约时间 CST 四个不同时区的缩写 1 C
  • 全网最新,解决maven配置本地仓库,IDEA不显示本地仓库的问题,IDEA创建maven项目,maven下载失败

    导语 在本地安装了maven后 使用IDEA创建maven项目后 IDEA下载到本地仓库会失败 配置了maven的本地仓库 IDEA不自动显示 我的maven的版本是3 8 1 IDEA的版本2020 2 s 正确配置maven的本地仓库的
  • chromedp入门

    chromedp是什么 chromedp是go写的 支持Chrome DevTools Protocol 的一个驱动浏览器的库 并且它不需要依赖其他的外界服务 比如 Selenium 和 PhantomJs Chrome DevTools
  • Markdown自动生成左侧导航栏

    导出Mardown为html 复制粘贴上去即可
  • 心理学十五讲

    真的应该看看这种科普类的作品 1 原来对于催眠这些东西 早就有系统的研究 有人赞同 有人不赞同 而我却不知道 不知道呀 必须勤读书才行呀 2013 12 9 2 中国人为什么趋同 女人为什么会要买广告上的东西 人们会根据周围的人的反应来判断
  • python使用plot画图

    参考地址 matplot官方文档 调用方法 from matplotlib import pyplot as plt 引入库 matplotlib inline 嵌入内部 matplotlib 跳出交互 plt plot x y fmt d
  • SAS EM(五)贷款评分卡制作(数据集+实战)(小白上手简易版)

    SAS EM 五 贷款模型评分卡制作 在完成评分卡制作前 需要确保sas相对应的功能是否能使用 正所谓工欲善其事必先利其器 这篇博客主要是实践为主 至于理论知识可查看我的评分卡专栏 有相关博文介绍 https blog csdn net l
  • vue鼠标移入添加class样式,鼠标移出去除样式

    div ul li li ul div
  • VTK Python 代码详解(五)读取点云数据、旋转平移、合并显示

    VTK Python 代码整理 读取点云 txt 数据并显示 txt 点云数据 代码 效果图 代码2 背面效果 代码封装优化 两个点云模型同时显示 代码 效果图 旋转 平移动点云模型 旋转 平移 变换代码 完整代码 最终效果 读取点云 tx
  • Error: Activity class {com.example.wusuowei.uniapp_simple/io.dcloud.PandoraEntry} does not exist.

    问题 uniapp离线打包时 将原本烧到手机的apk删除后 重新编译 出现了下面的错误 adb shell am start n com example wusuowei uniapp simple io dcloud PandoraEnt
  • Required request body is missing 错误解决

    今天测试接口的时候报错如下 ERROR c j d a c PartCleanController Required request body content is missing org springframework web metho
  • John Carmack:我们为什么不开发Linux游戏

    http www csdn net article 2013 02 13 2814126 John Carmack why we dont develop linux game 摘要 虽然Valve已经公开支持Linux游戏 Blizzar
  • Nignx优化与防盗链

    目录 前言 1 nginx优化 2 修改用户和组 3 设置缓存时间 4 日志分割 5 连接超时 6 更改进程数 7 网页压缩 8 盗链与防盗链 9 FPM模块参数优化 小结 前言 在企业信息化应用环境中 服务器的安全性和响应速度需要根据实际
  • mysql 半同步复制(semi_sync_replication)搭建及使用

    google为mysql开发了一个补丁一个基于半同步的补丁 应用与mysql5 0 回来mysql打上了该补丁 并在5 5版本中使用 半同步复制的理念是什么呢 在数据库更改操作执行前 确保更改操作至少被写入一台slave磁盘中 意味着着对于
  • JsonView--离线查看JSON格式化工具

    1 软件工具准备 下载地址如下 链接 https pan baidu com s 1opc 6kcnGSykiUtjVPKDg 提取码 grmt 2 解压后 无需安装 直接运行JsonView exe 打开界面如下 将json格式的数据 复
  • CTP接口入门

    该文章主要讲什么 这篇文章的面向对象是有一些C 基础 并且想用C 来做程式化交易的同学 这篇文章可以算是我的程式化学习笔记中的一篇 其中介绍了CTP的简单的使用方式 并且附上了一些代码以及我在试用的时候遇到的一些小坑 什么是CTP CTP是
  • C++:sprintf()的用法

    转 http blog csdn net masikkk article details 5634886 更多 http blog csdn net zjuwispersure article details 6083982 在将各种类型的
  • 使用ThreadLocal请务必remove

    场景说明 压测的时候发现调用某个接口同一个入参 返回的商品数据不一致 使用技术 threadLocal 问题原因 使用ThreadLocal没有remove 导致问题 1内存溢出 ThreadLocal依赖没有释放 无法GC 2线程池的某个
  • 基于STM32F103HAL库的声音定位系统

    这是一道学校出的电赛题目 要求在100 100 的平面上实现定位实现声音定位 由于一米太大了 我们就做了40 的 下面的讲解我按照40厘米的写 用到的处理器是 接下来分享一下调试心得 硬件部分需要制作发声装置和接收装置 详细可以参考这个文章