概要
電子工作42で超音波センサに関わったついでに今回は3つの超音波パターンを短距離間送って受け取る実験をしてみた。
実験の要点は:
(1) 3個の超音波パターンを送るプログラムの作成。
(2) 受け取る側でそれらを個々に区別認識するプログラムの作成。
(3)
実際に動作するかどうかの検討。
回路
発信器
下に3つの超音波パターン発生器の回路図を示す。 その目的のために3つのInput SWが導入してある。個々のInput SWから下述するよな違った超音波パターンが発生する。
受信器
この回路では送信側のInput SW1が押されるとLED1が点灯し、Input SW2が押されるとLED2が、さらにInput SW3が押されるとLED3が点灯する。個々のInput SWをもう一度押すと消灯する。押す毎にこの反転を繰り返す。
実験中―左のボードが発信側、右が受信側。 一番下に送信と受信用の超音波センサが向かい合っている。送信距離は電子工作42で述べたように短い。
左のボード下部の3つのSWに反応して一部点灯している赤い3個のLEDが右側のボード上に見える。修理のため海外旅行してきた愛用のオシロも右手に見える。
波形の解析
上記3つの超音波パターン発生器の3つのInput SW1、Input SW2、 Input SW3を押すとそれぞれ下に示すようなパターンが受け側の12F629のGP0(Pin7)に入力される(このポイントでオシロで測定した)。
(波形1) Input SW1を押した時に発生するパターンで、4本の方形波がほぼ50%のデュティー比できれいに展開されている。1パターンの全幅は約300ms
で、各方形波の幅と2つの方形波間の間隔はともに40ms前後である。
(波形2) Input SW2を押した時に発生するパターンで、2番目の方形波が欠けている。
(波形3) Input SW3を押した時に発生するパターンで、3番目の方形波が欠けている。
(波形4) 3つの異なるInput SWを次々と押した時に発生するパターンで、上に示し3つの波形パターンの5分の1のスケールで表示してある。
プログラム
3つの超音波パターン発生器用プログラム
送り手側のこのプログラムの概要は以下のようである。
1) 3つのInput SWのいずれから入力があったらLoop1, Loop2, Loop3などに進む、なければ待つ。
2) 例えは、Loop1へ飛んだ場合、H(40KHz)を5ms、Lを80ms発生させるサブルーチンを使ってHHHH波パターンを発生させる。
3) Loop2とLoop3に飛んだ場合も同様にしてHLHH波とHHLH波パターンをそれぞれ発生させる。
'********* プログラム ************
'UltraSoundPWM40KHz3.bas 2010.6.9 3 SWs for 3 signal patterns
'PIC16F628A with 4MHz internal
'******** ピン接続 ************
'Pin 14 - Vdd (5V)
'Pin 5 - Vss (GND)
'Pin 4 - /MCLR (Reset) connected to Vdd via 4.7K
'Pin 6 - RB0 connected to Input SW1
'Pin 7 - RB1 connected to Input SW2
'Pin 8 - RB2 connected to Input SW2
'Pin 9 - RB3 connected to Tr driving a ultrasonic sensor (T40-16)
'******** プログラム本体 ********
CMCON=7 'No comparator
VRCON=0 'A/D voltage reference disabled
TRISB=%11110111 'RB3 - PWM output
TRISA.5=1 'Reset
PR2=24 'Set PWM for 40 KHz (25:38KHz) ここで40KHz波発生のための設定をする
CCPR1L=13 'Set PWM for 50% duty cycle
CCP1CON=%00001100 'PWM mode selection =12 in decimal
T2CON=%00000100 'Timer2 ON + 1:1 prescale
InputSW1 var PORTB.0 'Input SW1
InputSW2 var PORTB.1 'Input SW2
InputSW3 var PORTB.2 'Input SW3
InputSWLoop:
Pause 500 'Giving 500ms-space between 3-peak pulses when Input SW was kept pressed パターン間の間隔として500msを設定
CCP1CON=0 'PWM OFF
If InputSW1=0 then Loop1 ‘SWエントリルーチン
If InputSW2=0 then Loop2
If InputSW3=0 then Loop3
Goto InputSWLoop
Loop1:
Gosub H5L80OnOff 'Produce 4 peaks 4つの方形波を含むHHHH波パターンを発生させる
Gosub H5L80OnOff
Gosub H5L80OnOff
Gosub H5L80OnOff
Goto InputSWLoop
Loop2:
Gosub H5L80OnOff 'Produce 3 peaks 3つの方形波を含むHLHH波パターンを発生させる
Pause 5 'No peak section
Pause 80
Gosub H5L80OnOff
Gosub H5L80OnOff
Goto InputSWLoop
Loop3:
Gosub H5L80OnOff 'Produce 3 peaks 3つの方形波を含むHHLH波パターンを発生させる
Gosub H5L80OnOff
Pause 5 'No peak section
Pause 80
Gosub H5L80OnOff
Goto InputSWLoop
H5L80OnOff: 'Subroutine High5ms + Low80ms. Two values 5ms and 80ms were decided on a trial and error basis while checking a pulse pattern at Point (C). – GP0 (Pin7) HとLを作るサブルーチン
CCP1CON=12 'PWM ON for 5ms PWMを5ms ON この5msと80msの値は、受信側のポイント(C)での波形が適当な幅と出来るだけ50%のデュティー比になるように実験的に決めた
Pause 5
CCP1CON=0 'PWM OFF for 80ms PWMを80ms OFF
Pause 80
Return
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's
configurations:
'OSC - INTOSCIO; WDTE - Enable;
Power-up Timer - Disable
'MCLRpin – Reset ; BODEN - Enable; Low voltage Programming - Disable, Code – Not Protect, Data EEPROM- Not Protect
超音波信号を受けて3個のLEDをON/OFFする回路用プログラム
受け側のこのプログラムの概要は以下のようである。
1) 30個のデータを集めるのでその保存場所を確保する。
2) 信号待ちしながら最初の方形波の端、つまりHが検知されたら信号パターンが送られて来たと解釈し、以下で10ms間隔で30個のデータを集め保存する。1つのパターンの全幅が300msなので300ms/10ms=30個とした。集めた各データの中身は1か0である。
3) (波形1)を検知する原理は、先ず全幅が300ms区間の4つの方形波部分の“1”の全数を推定する。最大25、最小16と考えて、もし、実際に測定した数がこの2つの間に入ればこのパターンは(波形1)と断定しLED1を点灯させる。
4) (波形2)を検知する原理は、このパターンでは2つ目の方形波が欠けているのD1からD16までの総和が最大5、最小3位と実験的に推定し、実際に測定した数がこの2つの間に入ればこのパターンは(波形2)と断定しLED2を点灯させる。
5) (波形3)を検知する原理は、このパターンでは3つ目の方形波が欠けているのD17からD30までの総和が実験的に最大3、最小1位と推定し、実際に測定した数がこの2つの間に入ればこのパターンは(波形3)と断定しLED3を点灯させる。ここで最大3、最小1と予想以上に小さい値になったのは全幅300ms区間をD1−D30が正しくカバーしていないためかも知れない。
'********* プログラム ************
'SoundSensor3LED.bas - 2010.6.10 Program to sense T4016 and turn on 3 LEDs
'12F629 with 4MHz internal
'******** ピン接続 ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input from TC4069
'Pin 4: GPIO.3: input - /MCLR (reset) via R=10K
'Pin 2: output - to LED (G) via R (indicator)
'Pin 6: GPIO.1: output - to LED1 (R) via R=470
'Pin 5: GPIO.2: output - to LED2 (R) via R=470
'Pin 3: GPIO.4: output - to LED3 (R) via R=470
'******** プログラム本体 ********
CMCON=7 'Comparator off
TRISIO=%001001 'all outputs except GPIO.0 & 3
D1 var byte 'storage for D1 (1 or 0) covering max. 4 peaks
D2 var byte
D3 var byte
D4 var byte
D5 var byte
D6 var byte
D7 var byte
D8 var byte
D9 var byte
D10 var byte
D11 var byte
D12 var byte
D13 var byte
D14 var byte
D15 var byte
D16 var byte
D17 var byte
D18 var byte
D19 var byte
D20 var byte
D21 var byte
D22 var byte
D23 var byte
D24 var byte
D25 var byte
D26 var byte
D27 var byte
D28 var byte
D29 var byte
D30 var byte
A1 var byte 'storage
A2 var byte
TotalA var byte
B var byte
C var byte
HorLdata var GPIO.0 'Input from invertor TC4069
LED var GPIO.5 'Indicator when a pulse is accepted
LED1 var GPIO.1 'For driving LED1
LED2 var GPIO.2 'For driving LED2
LED3 var GPIO.4 'For driving LED3
HorLdata=0
LED=0
LED1=0
LED2=0
LED3=0
Start:
If HorLdata=1 then ReadData 'Waiting the arrival of the first H peak 最初の方形波を待つ、検知したらReadData以下に進む
Goto Start
ReadData: ‘ここから10ms毎に30個のデータD1-D30を集める(各データは1か0、 4個の方形波を含む部分の幅約300msなので300ms/10ms=30個)
Pause 10
D1=HorLdata
Pause 10
D2=HorLdata
Pause 10
D3=HorLdata
Pause 10
D4=HorLdata
Pause 10
D5=HorLdata
Pause 10
D6=HorLdata
Pause 10
D7=HorLdata
Pause 10
D8=HorLdata
Pause 10
D9=HorLdata
Pause 10
D10=HorLdata
Pause 10
D11=HorLdata
Pause 10
D12=HorLdata
Pause 10
D13=HorLdata
Pause 10
D14=HorLdata
Pause 10
D15=HorLdata
Pause 10
D16=HorLdata
Pause 10
D17=HorLdata
Pause 10
D18=HorLdata
Pause 10
D19=HorLdata
Pause 10
D20=HorLdata
Pause 10
D21=HorLdata
Pause 10
D22=HorLdata
Pause 10
D23=HorLdata
Pause 10
D24=HorLdata
Pause 10
D25=HorLdata
Pause 10
D26=HorLdata
Pause 10
D27=HorLdata
Pause 10
D28=HorLdata
Pause 10
D29=HorLdata
Pause 10
D30=HorLdata
Pause 10
A1=D1+D2+D3+D4+D5+D6+D7+D8+D9+D10+D11+D12+D13+D14+D15
A2=D16+D17+D18+D19+D20+D21+D22+D23+D24+D25+D26+D27+D28+D29+D30
TotalA=A1+A2 ‘30個のデータD1-D30の和を求める
If 16=<(TotalA) and (TotalA)<25 then JumpA 'if OK, go to JumpA Parentheses essential! 総和が16と25との間に入っているかどうかチェックし、入っていれば波形1と断定
B=D1+D2+D3+D4+D5+D6+D7+D8+D9+D10+D11+D12+D13+D14+D15+D16
If 3=<(B) and (B)<5 then JumpB ‘D1−D16の総和が3と5の間に入っているかどうかチェックし、入っていれば波形2と断定
C=D17+D18+D19+D20+D21+D22+D23+D24+D25+D26+D27+D28+D29+D30
If 1=<(C) and (C)<3 then JumpC ‘D17−D30の総和が1と3の間に入っているかどうかチェックし、入っていれば波形3と断定。範囲が意外と小さくでた。
Goto Start
JumpA:
High LED 'Turn on LED Indicator when a pulse is accepted
Toggle LED1 ‘LED1を1回ごとに点灯/消灯の繰り返し
Pause 200 'Wait 200ms
Low LED 'Turn off LED
Goto Start
JumpB:
High LED 'Turn on LED
Toggle LED2
Pause 200 'Wait 200ms
Low LED 'Turn off LED
Goto Start
JumpC:
High LED 'Turn on LED
Toggle LED3
Pause 200 'Wait 200ms
Low LED 'Turn off LED
Goto Start
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's
configurations:
'FOSC - INTOSC; WDTE - Enable;
Power-up Timer - Disable
'MCLRpin – Reset
; BODEN - Enable; CD - Disable; CDP - Disable.
結論など
1) 3つの超音波のパターンを送信し、受信側で個々のものを区別認識することが出来た。
2) 送信側のプログラムはサブルーチンの使用によってすっきりした。
3) 受信側のプログラムでは、30個のデータを集めてそれらを操作する新しいロジックを採用した。
4) 送受信距離は相変わらず短く、電子工作42に示したものと変わらない。電圧を9V−>12V−>15Vと上げると距離は伸びる。
5) 差しあたって何か役立つものに応用できるか思いつかない。
6) 方形波の数を増せば送れる信号の数が増える。
7) 波形パターンを読込む新しいロジックが試せたのが最大の収穫だった。
改良した超音波信号を受けて3個のLEDをON/OFFする回路用プログラム(2010.6.15)
上記の'SoundSensor3LED.basは長いのでArray(配列)を使って短く見栄えを良くし、また、メモリが足りなくなったので12F629の代わりに12F683を使った。両者の間のピン配置は同じなので、12F683にこの新しいプログラムを入れて差し替えればよい。 Arrayの使い方に関しいろいろWeb上を探しまわったがに良く分からず、試行錯誤で何とか仕上げた。結局、30個のデータの保存領域確保とそれらの10ms毎の読込み、さらに30個のデータの加算などでArray を使うことによりコンパクトにすることが出来た。送受信の動作も前と変わらない。
Array (配列)の話: うまく利用するとプログラムがコンパクトに出来る。
変数名 var 型
型名 |
ビット長 |
最大値(10進) |
BIT |
1 |
0−1 |
BYTE |
8 |
0−255 |
WORD |
16 |
0−65535 |
LONG* |
32 |
−2147483647 ― 2147483647 |
*LONG型は18Fシリーズのみで使用可
例: Array var BYTE [4] の意味は以下の領域がメモリ内に確保されるということ。 [x]のような括弧を使う。
Array[0] + + + + + + + +
Array[1] + + + + + + + +
Array[2] + + + + + + + +
Array[3] + + + + + + + +
7 0 (8bit)
例: D var BIT[30] (今回のプログラム中で使われている)は同様にして BIT型でビット長が1なので以下のようになる。+には“1”か“0”が入る。
D[0] +
D[1] +
|
D[29] +
プログラム中では以下の様に使う。
I var Byte
D var Bit[30]
I=0
For i=0 to 29 'Reading 30 data once every 10 ms - D[0], D[1] ,.... D[29] ここから10ms毎に30個のデータD[0]-D[29]を集める
D[i]=HorLdata ‘ここがポイント!
Pause 10
Next I
'********* プログラム ************
'SoundSensor3LED683A.bas - 2010.6.16 modified from SoundSensor3LED.bas Previous program was shortened using arrays Program works at last!
'12F683 used with internal clock 4MHz
'******** ピン接続 ************
'Pin 1: Vdd (5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: input from TC4069
'Pin 4: GPIO.3: input - /MCLR (reset) via R=10K
'Pin 2: output - to LED (G) via R (indicator)
'Pin 6: GPIO.1: output - to LED1 (R) via R=4.7K
'Pin 5: GPIO.2: output - to LED2 (R) via R
'Pin 3: GPIO.4: output - to LED3 (R) via R
'******** プログラム本体 ********
CMCON0=7 'Comparator off ‘この2行も必須のようだ
ANSEL=0 'All ports digital
TRISIO=%001001 'all outputs except GPIO.0 & 3
A1 var byte
A2 var byte
TotalA var byte
B var byte
C var byte
HorLdata var GPIO.0 'Input from invertor TC4069
LED var GPIO.5 'Indicator when a pulse is accepted
LED1 var GPIO.1 'For driving LED1
LED2 var GPIO.2 'For driving LED2
LED3 var GPIO.4 'For driving LED3
i var byte 'Counter for 30 data collection
i=0 'Secure 30 data storages - D[0] var Byte, D[1] var Byte, ... D[29] var Byte, Arrayを使って30個のデータの保存領域確保
For i=0 to 29 ‘ここがポイント!
D var bit[30] 'No need to be "BYTE" because the bit length of D is 1, that is, "1" or "0" Dの中身は“1”か“0”なのでBit型の配列でOK!
next i
HorLdata=0
LED=0
LED1=0
LED2=0
LED3=0
Start:
If HorLdata=1 then ReadData 'Waiting the arrival of the first H peak 最初の方形波を待つ、検知したらReadData以下に進む
goto Start
ReadData:
i=0
For i=0 to 29 'Reading 30 data once every 10 ms - D[0], D[1] ,.... D[29] ここから10ms毎に30個のデータD[0]-D[29]を集める
D[i]=HorLdata ‘ここがポイント!
Pause 10
Next i
Pause 20
A1=0
For i=0 to 15 'A1=D[0]+.....+D[15] ここでD[0]+.....+D[15]の和を求める
A1=A1+D[i]
Next i
A2=0
For i=16 to 29 'A2=D[16]+ ....+D[29] ここでD[16]+.....+D[29]の和を求める
A2=A2+D[i]
Next i
TotalA=A1+A2
If 16=<(TotalA) and (TotalA)<25 then JumpA 'if OK, go to Jump1 Parentheses essential!
B=0
For i=0 to 15 'B=D[0]+.....+D[15] ここでD[0]+.....+D[15]の和を求める
B=B+D[i]
Next i
If 3=<(B) and (B)<6 then JumpB ‘ここの範囲を決める数値も少し変えた
C=0
For i=16 to 29 'C=D[16]+ ....+D[29] ここでD[16]+.....+D[29]の和を求める
C=C+D[i]
Next i
If 3=<(C) and (C)<6 then JumpC ‘ここの範囲を決める数値も少し変えた
Goto Start
JumpA:
High LED 'Turn on LED Indicator when a pulse is accepted
Toggle LED1
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Start
JumpB:
High LED 'Turn on LED
Toggle LED2
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Start
JumpC:
High LED 'Turn on LED
Toggle LED3
Pause 200 'Wait 200ms
Low LED 'Turn off LED
GOTO Start
'******** プログラムの終了 ********
'Note:
'melabs U2 Programmer's configurations 12F683:
'FOSC – INTOSCIO; WDTE - Enable;
Power-up Timer - Disable
'MCLRpin – Reset ; BODEN - Enable; Internal External Switvh Over – Enable, Fail-Safe Clock Monitor – Enable, CD - Disable;Dtata EPPROM - Disable.