【Raspberry Pi】ECMで音センサつくってみた

【Raspberry Pi】ECMで音センサつくってみた
【Raspberry Pi】ECMで音センサつくってみた

こんなこと、やります。

  • エレクレットマイク(ECM)を使って音センサの制作
  • 交流信号を直流信号へ変換する
  • ADコンバータを使ってRaspberry Piで音を認識させる
  • 音量に合わせてLEDを点灯させる

Raspberry Piで音が感知できるように実験してみました。この記事では音センサの作り方をメインにご紹介します。音センサは交流回路の勉強にもなって楽しいので、ぜひ挑戦してみてください。

こちらの動画のように、Raspberry Piと自作のECMマイクを使って、音量に合わせてLEDを点灯させるサウンドレベルインジケーターのようなことやっていきます!

音センサの概要

音センサを実現するための概要を説明します。

音センサの仕組み

今回製作した音センサの仕組みは次のようになります。

graph LR A[ECM] --> B[AMP] B --> C[AC-DC] C --> D[ADC] D --> E[Raspberry Pi]

  1. マイクロフォン(ECM)で音声を集音
  2. アンプ回路で音声を増幅
  3. 音声の交流信号を直流信号に変換
  4. 直流信号をADコンバータでデジタル変換
  5. SPI通信でデジタル信号をRaspberry Piで読み取る

エレクレットマイク(ECM)

音を感知するためのECMマイクは、以前に自作したものを使用します。

作るのが面倒な方は、ECMとアンプがモジュール化されたものを使うと便利です。

また、Raspberry Piはお好きなものをお使いください。

マイクアンプの製作

ECMで集音した信号は、電圧が数十mV程度と小さすぎます。よって、そのままでは使えないのでアンプを通して十分大きな信号に変換してあます。

マイクアンプを通して微弱信号を増幅させる
マイクアンプを通して微弱信号を増幅させる

非反転増幅回路

オペアンプを使って、非反転増幅回路でマイク信号を増幅させます。この回路では、1kΩと470kΩの抵抗によって470倍の信号増幅が可能です。

マイクアンプの電子回路図
マイクアンプの電子回路図

▼ 非反転増幅回路の詳しくはこちら。

今回は音質に拘らないので、NJM4558やTL072などの安価なオペアンプで十分です。

増幅回路の波形を観察

ファンクションジェネレータでサイン波を鳴らし、マイクで集音して増幅回路に通してみました。その時の入力側と出力側の波形のようすです。

マイクアンプの増幅をオシロスコープで観察
マイクアンプの増幅をオシロスコープで観察

写真のように10mVp-p程度だったECM出力の電圧が、アンプを通したことで4Vp-p程度まで増幅されました。ただし、過増幅のために波形は歪んでいます。人間の耳で聞けば割れた音になってますが、センサの用途ですのでこれで問題ありません。あくまで音を感知できればいいので、音質は気にしなくて良いです。

発振器のすすめ

ところで、こういった低周波の実験には「発振器」があると便利です。発振器は「ファンクションジェネレータ」や「オシレーター」とも呼ばれます。

▼ ファンクションジェネレータは自作することも可能です。

交流信号を直流信号に変換する(AC-DC)

マイクアンプで増幅された信号は、GNDの0Vを中心にプラスマイナスへ振れる交流信号です。よって、このままではADコンバータに入力できません。そこで、交流信号を直流信号に変換するAC-DCコンバータを作っていきます。

作ると言っても、とても簡単です。つぎのように半波整流回路を利用します。

AC-DCコンバータの回路

半波整流でAC-DC変換する電子回路図
半波整流でAC-DC変換する電子回路図

このAC-DCコンバータの回路の仕組みはつぎのとおりです。

  1. 0Vを中心に上下する交流信号の「プラス側の信号のみ」をダイオードで取り出す
  2. ダイオードを通過した信号は、1uのコンデンサに蓄電され、そして100kΩの抵抗へ流れていく
  3. 出力が3.3V以上の電圧にならないよう、ツェナーダイオードでリミッターをかける

AC-DC変換後の波形はこんな感じのものになります。

ACからDCへ変換する説明
ACからDCへ変換する説明

▼ ダイオードとツェナーダイオードは、小信号用のものをお使いいただけます。

なお、ダイオードを通過した信号はOUTへも流れますが、OUT先の入力抵抗(入力インピーダンス)は非常に高いと想定しているため、1uに蓄えられた電荷のほとんどが100kΩの抵抗へ流れることになります。このことは、インピーダンスについて学ぶと理解できますので、詳しく学びたい方はこちらの書籍をおすすめします。(私のバイブルです)

AC-DCコンバータの実際

こちらの写真はマイクアンプから出力された信号と、「ダイオードのみ」を通した時の信号をオシロスコープで観察したものです。

ダイオードのみを通した時の信号をオシロスコープで観察
ダイオードのみを通した時の信号をオシロスコープで観察

ダイオードを通すと、プラス側の信号のみを取り出すことができます。またダイオードの向きを反対にすれば、マイナス側の信号のみを取り出せます。

ダイオードでは順方向電圧があり、ダイオードを通った信号は0.6Vほど電圧が低くなります。上の写真からもそのようすが観察できます。 つまり、0.6V以上の入力信号でないとこの回路は動作しません。ですから、アンプ回路でECMの微弱信号を大きな電圧に増幅する必要があったのですね。

もしも0Vから動作させたい場合は、理想ダイオード回路を使って実現できます。詳しくはこちらをご覧ください。

理想ダイオード回路は、本格的なVUメーターやdB測定器などで精密な測定器に使われたりします。今回の用途では精度は求めませんので、簡易的な方法でAC-DCコンバータを実現させました。 この簡易的なAC-DCコンバータ回路は、他にも土壌センサやコンプレッサーなどのエンベロープ発生に使われてます。

コンデンサ(1u)後の抵抗値(100k)を変えることで、信号による追従速度を変化させられます。たとえば抵抗値を大きくすると、コンデンサに貯まった電荷が逃げにくくなるため、音声信号の追従が遅くなります。ここら辺は実際に回路を組んで調整します。

ADコンバータ

さて、AC-DCコンバータで直流になったアナログ電圧をRaspberry Piで読み取るためには、ADコンバータが必要です。ADコンバータはアナログ信号をデジタル信号に変換するものです。

ADコンバータは、SPIで通信する2チャネル・8ビットのMAX1118を使いました。MAX1118の使い方はこちらの記事をご覧ください。

他にもADコンバータはいろいろあります。

お好きなADコンバータをお使いいただけますが、Raspberry Piで使う場合はI2CまたはSPI接続のADコンバータが簡単です。

音量に合わせてLEDを点灯させるPythonプログラム

自作のECM音センサ
自作のECM音センサ

ここまで準備ができたところで、さいごにRaspberry Piを使って音センサを使ってみます。音量に合わせてLEDを点灯させるPythonプログラムを書いてみました。Raspberry PiのGPIOに、1kΩの抵抗を介してLEDを5個配線してます。

py
# -*- coding: utf-8 -*-
import spidev
import time
import RPi.GPIO as GPIO

LED0 = 4 # GPIO番号
LED1 = 14
LED2 = 15
LED3 = 17
LED4 = 18

Vref = 3.336  # Raspberry Piの3.3V電源をテスターで実測

GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.OUT)  # CNVST

GPIO.setup(LED0, GPIO.OUT)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)

spi = spidev.SpiDev()
spi.open(0, 0)  # bus0,cs0
spi.no_cs = True  # CSを使わない
spi.max_speed_hz = 1000000  # 1MHz
spi.bits_per_word = 8

def sendCNVST(CH):
    if CH == 0:
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)
    elif CH == 1:
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)
        GPIO.output(8, GPIO.HIGH)
        GPIO.output(8, GPIO.LOW)

def getVolts():
    adc = spi.xfer2([0x00])
    return adc[0] / 255.0 * Vref

try:
    while True:
        sendCNVST(0)
        v0 = getVolts()
        # print(v0)
        
        if v0 > 0.75:
            GPIO.output(LED0, GPIO.HIGH)
            GPIO.output(LED1, GPIO.HIGH)
            GPIO.output(LED2, GPIO.HIGH)
            GPIO.output(LED3, GPIO.HIGH)
            GPIO.output(LED4, GPIO.HIGH)

        elif v0 > 0.6:
            GPIO.output(LED0, GPIO.HIGH)
            GPIO.output(LED1, GPIO.HIGH)
            GPIO.output(LED2, GPIO.HIGH)
            GPIO.output(LED3, GPIO.HIGH)
            GPIO.output(LED4, GPIO.LOW)
        elif v0 > 0.45:
            GPIO.output(LED0, GPIO.HIGH)
            GPIO.output(LED1, GPIO.HIGH)
            GPIO.output(LED2, GPIO.HIGH)
            GPIO.output(LED3, GPIO.LOW)
            GPIO.output(LED4, GPIO.LOW)
        elif v0 > 0.3:
            GPIO.output(LED0, GPIO.HIGH)
            GPIO.output(LED1, GPIO.HIGH)
            GPIO.output(LED2, GPIO.LOW)
            GPIO.output(LED3, GPIO.LOW)
            GPIO.output(LED4, GPIO.LOW)

        elif v0 > 0.15:
            GPIO.output(LED0, GPIO.HIGH)
            GPIO.output(LED1, GPIO.LOW)
            GPIO.output(LED2, GPIO.LOW)
            GPIO.output(LED3, GPIO.LOW)
            GPIO.output(LED4, GPIO.LOW)
        else:
            GPIO.output(LED0, GPIO.LOW)
            GPIO.output(LED1, GPIO.LOW)
            GPIO.output(LED2, GPIO.LOW)
            GPIO.output(LED3, GPIO.LOW)
            GPIO.output(LED4, GPIO.LOW)

        time.sleep(0.01)

except KeyboardInterrupt:
    spi.close()
    GPIO.output(LED0, GPIO.LOW)
    GPIO.output(LED1, GPIO.LOW)
    GPIO.output(LED2, GPIO.LOW)
    GPIO.cleanup()

▼ SPI通信でデータを読み取る関数spi.xfer2は、こちらの記事で詳しく解説してます。

▼ 作った音センサのようすは、こちらの動画をご覧ください。 音に反応するセンサーを作ってみた!ラズパイ - YouTube

関連記事

 
最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

この記事で紹介した商品

人気のArduino互換機
Arduinoで人気の周辺パーツ
あると便利な道具
Arduinoのオススメ参考書

▼ Arduino初心者向きの内容です。ほかのArduino書籍と比べて図や説明がとてもていねいで読みやすいです。Arduinoで一通りのセンサーが扱えるようになります。

▼ 外国人が書いた本を翻訳したものです。この手の書籍は、目からうろこな発見をすることが多いです。

▼ Arduinoの入門書を既に読んでいる方で、次のステップを目指したい人向きの本です。C言語のプログラミングの内容が中心です。ESP32だけでなく、ふつうのArduinoにも役立つ内容でした。

関連記事