使用声音矩阵模块辨别出声源的方位,声音的大小可以反映出小车与声源的距离。
基于以上两点在空旷无回音的地点找到声源,希望感兴趣的朋友们可以继续完善算法,客服噪声、回音等等问题
驱动是用的l298n,加装了两个光电传感器实现寻声过程中基本避障功能。
单片机源程序如下:
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include "adc.h"
- #include "dma.h"
- #include "moto.h"
- #include "pwm.h"
- #include "oled.h"
- #include "key.h"
- float Mv=0; //平均值
- int S=0; //模拟声音大小
- float Jvalue(float a);//数据处理,类似绝对值
- u16 adcx[6]; //ADC采样数组
- extern u8 guangdian;
- void Display(void);//显示
- int main(void)//主函数
- {
- // int i;//循环变量
- // float adc1,adc2,adc3,adc4,adc5,adc6; //ADC采样值
- // float v1,v2,v3,v4,v5,v6;//数据值
- delay_init(); //延时函数初始化
- SystemInit();
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
- LED_Init(); //LED端口初始化
- MOTO_GPIO_Config(); //电机初始化
- OLED_Init(); //OLED初始化
- KEY_Init();
- OLED_ColorTurn(0);//0正常显示,1 反色显示
- OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
- GPIO_SetBits(GPIOB,GPIO_Pin_6); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0;
- GPIO_SetBits(GPIOB,GPIO_Pin_7); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0;
- delay_ms(1000); //延时启动
- GPIO_ResetBits(GPIOB,GPIO_Pin_7); //LED1对应引脚GPIOE.5拉高,灭 等同LED1=1;
- delay_ms(1000); //延时启动
- GPIO_SetBits(GPIOB,GPIO_Pin_6); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0;
- GPIO_SetBits(GPIOB,GPIO_Pin_7); //LED0对应引脚GPIOB.5拉低,亮 等同LED0=0;
- TIM1_PWM_Init(100,36); //PWM初始化
- MYDMA_Config(DMA1_Channel1,(u32)(&ADC1->DR),(u32)adcx,6);//DMA1通道1,外设为串口1,存储器为SendBuff,长度SEND_BUF_SIZE.
- Adc_Init(); //ADC初始化
- TIM_SetCompare1(TIM1,25); //占空比=1-25/100
- TIM_SetCompare3(TIM1,25);
- TIM3_Int_Init(10,35999);
- delay_ms(400); //延时启动
- while(1) //主循环
- {
- // v1=0;v2=0;v3=0;v4=0;v5=0;v6=0; //清零
- // for(i=500;i>0;i--) //循环检测500次
- // {
- // adc1=(float)(adcx[0])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v1+=Jvalue(adc1)*0.6;
- // adc2=(float)(adcx[1])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v2+=Jvalue(adc2);
- // adc3=(float)(adcx[2])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v3+=Jvalue(adc3);
- // adc4=(float)(adcx[3])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v4+=Jvalue(adc4);
- // adc5=(float)(adcx[4])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v5+=Jvalue(adc5)*0.4;
- // adc6=(float)(adcx[5])*(3.3/4096); //获取计算后的带小数的实际电压值,比如3.1111
- // v6+=Jvalue(adc6);
- // }
- // Mv=(v1+v2+v3+v4+v5+v6)/6; //求平均
- //// Display(); //显示
- //// delay_ms(2000); //延时启动
- // if((v1+v2+v3+v4+v5+v6)<120) //太远
- // {
- // Car_Stop(); //停车
- // }
- // else if((v1+v2+v3+v4+v5+v6)>1800)//太近
- // {
- // Car_Stop();
- // }
- // else //正常范围
- // {
- // if(1) //声源在前侧
- // {
- // if((v6)>(v2)) //声源在左边
- // {
- // Car_Turn_Left();//左转
- // S++; //模拟声音大小值
- // }
- // else if((v2)>(v6))//声源在右边
- // {
- // Car_Turn_Right(); //右转
- // S++;
- // }
- // else //声源在中间
- // {
- // Car_Go(); //前进
- // S++;
- // }
- // }
- // else //声源在后侧
- // {
- // Car_RRight();//原地右转
- // }
- ////// Car_RRight();//原地右转
- ////// Car_Go(); //前进
- ////// Car_Turn_Left();//左转
- //// Car_Turn_Right(); //右转
- // }
- }
- }
- float Jvalue(float a) //数据处理,将正负变换的数据转换成正误差
- {
- float b;
- if(a>=1.65)
- {
- b=a-1.65;
- }
- else
- {
- b=1.65-a;
- }
- return b;
- }
- void Display(void)//数据显示
- {
- OLED_ShowChinese(0,1,18,16,1);//"声"
- OLED_ShowChinese(18,1,19,16,1);//"音"
- OLED_ShowChinese(36,1,9,16,1);//":"
- OLED_ShowNum(45,1,Mv,4,16,1);
- OLED_ShowChar(80,1,'d',16,1);
- OLED_ShowChar(90,1,'B',16,1);
- OLED_ShowChinese(0,20,0,16,1);//"路"
- OLED_ShowChinese(18,20,1,16,1);//"程"
- OLED_ShowChinese(36,20,2,16,1);//":"
- OLED_ShowNum(45,20,S,4,16,1);
- OLED_ShowChar(80,20,'c',16,1);
- OLED_ShowChar(89,20,'m',16,1);
-
- OLED_ShowNum(45,40,guangdian,4,16,1);
- OLED_Refresh();//更新显存到OLED
- }
复制代码
Keil代码下载:
程序源码.7z
(222.8 KB, 下载次数: 31)
|