STM32 f103搭配LM386聲音傳感器實現簡單音樂識別

 

STM32 f103搭配LM386聲音傳感器實現簡單音樂識別

1.前言

     2019年12月初,有一箇中國機器人技能大賽中的雙足機器人比賽項目,意思是機器人識別音樂跳對應節奏的舞蹈,五首音樂隨機抽三首歌曲,音樂停,機器人停。html

     新比賽,新項目,難度天然有,坑也很多。但願這篇文章能給你們帶來一點幫助。廢話很少說,進入正題。node

2.效果

(健康歌)每100ms採樣一次,歌曲前5秒內共測50次數據,重複12組web

(卡路里) 重複7組windows

       能夠看出一首歌通過屢次測值,其採樣值數組呈現出有規律的特徵;不一樣的歌曲的特徵也有較好的區分度。達到了區分歌曲的效果。下面講講具體實現步驟。數組

3.思路

  1. 作什麼:識別不一樣音樂,識別聲音有無。
  2. 怎麼作:a.利用傳感器判斷出音樂或聲音(網上資料極少);   b.利用手機app聽歌識曲,返回對應值(app感受太難) ;    c.檢測到聲音就隨機跳(下策,保命方案);    d.遙控(做弊);   e.人在旁邊說出歌曲有關的詞語,語音模塊識別(干擾大)
  3. 個人選擇:a+c
  4. 技術路線

4.硬件

      找到一塊具備模擬量輸出功能的聲音傳感器模塊,我用的是下面這塊,感受不錯,其餘的沒嘗試過。將f103芯片的A1腳與模塊的AOUT引腳相連(奇怪的是我與DOUT相連也會獲得和AOUT差很少的模擬量值,很迷,有大佬懂的話麻煩指出一下問題所在)。app

 

5.軟件

利用正點原子的adc.c文件來處理模擬量值,並最終返回給Get_Adc_Average()函數less

 
 
 
x
 
 
 
 
1
//初始化ADC
2
//這裏咱們僅以規則通道爲例
3
//咱們默認將開啓通道0~3
4
void  Adc_Init(void)
5
{ 
6
    ADC_InitTypeDef ADC_InitStructure; 
7
GPIO_InitTypeDef GPIO_InitStructure;
8
    //使能ADC1通道時鐘
9
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); 
10
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//設置ADC分頻因子6 72M/6=12,ADC最大時間不能超過14M
11
    //PA1 做爲模擬通道輸入引腳                         
12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
13
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模擬輸入引腳
14
GPIO_Init(GPIOA, &GPIO_InitStructure);
15
16
ADC_DeInit(ADC1);  //復位ADC1 
17
18
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
19
    //ADC工做模式:ADC1和ADC2工做在獨立模式
20
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//模數轉換工做在單通道模式
21
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//模數轉換工做在單次轉換模式
22
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
23
    //轉換由軟件而不是外部觸發啓動
24
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//ADC數據右對齊
25
ADC_InitStructure.ADC_NbrOfChannel = 1;//順序進行規則轉換的ADC通道的數目
26
ADC_Init(ADC1, &ADC_InitStructure);
27
    //根據ADC_InitStruct中指定的參數初始化外設ADCx的寄存器   
28
29
  
30
ADC_Cmd(ADC1, ENABLE);//使能指定的ADC1
31
 
        
32
ADC_ResetCalibration(ADC1);//使能復位校準  
33
 
        
34
while(ADC_GetResetCalibrationStatus(ADC1));//等待復位校準結束
35
 
        
36
ADC_StartCalibration(ADC1); //開啓AD校準
37
 
        
38
while(ADC_GetCalibrationStatus(ADC1)); //等待校準結束
39
 
        
40
    //ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的ADC1的軟件轉換啓動功能
41
}
42
43
//得到ADC值
44
//ch:通道值 0~3
45
u16 Get_Adc(u8 ch)   
46
{
47
  //設置指定ADC的規則組通道,一個序列,採樣時間
48
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
49
    //ADC1,ADC通道,採樣時間爲239.5週期    
50
  
51
ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的ADC1的軟件轉換啓動功能
52
 
        
53
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待轉換結束
54
55
return ADC_GetConversionValue(ADC1);//返回最近一次ADC1規則組的轉換結果
56
}
57
58
u16 Get_Adc_Average(u8 ch,u8 times)
59
{
60
u32 temp_val=0;
61
u8 t;
62
for(t=0;t<times;t++)
63
{
64
temp_val+=Get_Adc(ch);
65
delay_ms(5);
66
}
67
return temp_val/times;
68
}  
 
 

      將Get_Adc_Average()拿到的值經過串口輸出在電腦屏幕上,適當調整其數值範圍,刷新時間間隔。我在代碼中就進行了(4093-adcx),(delay_ms(100))相關處理。ide

 
 
 
xxxxxxxxxx
18
 
 
 
 
1
while(1)
2
{
3
 printf("\r\n");
4
 for(i=0;;i++) 
5
        {
6
  for(j=0;j<50;j++)
7
     {
8
                  adcx=Get_Adc_Average(ADC_Channel_1,10);
9
                  printf("%-4d \r",4093-adcx);                
10
                  delay_ms(100);
11
      }
12
             printf("\r\n");
13
             delay_ms(1500);
14
             delay_ms(1500);
15
     }
16
}
17
18
 
 

判斷歌曲就更簡單了,把採樣值存入數組,寫一個條件語句判斷數組的特徵就行了,以下:svg

 
 
 
xxxxxxxxxx
35
 
 
 
 
1
u8 check_song(void)
2
{
3
u16 adcx,adc[35]={0};
4
u8 i,flag=0;
5
printf("\r\n");
6
for(i=0;i<35;i++)//存儲數據
7
   {
8
adcx=CurrentAdc();
9
adc[i]=adcx;
10
if (adc[i]>300)
11
   flag++;
12
printf("%-4d \r", adc[i]);
13
delay_ms(100);
14
15
   }
16
 
        
17
18
 if(flag>32) 
19
           {
20
        printf("flag%d\r",flag);
21
        return 0;//太極拳
22
   }
23
 else
24
   {
25
        printf("flag%d\r",flag);
26
        
27
if((adc[23]<5&&adc[24]<5)
28
 ||(adc[24]<5&&adc[25]<5)
29
 ||(adc[25]<5&&adc[26]<5)
30
 ||(adc[26]<5&&adc[27]<5)
31
 ||(adc[27]<5&&adc[28]<5))
32
   return 1;//健康歌
33
   else return 2;//翻跟頭
34
   }
35
}
 
 

6.總結

a.未知是最大的恐懼,行動是最好的解藥

      一看到比賽項目的時候,臥槽,感受很難,果真網上一查,什麼資料也沒有。。絕望,想放棄。。比賽前半個月,老師開始問進度了,很慌,啥也沒有。但很差意思空手去,因而和隊友總結出上面幾套方案,發現有個保命方案,內心稍微有點底,開始去探索更好的方法。最後搞出來聲音的adc採集,其實如今看看代碼,實在是簡單,慚愧慚愧。其實比賽現場能真正識別出音樂的不超過10個(共30個隊伍),我難人亦難,但我只要去作,山重水複疑無路,柳暗花明又一村。這已超過了很多的人,最重要的是打敗了本身。必定要去作,用心作!函數

b.作項目就跟取西經樣,人生未嘗不是

      準備過程當中是不可能一路順風的,一天一個小自閉,三天一個大自閉,燒板子查不出問題,斷結構從新打印,破代碼運行不出效果,軟件崩潰文件沒保存......簡直懷疑人生。。通常遇到這時候,放下手中的工做,跑個步,洗個澡,吃個飯,歸來仍是少年。作人嘛,最重要的就是心態好啦。

c.持續學習,模仿優秀的人

      現階段自身的能力還不足以輸出不少很好的內容。模仿大佬,總結經驗是比較好的成長路線。慢慢地就會有本身的風格了。加油!

相關文章
相關標籤/搜索