概要
手を叩いて(clapping)スイッチをON/OFFできないかと考えてWEB上で製作例など検索してみたが日本語では以外とすくない。今回は以下のようなプロセスを考えてみた。
1) コンデンサマイクで手叩き音を拾う。
2) アンプで増幅する。
3) CdS-LEDアナログ・フォトカプラ(MI0202CL)とインバータでパルスの波形をきれいにする。
4) それを12F629で処理してLEDを点灯させたり、SSR(Solid State Relay)を駆動したりなどの仕事をさせる。
本電子工作の最大の特徴はPICBasic ProのPULSINという波幅を計測するコマンドを使って一定幅のパルスのみ選択して利用する点である。
回路図
マイクからの入力を増幅する回路はWEB上に公開されているもの(例えば、http://homepage3.nifty.com/mitt/pic/pic6_03-1.html さん)を一部使わせて貰った。増幅されたパルスを12F629で処理するのに適する様に調整するために、パルスの大きさを抵抗値に変換しバッファーのような働きをするCdS-LEDアナログ・フォトカプ(LEDの輝度変化がCdSで抵抗値変化に変換される)を通し、さらにインバータ(4069)を通すと、比較的ノイズのすくないきれいな波形のパルスが得られる。図中のVR1とVR2でそれぞれ感度とパルス波幅を調整する。
*VR1値を大きくすると(e.g.33K)感度が上がり、口で”アー”と言った雑音とみなす音声(マイクから20cm位置で65dB位)もパルスとして拾いやすくなる。1K−220W位では容易に音声を拾わなくなる。
*VR2値を大きくすると(e.g.33K)、パルスの波幅が広がり“手叩き音”を拾わなくなり、”アーという音声”を拾いやすくなる。3.3K位に小さくすると手叩き音で波幅が11ms程になり”アーという音声”を拾いにくくなる。
回路全体で5−6mAほど消費する。したがって単三アルカリ電池4本用いたとすると、700mAhとされているので6mAではどれほど持つか計算してみると、700mAh/6mA=117hとなり117h/24h=4.9日となり電池による駆動は実用的でない。差し当たってDC5VのACアダプタを使うことにした。
実験中
パルスの波形 (Wave form of pulse)
上記の回路図上のポイントA, B ,Cで”手叩き音”と“アーという音声”のパルスの波形をオシロ(PicoScope 2105)で測定してみた。
1) 回路図の中でAというポイントでその先の配線を切った状態で、マイクから20cm位の距離で”手叩き音”と“アーという音声”の各波形をオシロで拾ったものである。左手の2本が手叩き音で、鋭利な槍状のパルスで高さ4V弱で幅が4−5msあり、その後がアーという音声に対応する。幾つもの槍状のパルスよりなり幅は330msであった。これらのパルスをソフト的に処理すのは難しい。Point (A)
2) 同様にBでその先の配線を切った状態で測定したものである。 左手の3本のパルスは約0.7秒ほどの間隔での手叩き音で下向きに発生する。ピークの深さ2V弱、波形からPULSINで計測できるかどうか分からない。それらの後の大きい下向きのパルスはアーという音声に対応し、波幅は350msもある。それでも上記1)に比べノイズの少ないスムーズな波形になっていることが分かる。Point (B)
3) 同様にCでその先の配線を切った状態で測定したものである。左手の4本のきれいなパルスは約0.5秒間隔での手叩き音に対応し、高さ5V、波幅が10−15msである。その後の大きなパルスはアーという音声に対応し波幅は300msもある。Point (C)
4) 上図の手叩き音4本の内の1本を拡大したものである。大変きれいなパルスであることが分かる。 One enlarged clap pulse of Point (C)
5) 一方、“アー”とか“アオー”とかいう音声をマイクが拾うと回路図のCポイントでこんなパルスが発生する場合がある。下述するプログラムではこのようなパルスを手叩き音として認識しないように一応工夫してある。すなわち、左から2番目の5V近い高さのピーク(波幅も大切)を手叩き音と認識したとすると、その後30ms毎に3回ピーク高さが“H”であるかチェックし、さらに150ms後にピーク高さが”L”であるかチェックして設定した拒否条件に合致すればこのパルスを手叩き音と認識しない。音声や雑音によってこのような複雑なパルスが発生するのでソフト的な処理は簡単ではない。
この手叩き音スイッチの動作
初めに手を叩くとスイッチが入り、次に手を叩くとスイッチが切れる。その動作を繰り返す。
プログラム
手叩き音を会話などの雑音といかに区別して12F629に取り込むかがプログラム作成の要である。プログラムの流れやポイントは次のようである。
1) マイクの出力をアンプで増幅し、その後2つのデバイスでパルスの波形を調整しPULSINを使って12F629に取込み、その値Wをメモリに保存。
“Pulsin, GPIO.0, 1, W” はGPIO.0より“H”パルスを取り込みWに保存せよという意味で、”H”に達しない(<2V?)パルスは取り込まない。
2) その値Wが任意に設定した波幅範囲の中に入っているどうかを調べ、入っていれば手叩き音として認知してLED(G)を点灯させたり、SSRを駆動させたりする。
もし入っていなければ先頭に戻って待つ。
3) Nextaction ..... GOTO Peakwaitloopの中で行っていることは: 上の5)で述べたように、一定の波幅範囲の中に入る波幅の小さいパルス(手叩き音として認知される)に付属して幅広いパルスが来るような場合を想定して、そのようなパルスを除こうというものである。30ms待ってパルスの高さをチェックして“H”ならプログラムの先頭(Peakwaitloop)へ、”L”ならもう2回30ms待って同じことを切り返し、次いで150ms待ってパルスの高さをチェックして“L”ならJUMPへ、”H“ならプログラムの先頭へ戻る。
4) TOGGLEコマンドを使って手を叩く毎にON/OFFを繰り返すようにした。
5) 設定条件に合った手叩き音(“H”で波幅6−25ms)を受け取ると200ms間LED (GPIO.5)が点灯し、そしてON/OFF状態(LEDorSSR var GPIO.4)が反転する。
'********* プログラム ************
'SoundSensorW2.bas - 2010.4.8 worked
'Clapping produces a sharp peak to be read by 12F629.
'******** ピン接続 ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input
'Pin 4: input
'Pin 2: output - to LED (R) via R
'Pin 3: output - to LED (G) via R or SSR (Solid State Relay)
'******** プログラム本体 ********
CMCON=7 'Comparator off
TRISIO=%001001 'all outputs except GPIO.0 & 3
W1 var WORD 'storage for peak width
Peakin var GPIO.0 'Input from invertor(4069)
LED var GPIO.5 'Indicator when a pulse is accepted
LEDorSSR var GPIO.4 'For driving LED or SSR
LEDorSSR=1
Peakwaitloop:
Peakin=0
LED=0
Pulsin Peakin, 1, W1 'Read a high peak and store it in W1 ここでパルスを取り込む
If (600=<W1) and (W1<2500) Then Nextaction 'Pulse width range 6ms=<W1<25ms 取り込んだパルス幅を6−25msに限定/この設定大切
GOTO Peakwaitloop
Nextaction: 以下の9行で雑音としての多ピークパルスを除く作業をする (上述の5)に対応)
Pause 30 'Wait 30ms 30ms間隔で3回パルスの高さが“H”であるかどうかチェック
If Peakin=1 then Peakwaitloop
Pause 30
If Peakin=1 then Peakwaitloop
Pause 30
If Peakin=1 then Peakwaitloop
Pause 150 'Wait 150ms 150ms待ってパルスの高さが“L”であるかどうかチェック
If Peakin=0 then Jump
GOTO Peakwaitloop
Jump:
High LED 'Turn on LED
Toggle LEDorSSR TOGGLEコマンドでJumpに到達する毎にLEDorSSR(GPIO.4)を反転させる(=LED(G)またはSSRをON/OFFさせる)
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Peakwaitloop
End
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's configurations:
'FOSC - INTOSC; WDTE - Enable; Power-up Timer - Disable
'MCLRpin – Input Pin ; BODEN - Enable; CD - Disable; CDP - Disable.
結論·余談
1) 完全に“手叩き音”だけに反応するON/OFFスイッチを作るのは難しい。
2) 改良プログラム'SoundSensorW2.bas のもと、VR1=220W、VR2=3.3KWで、マイクから10−20cmの距離で手叩き音にかなり確実に反応するようになった。
3) 雑音にも大分強くなったが、マイクから20cm位の距離で、大きい声(>75dB)で“アオー”などと発声すると反応する。
4) 抑揚の少ない連続的なアーという雑音(音声を含め)には反応しにくい。充電池式携帯掃除機の音(ガーという連続音)には80dBの音圧でも反応しない。
5) If (600=<W1) and (W1<2500) Then Nextactionの範囲設定とNextaction ..... GOTO Peakwaitloop部分が最重要。範囲6−25msはオシロで何度も測定して決定。Nextaction ..... GOTO Peakwaitloop部分は30ms毎のチェック繰り返し回数を2回から3回に増やし、“L”チェックの100msを150msに変えたら手叩き音の認識精度が大変良くなった。
6) 新しいmelabs U2 Programmerは素晴らしい。Hexファイルをいちいち導入する必要がない。しかも処理が速い。USBなので電源も要らない。
7) 今回の材料費1000円ちょっと。
8) 単なる音圧センサにしては回路がちょっと複雑かも、しかも電流消費が5−6mAで電池駆動には向かない。考えてみましょう!
改良したプログラム(2010.4.10)
上記のプログラム SoundSensorW2.bas のロジックを変えて手叩き音の認識精度が大きく向上した。つまり、ノイズに強くなった。もちろん完全ではない。
1) マイクから20cm位の距離で70dBの“アー”や“アオー”という音声にはほぼ反応しなくなった。
2) 手叩き音の受け入れパルス幅範囲を8−25msと狭くしたので、手の平同士を叩きあう時に発生するこもり気味の音(波幅が広い)により確実に反応するようになった。
'********* プログラム ************
'SoundSensorW3.bas - 2010.4.10 worked more resistant to noise
'Clapping produces a sharp peak to be read by 12F629.
'******** ピン接続 ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input
'Pin 4: input
'Pin 2: output - to LED (R) via R
'Pin 3: output - to LED (G) via R or SSR (Solid State Relay
'******** プログラム本体 ********
CMCON=7 'Comparator off
TRISIO=%001001 'all outputs except GPIO.0 & 3
W1 var WORD 'storage for Peak1 width
D1 var byte ‘data storage for 1 or 0
D2 var byte
D3 var byte
D4 var byte
Peakin var GPIO.0 'Input from invertor
LED var GPIO.5 'Indicator when a pulse is accepted
LEDorSSR var GPIO.4 'For driving LED or SSR
LEDorSSR=1
Peakwaitloop:
Peakin=0
LED=0
W1=0
Pulsin Peakin, 1, W1 'Read a high peak and store it in W1 ここでパルスを取り込む
If (800=<W1) and (W1<2500) Then Nextaction 取り込んだパルス幅を8−25msに限定
GOTO Peakwaitloop
Nextaction:
Pause 30 'Wait 30ms ここから30ms間隔で3回パルスの”H” or “L” を読んでD1, D2, D3に保存
D1=Peakin 'Read Peakin and store it in D1
Pause 30
D2=Peakin
Pause 30
D3=Peakin
Pause 200 200ms後にパルスの”H” or “L” を読んでD4に保存
D4=Peakin
If (D1+D2+D3)>=2 and D4=0 then Peakwaitloop (D1 + D2 + D3)が2に等しいか大きく、さらにD4が“L”なら、パルスはノイズなので先頭に戻る
High LED 'Turn on LED
Toggle LEDorSSR
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Peakwaitloop
End
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's configurations:
'FOSC - INTOSC; WDTE - Enable; Power-up Timer - Disable
'MCLRpin – Input Pin ; BODEN - Enable; CD - Disable; CDP - Disable.
さらに改良したプログラム(2010.4.12)
上記のプログラム SoundSensorW3.bas のロジックを変えて手叩き音の認識精度が大きく向上し、さらにノイズに強くなった。ほぼ完璧に近い?
1) 手叩き音を受け付ける条件「“H”ピークで波幅8−25ms」にマッチするパルス以外を受けつなくするように、候補パルスの前後の一定時間”L”の状態にあることを受付け条件に加えた。
2) 勿論、手叩き音以外に「“H”ピークで波幅8−25ms」にマッチするパルスであればシステムは反応する。しかし“アー”とか“アオー”という音声には全く反応しなくなった。
3) 前のプログラム同様に、手の平同士を叩きあう時に発生するこもり気味の音により確実に反応する。
このプログラムでは、下図のように候補パルス(波幅14ms)の前3個所 Y1、Y2、Y3 (20ms間隔)で“L”であることを確かめ、候補パルスの後ろ6個所Y4、Y5、Y6、Y7、Y8、Y9(10ms間隔)で“L”であることを確かめて、そしてすべて“L”であるとき候補パルスは手叩き音として認識される。これでノイズとしての多ピークパルスや幅広パルスは除かれる。意外と単純なロジlックであるが効果はてきめんであった。
'********* プログラム ************
'SoundSensorW4.bas - 2010.4.11 worked very resistant to noise
'Clapping produces a sharp peak to be read by 12F629.
'******** ピン接続 ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input
'Pin 4: input
'Pin 2: output - to LED (R) via R
'Pin 3: output - to LED (G) via R or SSR (Solid State Relay)
'******** プログラム本体 ********
CMCON=7 'Comparator off
TRISIO=%001001 'all outputs except GPIO.0 & 3
W1 var WORD 'storage for Peakin width
PD1 var byte 'storage for PD1 (1 or 0)
PD2 var byte
PD3 var byte
D1 var byte 'storage for D1 (1 or 0)
D2 var byte
D3 var byte
D4 var byte
D5 var byte
D6 var byte
Peakin var GPIO.0 'Input from invertor
LED var GPIO.5 'Indicator when a pulse is accepted
LEDorSSR var GPIO.4 'For driving LED or SSR
LEDorSSR=1
Peakwaitloop:
Peakin=0
LED=0
W1=0
PD1=Peakin ここから7行で3回20msの間隔を置いて候補パルスの前が“L”であることを確認している
Pause 20
PD2=Peakin
Pause 20
PD3=Peakin
If (PD1+PD2+PD3)=0 then Nextaction すべてが“L”だったら次に行く
GOTO Peakwaitloop
Nextaction:
Pulsin Peakin, 1, W1 'Read a high peak and store it in W1 ここで候補パルスを読み込んで8−25msにあるかどうかをチェック
If (800=<W1) and (W1<2500) Then Nextaction1
GOTO Peakwaitloop
Nextaction1:
Pause 10 'Wait 10ms ここから14行で6回10ms間隔で上の条件をパスした候補パルスの後が“L”であることをチェック
D1=Peakin 'Read Peakin and store it in D1
Pause 10
D2=Peakin
Pause 10
D3=Peakin
Pause 10
D4=Peakin
Pause 10
D5=Peakin
Pause 10
D6=Peakin
If (D1+D2+D3+D4+D5+D6)=0 then Jump 上記の条件をパスしたらJump以下の動作を、そうでなければ先頭へ戻る
Goto Peakwaitloop
Jump:
High LED 'Turn on LED
Toggle LEDorSSR
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Peakwaitloop
End
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's configurations:
'FOSC - INTOSC; WDTE - Enable; Power-up Timer - Disable
'MCLRpin – Input Pin ; BODEN - Enable; CD - Disable; CDP - Disable.
Clap ON/OFF Switch (Electronic Project No.40 English Version)
Using PICBasic Pro (version 2.50A), 12F629 and various other components as shown in the circuit below, a clap ON/OFF switch was built. One of the features in this project is the use of PBP’s PULSIN command for reading the width of clap pulse and storing it as data. The other features and matters to note are:
1) As TOGGLE command is also used, the first clap turns on LED (Green) or SSR and the second clap turns them off, repeating the same step.
2) The output from the microphone is amplified by LM358N, then converted to a clean “H” pulse through CdS-LED analog-photocoupler (a kind of buffer?) and inverter 4069, which is introduced into 12F629 through GPIO.0 for processing.
3) The wave forms of pulse at Points (A), (B) and (C) in the circuit diagram (measured by cutting the connection) generated when hands are clapped are shown respectively in 1) , 2) and 3) under Wave form of pulse described in the above section (located in the Japanese language section).
4) The system consumes 5 - 6 mA of current at 5 V, so it is not suitable for battery operation.
5) Though the system best responds to a clean “H” pulse with a width of 8-25ms and is quite resistant to noise pulses, it may respond to any pulse having the similar shape and width in principle.
6) VR1: Sensitivity adjustment, VR2: Wave width adjustment
Typical clap pulse (width: 14ms, height: “H”). Before and after it, the level of voltage (“H” or “L”) is checked at 9 points (Y1-Y9). If the level at all 9 points is found to be “L”, the pulse is acknowledged as a genuine clap pulse. This process is critical in differentiating a clap pulse from other noise pulses.
Program
The program is simple but works well.
'********* Program ************
'SoundSensorW4.bas - 2010.4.11 worked very resistant to noise pulses
'Clapping produces a sharp peak to be read by 12F629.
'******** Pin connection ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input
'Pin 4: input
'Pin 2: output - to LED (R) via R
'Pin 3: output - to LED (G) via R or SSR (Solid State Relay)
'******** Main body of program ********
CMCON=7 'Comparator off
TRISIO=%001001 'all outputs except GPIO.0 & 3
W1 var WORD 'storage for Peakin width
PD1 var byte 'storage for PD1 (1 or 0)
PD2 var byte
PD3 var byte
D1 var byte 'storage for D1 (1 or 0)
D2 var byte
D3 var byte
D4 var byte
D5 var byte
D6 var byte
Peakin var GPIO.0 'Input from inverter
LED var GPIO.5 'Indicator when a pulse is accepted
LEDorSSR var GPIO.4 'For driving LED or SSR
LEDorSSR=1
Peakwaitloop:
Peakin=0
LED=0
W1=0
PD1=Peakin ‘In the following 7 lines, whether the voltage level at 3 points (20ms interval between them) before a candidate pulse is “L” is checked.
Pause 20
PD2=Peakin
Pause 20
PD3=Peakin
If (PD1+PD2+PD3)=0 then Nextaction ‘If the voltage level at all the points is “L”, go to Nextaction..
GOTO Peakwaitloop
Nextaction:
Pulsin Peakin, 1, W1 'Read a high peak and store it in W1 ‘The candidate pulse is read by Pulsin, and if it falls in a range of 8−25ms, go to Nextaction1.
If (800=<W1) and (W1<2500) Then Nextaction1
GOTO Peakwaitloop
Nextaction1:
Pause 10 'Wait 10ms ‘In the following 14 lines, whether the voltage level at 6 points (10ms interval between them) after the candidate pulse is “L” is checked.
D1=Peakin 'Read Peakin and store it in D1
Pause 10
D2=Peakin
Pause 10
D3=Peakin
Pause 10
D4=Peakin
Pause 10
D5=Peakin
Pause 10
D6=Peakin
If (D1+D2+D3+D4+D5+D6)=0 then Jump ‘If the voltage level at all the points is “L”, go to Jump.
Goto Peakwaitloop
Jump: ‘Turns on LED or drives SSR.
High LED 'Turn on LED
Toggle LEDorSSR
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Peakwaitloop
End
'******** End of program ********
'Note:
'melabs U2 Programmer's configurations:
'FOSC - INTOSC; WDTE - Enable; Power-up Timer - Disable
'MCLRpin – Input Pin ; BODEN - Enable; CD - Disable; CDP - Disable.
$$$$$$$$$$$$$$$$$$$$$$$ 備忘録−上の電子工作40と全く関係ないことなど (2010.4.18) $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
秋月で昔買ったCURITYという携帯式のVoice Recorder を持っていて、それなりに重宝しているがCR2016といる薄いリチウム電池(3V, 2枚使用)があまり持たない。そこで、容量の大きい単5サイズの12Vアルカリ電池(A23S, Golden Power)を外付けしてみることにした(秋月入手、そのケースは千石で)。このVoice Recorderを調べてみると、(1)6Vで動作し、4Vまでは音割れするが何とか動作する。(2)待機時の消費電流は8−10mA(at 6-5V)と大変低い。(3)音声の再生時の消費電流は35−30mA(at 6-5V)ほどであった。
Voice Recorderは最大6Vで動作するので、電池の12Vの電圧を下げないといけない。そこで10mAと電流消費の小さいXC6202P502TB (最大入力電圧が20V, 出力5Vで150mA)というCMOS 3端子レギュレータ(¥50)を使うことにした。そして下の回路図のように12V電池のケースに他の部品を一切付けずにハンダ付けした。Voice Recorderの方は、オリジナル電池を外し、それを保持していた+、- 端子に外部電池につなぐ線(2本)をハンダ付けした(熱注意)。テストの結果、高くクリヤーな音声が再生されるようになった。電池がどれ位持つか楽しみである。下に電池を取り付けたVoice Recorderの写真を示す。
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$