聲音檢測∕聲音放大器(二):計算聲波峰對峰值(振幅大小)的程式

上一篇「模組介紹與自製LM386麥克風聲音放大器」文章使用的程式,對全週聲波沒有太大的用處;應用程式需要的通常是音量大小,也就是波形的振幅大小(或者說峰對峰值)。

振幅、峰對峰值

以右上圖的訊號為例,振幅代表一段時間內的聲波最大(波峰)和最小值(波谷)的差。本實驗採用LM386聲音放大器電路,你可以使用現成的模組,或者依照上一篇文章自行DIY一個。顯示聲波和振幅大小的程式如下:

const int interval = 10;  // 取樣間隔時間,10ms。
unsigned int sample;   // 聲音取樣值
unsigned int amplitude;  // 訊號振幅

void setup() {
  Serial.begin(9600);
}

void loop() {
  unsigned int sigMax = 0;  // 最高峰值
  unsigned int sigMin = 2000;  // 最低峰值
  unsigned long now = millis(); // 當前時間

  // 若目前時間未達間隔時間,則讀取聲音值,並紀錄最低和最高峰值。
  // 這段程式說明請參閱下文。
  while (millis() < now + interval) {
    sample = analogRead(A0);
    if (sample < sigMin) {
      sigMin = sample;
    } else if (sample > sigMax) {
      sigMax = sample;
    }
  }
  
  // 求取訊號振幅
  amplitude = sigMax - sigMin;

  // 輸出原始聲音和振幅值,中間用“,”分隔。
  Serial.print(sample);
  Serial.print(",");
  Serial.println(amplitude);
}

loop()函式當中的while迴圈,用於在設定的時間間隔(10ms)內,不停地讀取類比A0(聲音)值,並且比較出最低和最高峰值。以讀取下圖左、灰底的訊號為例,一開始sigMin變數刻意被設定成很高的值(2000),因此第1個類比輸入值將成為「最低峰值」;sigMax變數也刻意被設定成0,所以第2個類比輸入值將成為「最高峰值」:

求取峰值

當while迴圈執行完畢後,sigMin和sigMax將分別紀錄了這個取樣間隔的最低和最高峰值。

在序列繪圖家顯示多筆資料的波形

把程式上傳到Arduino Uno之後,選擇IDE裡的「工具→序列繪圖家」指令,將能看到原始的聲頻訊號以及振幅(峰對峰)值:

序列繪圖家繪製的訊號圖

在「序列繪圖家」顯示多個波形圖的方法,是把所有數據都輸出在同一行,中間用逗號分隔。底下兩段敘述將可分別繪製A, B和X, Y, X三個變數值:

把所有數據都輸出在同一行,中間用逗號分隔。

LM386麥克風聲音放大電路說明

LM386技術文件有提供幾個聲頻放大器的示範電路,底下是最基本的增益20倍電路如果不需要調整麥克風輸入音量,就不用接10K可變電阻。

增益20倍的電路

輸出端連接250µF電容,可消除混入輸出訊號的直流。這個電容不必是250µF,常見的數值介於100µF~250µF。

消除輸出訊號的直流

輸出端0.05µF和10Ω串連構成的佐貝爾網路濾波器(Zobel Network Filter),用於控制放大器的輸出阻抗並穩定輸出訊號。

第7腳建議接一個1µF~10µF電容,降低放大電路在開關機時,忽然「爆衝」的湧浪電流干擾。

在1和8腳並接一個10µF電容,就變成增益200倍的聲頻放大器。

增益200倍的電路

LM386的電壓增益倍率公式

LM386的電壓增益倍率,可由第1和8腳之間連接的電阻值調整。底下是LM386技術文件第1頁所示的晶片內部等效電路:

LM386晶片內部等效電路

聲頻放大倍率由電路中的三個電阻值決定,根據LM386 Audio Amplifier Analysis(LM386聲音放大器分析)文章推導的公式,當1和8腳不外接任何元件時,放大增益為20:

增益公式

在1和8腳連接一個電容,對交流(聲頻)訊號相當於短路(對直流則是斷路),所以增益值為200:

增益公式

在1和8腳之間串連一個電阻和電容,就可以調整放大增益:

增益N倍的電路

以串接1.2KΩ電阻為例,它將和R1電阻並聯,根據增益計算公式求出的值大約是38.2。

增益公式

欸…根據LM386技術文件第11頁所述,連接1.2KΩ電阻的增益是50…莫非原廠技術文件有誤?

Posts created 467

19 thoughts on “聲音檢測∕聲音放大器(二):計算聲波峰對峰值(振幅大小)的程式

  1. 放大增益為20的計算裡, 應該是2*15000, 而不是2*1500哦~~~應該是筆誤了~~~

  2. 我在進行17張的觸控式電容鍵盤時,無法正常執行,arduino 顯示:”找到無效的程式庫”

    1. 書本光碟裡面有個「程式庫」資料夾,請將裡面的資料夾都複製到「文件→Arduino→libraries」路徑。另請參閱9-16頁的程式庫安裝說明,以及18-4頁的Keypad程式庫說明。還有,請確認控制板有選擇正確。

      thanks,
      jeffrey

    1. 我是用Adobe Flash(现已改名Animate) 软件,搭配鼠标(偶尔用第一代微软Surface Pro平板的Wacom笔)徒手绘制的。

      thanks,
      jeffrey

  3. 使用序列阜通訊時,有方法一次讀取兩個資料,進行動作嗎(讀取a4如此類)

    1. 可以,讀多少資料都沒問題,序列就是把資料依序傳送出去之意。

      thanks,
      jeffrey

    2. 我的意思是:在一程式迴圈哩,可否讀取兩個資料

  4. LCD1602 可以調整可變電阻嗎,還有接線方式是與arduino直接相接嗎,因為我看不清楚螢幕

    1. 可以調整對比,請參閱9-5頁接線,或者選購如18-13的I2C轉接介面。

      thanks,
      jeffrey

    2. 請問:我的型號是LCD1602,他是一種可以直接相接在Arduino上的擴充模組本,並沒有需要接線

    3. 我知道1602,書本第9章和第18章的範例有使用這個LCD。如果你的LCD是原始的並列介面型式,就需要自行外接可變電阻來調整對比(參閱9-5頁電路)。

      thanks,
      jeffrey

  5. 請問一下我有6個LM386的模組
    我想要接6個分別為A0,A1,A2,A3,A4,A5
    目前是可以讀到每一個的聲音訊號波形
    但是我不太清楚該怎麼計算6個個別的聲音振幅
    想請問大大我程式碼應該怎麼修改會比較好?

    1. 每個類比輸入取樣都需要紀錄「取樣值」和「振幅值」,你可以先定義包含這兩個成員的結構(struct),以及儲存6個元素的陣列。接著,把求取訊號振幅的程式寫成函式,逐一讀取A0~A5類比輸入訊號,用自訂結構暫存運算結果,再存入陣列。

      thanks,
      jeffrey

  6. 我去買了電容麥克風+ 1k電阻+ 0.1uf電容
    我照您電路電容麥克風的接法的. 把10k 改成10k的可變電阻+一個1k的電阻(防止我調整到0ohm). 再接0.1uf電容 然後直接接在 stm32f4 discovery的板子的adc. 把訊號電壓跟時間畫出來(透過stm32cubeMonitor功能)
    (還沒有零件把LM386其他部分兜起來, 所以想先量放大前的訊號)

    觀察如下:
    1.調整可變電阻. adc的電位隨著上升下降 (沒有講話的時候的基礎值).
    2.講話的時候,不會改變 offset (講話電壓 – adc DC offset)
    3.另外加0.1 uf 也看起來也是沒甚麼區別. (講話的offset 電壓都差不多)
    4.電容麥克風我直接用電表量. 平常1.1k 如果我對他吹氣 會變成1.1-2k浮動.越大力吹氣阻越高)

    想請問一下
    1.我這樣接, 應該等於把電容麥克風 串接1k電阻.0.1uf 電容.然後量麥克風通過之後訊號 跟地的相對電壓,這樣對嗎?
    2.為什麼接了0.1uf 並不會消除 dc ooset? (電容的原理不是應該穩定之後 不會有直流通過 而且沒有電壓不會有電流 ,I = dV/dt)
    3.您再聲音檢測∕聲音放大器(一) 裡面data訊號有接0.1uf電容 在這篇文章沒有接.理由是因為有接沒接差不多嗎?
    4.dc offset改變(大概從0.1*3.3v ~ 0.8*3.3v)是因為可變電阻的原因嗎?
    5.沒接0.1UF 感覺沒甚麼差,是否因為電容麥克風本身就是電容嗎?還是其實有差只是我沒發現..
    6. 250uf 照您文章的說法 ,會把DC offset變成0.如果我是要接到ADC分析,是否我要把這個電容拿掉?否則我量不到負電壓.

    抱歉我是資工 所以很多電路相關不懂 問題很奇怪的話請多包涵 我有再努力看資料把這部分補起來了.@@..

    1. 一般市售的電容麥克風元件,內部不是單純的電容結構,而是內含FET元件,像這一種麥克風元件(Electret microphone)

      即便是單純的電容式麥克風元件,它的輸出就是隨音量大小波動的電壓,測量它的電阻值是沒有意義的。

      放大器的輸出訊號不會有負值,因為它的電源是正電源和接地,輸出訊號只會落在這個範圍。

      thanks,
      jeffrey

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top