ブレッドボードラジオAVRマイコン入門

BASCOM-AVR A⁄D変換(その2)

 A⁄D変換値によってLEDの点灯状態が変化するプログラムの実験をしました。

1. プログラムのテスト用回路

 テスト用回路は下記の通りです。A⁄D変換入力は前と同じくADC9(PB6, 9番ピン)に10kΩのボリュームをつなぎました。出力はPA0〜PA7とGND間にLEDを接続しました。

 第1図

2. A⁄D変換値に応じてLEDの点灯個数が変化する

 A⁄D変換値(入力電圧)に応じてLEDの点灯個数が0個から8個まで変化するプログラムです。A⁄D変換値が大きくなるほど点灯個数が増えます。下の図のような感じです。白丸が消灯、赤丸が点灯を表わしています。

A⁄D変換値LED7LED6LED5LED4 LED3LED2LED1LED0
0
1〜127
128〜251
252〜383
384〜511
512〜639
640〜767
768〜895
896〜1023

 プログラムファイル adc2a.bas

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Porta = Output ポートAを出力に設定する。
5 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。
変換方法は「単独変換」、分周値は「自動」。
6
7 Dim A As Word ワード型変数「A」を使用する。
8
9 Do Doループの範囲ここから。
10  Porta = 0 LEDをすべて消灯する。
11  Start Adc A⁄D変換を開始する。
12  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
13  If A = 0 Then Porta = 0 「A = 0」ならLEDをすべて消灯する。
14  If A > 0 Then Porta.0 = 1 「A > 0」ならLED0を点灯する。
15  If A >= 128 Then Porta.1 = 1 「A ≥ 128」ならLED1を点灯する。
16  If A >= 256 Then Porta.2 = 1 「A ≥ 256」ならLED2を点灯する。
17  If A >= 384 Then Porta.3 = 1 「A ≥ 384」ならLED3を点灯する。
18  If A >= 512 Then Porta.4 = 1 「A ≥ 512」ならLED4を点灯する。
19  If A >= 640 Then Porta.5 = 1 「A ≥ 640」ならLED5を点灯する。
20  If A >= 768 Then Porta.6 = 1 「A ≥ 768」ならLED6を点灯する。
21  If A >= 896 Then Porta.7 = 1 「A ≥ 896」ならLED7を点灯する。
22  Waitms 100 0.1秒間そのまま。
23 Loop Doループの範囲ここまで。9行目へ戻る。
24
25 End 終わり。

 13行目から21行目の「If」プログラムでADC値による条件分けをしています。ADC値が「0」のときはすべてのLEDが消灯、「0」以外のときは値に応じた数のLEDが光ります。「A > 0」は「Aが0より大きい」、つまり「1」以上という意味です。「A >= 128」は「A ≥ 128」、つまり「Aが128以上」という意味です。

 このプログラムでは条件に合致したときに実行するプログラムが1行だけなので、「Then」に続けて記述しました。この場合、間に「 : 」(コロン)は入らないことに注意してください。また、「Else」命令がなく、これでひとつの「If」構文が終わるので、「End If」は省略できます。

3. Forループを用いる

 上と同じ動作をするプログラムを「For」ループを使って書くと下記のようになります。LEDの点灯個数が変わる境目のADC値を上のプログラムと合わせるため、元のADC値に「1」を加えていますが、どちらでも見た目はほとんど変わりません。

 プログラムファイル adc2b.bas

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Porta = Output ポートAを出力に設定する。
5 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。
変換方法は「単独変換」、分周値は「自動」。
6
7 Dim A As Word ワード型変数「A」を使用する。
8 Dim N As Byte バイト型変数「N」を使用する。
9
10 Do Doループの範囲ここから。
11  Porta = 0 LEDをすべて消灯する。
12  Start Adc A⁄D変換を開始する。
13  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
14  If A = 0 Then : Porta = 0 条件分岐プログラムここから。
「A = 0」ならLEDをすべて消灯する。
15  Else そうでなければ(「A ≠ 0」ならば)、
16  A = A + 1 「A」に「1」を加えて新たな「A」とする。
17  A = A / 128 「A÷128」の答えを新たな「A」とする。
18  For N = 0 To A Forループここから。「A+1」回繰り返し。
19  Porta.n = 1 ポートAのN番を「1」にする。LED・Nが点灯。
20  Next N Forループここまで。18行目へ戻る。
21  End If 条件分岐プログラムここまで。
22  Waitms 100 0.1秒間そのまま。
23 Loop Doループの範囲ここまで。10行目へ戻る。
24
25 End 終わり。

 14行目から21行目が「If」構文(条件分岐プログラム)です。今回は複数行になるので最後に「End If」が必要です。また、14行目には条件に合ったときに実行するプログラムも記述されていますが、この場合は間に「 : 」(コロン)が要ります。

 この辺は非常にややこしいので、ちょっと横道にそれますが、「If」構文の正しい書き方の例を並べておきます。下記のプログラムはいずれも「Aが0ならばBを0にする、Aが0でなければBを1にする」という動作になります。「Aが0でない(A ≠ 0)」はプログラム上では「A <> 0」と書きます。「Then」命令と「Else」命令の内容がともに短いときはすべてを1行で済ませてしまうこともできます。

[ 書き方1 ]
If A = 0 Then B = 0
If A <> 0 Then B = 1
[ 書き方2 ]
If A = 0 Then
 B = 0
End If
If A <> 0 Then
 B = 1
End If
[ 書き方3 ]
If A = 0 Then : B = 0
 Else : B =1
End If
[ 書き方4 ]
If A = 0 Then : B = 0
 Else
 B = 1
End If
[ 書き方5 ]
If A = 0 Then
 B = 0
 Else
 B = 1
End If
[ 書き方6 ]
If A = 0 Then B = 0 Else B = 1

4. LEDの点滅間隔をボリュームで調節する

 A⁄D変換入力端子につないだボリュームを回すと、LEDの点滅速度が変化するプログラムです。LED点滅プログラムの「Waitms」の数字のところにA⁄D変換値を代入します。ボリュームのスライダー位置によって「Waitms 0」から「Waitms 1023」まで変化するので、連続点灯から約1秒毎のゆっくりした点滅まで、間隔を任意に調節することができます。8個のLEDすべてを同時に点滅させます。

 プログラムファイル adc2c.bas

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Porta = Output ポートAを出力に設定する。
5 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。
変換方法は「単独変換」、分周値は「自動」。
6
7 Dim A As Word ワード型変数「A」を使用する。
8
9 Do Doループの範囲ここから。
10  Start Adc A⁄D変換を開始する。
11  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
12  Porta = 255 LED0〜7すべてを点灯する。
13  Waitms A Aミリ秒間そのまま。
14  Porta = 0 LED0〜7すべてを消灯する。
15  Waitms A Aミリ秒間そのまま。
16 Loop Doループの範囲ここまで。9行目へ戻る。
17
18 End 終わり。

5. 暗くなるとLEDが点灯する

 A⁄D変換端子に光センサのCdSをつなぎ、暗くなる(CdSの受光面の上に手をかざす)とLEDが点灯、明るくなると消灯するプログラムです。回路図を下に示します。あらかじめ明るいときと暗いときの入力電圧とADC値を調べたところ図右のようになりました。そこで、この中間の値(ADC=800)のときにLEDの状態が切り替わるようにしました。

 第2図

 プログラムファイル adc2d.bas

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Porta = Output ポートAを出力に設定する。
5 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。
変換方法は「単独変換」、分周値は「自動」。
6
7 Dim A As Word ワード型変数「A」を使用する。
8
9 Do Doループの範囲ここから。
10  Start Adc A⁄D変換を開始する。
11  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
12  If A > 800 Then ADC値が800より大きければ、
13  Porta = 255 LED0〜7すべてを点灯する。
14  Else そうでなければ(A < 800ならば)、
15  Porta = 0 LED0〜7すべてを消灯する。
16  End If 条件分岐プログラムここまで。
17  Waitms 100 0.1秒間そのまま。
18 Loop Doループの範囲ここまで。9行目へ戻る。
19
20 End 終わり。