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

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

 ATtiny26LのA⁄D変換入力端子に温度測定用IC・LM35DZをつないで、簡単な温度計のプログラムを作ってみました。

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

 テスト用回路は下記の通りです。LM35DZの出力端子をマイコンICのADC9(PB6, 9番ピン)につなぎました。測定した温度を表示するためにLCD・液晶ディスプレイも接続します。LM35DZは2SC1815などのトランジスタと同じ形をした3本足のICです。出力電圧は1℃あたり10mVです。つまり0℃のとき0V、10℃のとき100mV、20℃のとき200mVと、たいへんわかりやすくなっています。

 第1図

2. LCDに温度を表示する

 第2図

 まずは普通に温度を表示するプログラムです。簡単にするために端数を切り捨てて1℃単位で表示します。LM35DZの出力電圧は1℃あたり10mVなので、A⁄D変換値を2.048で割れば温度になります。「℃」の左上の丸は、LCDの文字コード表にそれらしい記号(&Hdf)があったので使いました。

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

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 LCDのピン接続の設定。DB4=PA4, DB5=PA5。
5 Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 LCDのピン接続の設定。DB6=PA6, DB7=PA7。
6 Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 LCDのピン接続の設定。E=PA3, RST=PA2。
7 Config Lcd = 16 * 2 16文字×2行表示のLCDを使用する。
8 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。「単独変換・分周比自動」。
9
10 Dim A As Word ワード型変数「A」を使用する。
11 Dim T As Byte バイト型変数「T」を使用する。
12 Cursor Off カーソルを表示しない。
13
14 Do Doループの範囲ここから。
15  Start Adc A⁄D変換を開始する。
16  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
17  T = A / 2.048 「A÷2.048」の答えを変数「T」に代入。
18  Cls LCDの表示を消去する。
19   Lcd "Temp=" ; T LCDに「Temp=」と変数「T」の値を表示。
20   Lcd Chr(&Hdf) ; "C" LCDに「℃」を表示。
21  Wait 1 1秒間そのまま。
22 Loop Doループの範囲ここまで。14行目へ戻る。
23
24 End 終わり。

3. 温度を0.5℃刻みで表示する

 第3図

 ATtiny26LのA⁄D変換は5mV程度の精度があるので、温度を0.5℃刻みで表示してみました。A⁄D変換値を2.048で割った答えの整数部分と小数部分を取り出します。小数部分の数値の大きさによって3通りの表示に分類します。

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

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 LCDのピン接続の設定。DB4=PA4, DB5=PA5。
5 Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 LCDのピン接続の設定。DB6=PA6, DB7=PA7。
6 Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 LCDのピン接続の設定。E=PA3, RST=PA2。
7 Config Lcd = 16 * 2 16文字×2行表示のLCDを使用する。
8 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。「単独変換・分周比自動」。
9
10 Dim A As Word ワード型変数「A」(A⁄D変換値)。
11 Dim T0 As Simgle シングル型変数「T0」(元の温度値)。
12 Dim Ti As Byte バイト型変数「Ti」(「T0」の整数部分)。
13 Dim Tf As Single シングル型変数「Tf」(「T0」の小数部分)。
14 Cursor Off カーソルを表示しない。
15
16 Do Doループの範囲ここから。
17  Start Adc A⁄D変換を開始する。
18  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
19  T0 = A / 2.048 「A÷2.048」の答えを変数「T0」に代入。
20  Ti = Int(t0) 「T0」の整数部分を変数「Ti」とする。
21  Tf = Frac(t0) 「T0」の小数部分を変数「Tf」とする。
22  Cls LCDの表示を消去する。
23   Lcd "Temp=" LCDに「Temp=」と表示。
24
25  If Tf < 0.25 Then 条件分岐1。「Tf<0.25」ならば、
26   Lcd Ti ; ".0" LCDに「Ti」の値と「.0」を表示。
27  End If 条件分岐1ここまで。
28  If 0.25 <= Tf And Tf < 0.75 Then 条件分岐2。「0.25≤Tf、かつTf<0.75」ならば、
29   Lcd Ti ; ".5" LCDに「Ti」の値と「.5」を表示。
30  End If 条件分岐2ここまで。
31  If 0.75 <= Tf Then 条件分岐3。「0.75≤Tf」ならば、
32   Ti = Ti + 1 「Ti」に「1」を加える。
33   Lcd Ti ; ".0" LCDに「Ti」の値と「.0」を表示。
34  End If 条件分岐3ここまで。
35
36  Lcd Chr(&Hdf) ; "C" LCDに「℃」を表示。
37  Wait 1 1秒間そのまま。
38 Loop Doループの範囲ここまで。16行目へ戻る。
39
40 End 終わり。

 25行目から34行目にかけて、条件分岐プログラムが3種類あります。これは元の温度値「T0」の小数部分「Tf」の大きさによって表示の仕方を変えるプログラムです。28行目「If 0.25 <= Tf And Tf < 0.75 Then」は、「0.25 <= Tf」と「Tf < 0.75」という2つの条件の両方に当てはまれば、という意味です。つまり「0.25 ≤ Tf < 0.75ならば」という意味になります。ここを「If 0.25 <= Tf < 0.75 Then」と書いたらエラーになりました。

 条件がややこしいので具体的な数字を例にとって説明します。まず、条件は下記の3つです。

 ADC値(変数「A」の値)が41, 42, 43のとき、他の変数の値と最終的な温度表示は下記の表のようになります。

ADC値変数T0変数Ti変数Tf 条件判断温度表示
4120.019200.019 条件1に合う20.0℃
4220.507200.507 条件2に合う20.5℃
4320.996200.996 条件3に合う21.0℃

 ADC値が41のとき、「T0」は41÷2.048=20.019です。整数部分「Ti」は20、小数部分「Tf」は0.019です。これは条件1「Tf < 0.25」に合致しますので、プログラム26行目「Lcd Ti ; ".0"」により、「Ti」(20)と「.0」が表示され、「20.0℃」となります。

 ADC値が42の場合は小数部分が0.507になります。これは条件2「0.25 ≤ Tf < 0.75」に合っていますから、プログラム29行目「Lcd Ti ; ".5"」によって「Ti」(20)と「.5」が表示され、「20.5℃」となります。

 ADC値が43のときは、整数部分が20、小数部分が0.996です。これは条件3「0.75≤Tf」に当てはまるので、まずプログラム32行目「Ti = Ti + 1」で「Ti」の値を21にして、次に33行目「Lcd Ti ; ".0"」により「21.0℃」と表示します。

4. バーグラフによる温度表示

 第4図

 温度をバーグラフで表示するプログラムを作ってみました。細かい表示をしようと思うとプログラムが複雑になりすぎるので、0℃から40℃の範囲で1℃あたり2⁄5桁分ずつバーが延びていく単純なパターンにしました。5℃刻みの目盛線もグラフがある部分だけにしか付けていません。それでもかなり面倒くさいプログラムです。きっと、もっと簡単なやり方があるはずです。

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

1 $regfile = "at26def.dat" ATtiny26Lを使用する。
2 $crystal = 1000000 クロック周波数を1MHzに設定。
3
4 Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 LCDのピン接続の設定。DB4=PA4, DB5=PA5。
5 Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 LCDのピン接続の設定。DB6=PA6, DB7=PA7。
6 Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 LCDのピン接続の設定。E=PA3, RST=PA2。
7 Config Lcd = 16 * 2 16文字×2行表示のLCDを使用する。
8 Config Adc = Single , Prescaler = Auto A⁄D変換の設定。「単独変換・分周比自動」。
9
10 Declare Sub Bargraph1 サブルーチン「Bargraph1」を使用する。
11 Declare Sub Bargraph2 サブルーチン「Bargraph2」を使用する。
12 Dim A As Word ワード型変数「A」を使用する。
13 Dim T As Byte バイト型変数「T」を使用する。
14 Deflcdchar 1, 32, 32, 16, 16, 16, 16, 32, 32 Chr(1)の文字データ。
15 Deflcdchar 2, 32, 32, 24, 24, 24, 24, 32, 32 Chr(2)の文字データ。
16 Deflcdchar 3, 32, 32, 28, 28, 28, 28, 32, 32 Chr(3)の文字データ。
17 Deflcdchar 4, 32, 32, 30, 30, 30, 30, 32, 32 Chr(4)の文字データ。
18 Deflcdchar 5, 32, 32, 31, 31, 31, 31, 32, 32 Chr(5)の文字データ。
19 Deflcdchar 6, 32, 1 , 16, 16, 16, 16, 1 , 32 Chr(6)の文字データ。
20 Cursor Off カーソルを表示しない。
21
22 Do Doループの範囲ここから。
23  Start Adc A⁄D変換を開始する。
24  A = Getadc(9) 「ADC9」の入力をA⁄D変換して「A」に代入。
25  T = A / 2.048 「A÷2.048」の答えを変数「T」に代入。
26  T = T * 2 「T」に「2」を掛けたものを「T」とする。
27  Cls LCDの表示を消去する。
28  Locate 1 , 4 : Lcd "1O" LCDの上の行4桁目に「10」を表示する。
29  Locate 1 , 8 : Lcd "2O" LCDの上の行8桁目に「20」を表示する。
30  Locate 1 , 12 : Lcd "3O" LCDの上の行12桁目に「30」を表示する。
31  Call Bargraph1 サブルーチン「Bargraph1」を実行する。
32  Call Bargraph2 サブルーチン「Bargraph2」を実行する。
33  Wait 1 1秒間そのまま。
34 Loop Doループの範囲ここまで。22行目へ戻る。
35
36 End メインプログラム終わり。
37
38 Sub Bargraph1 サブルーチン「Bargraph1」ここから。
(1桁単位のバーを表示するプログラム)。
39  Local Col As Byte サブルーチン内で変数「Col」を使用する。
40  Local Bar5 As Byte サブルーチン内で変数「Bar5」を使用する。
41  Bar5 = T / 5 「T」を「5」で割った数を「Bar5」とする。
42  Lowerline LCDの下の行に表示する。
43  For Col = 1 To Bar5 Forループ。「Bar5」回繰り返し。
44   Select Case Col 変数値選択。「Col」の値によって表示を変える。
45   Case 2 : Lcd Chr(6) 「Col=2」ならばLCDにChr(6)を表示する。
46   Case 4 : Lcd Chr(6) 「Col=4」ならばLCDにChr(6)を表示する。
47   Case 6 : Lcd Chr(6) 「Col=6」ならばLCDにChr(6)を表示する。
48   Case 8 : Lcd Chr(6) 「Col=8」ならばLCDにChr(6)を表示する。
49   Case 10 : Lcd Chr(6) 「Col=10」ならばLCDにChr(6)を表示する。
50   Case 12 : Lcd Chr(6) 「Col=12」ならばLCDにChr(6)を表示する。
51   Case 14 : Lcd Chr(6) 「Col=14」ならばLCDにChr(6)を表示する。
52   Case 16 : Lcd Chr(6) 「Col=16」ならばLCDにChr(6)を表示する。
53   Case Else : Lcd Chr(5) 「Col」が上記以外ならばChr(5)を表示する。
54   End Select 変数値選択ここまで。
55  Next Col Forループここまで。43行目へ戻る。
56 End Sub サブルーチン「Bargraph1」ここまで。
57
58 Sub Bargraph2 サブルーチン「Bargraph2」ここから。
(1⁄5桁単位のバーを表示するプログラム)。
59  Local Bar1 As Byte サブルーチン内で変数「Bar1」を使用する。
60  Bar1 = T Mod 5 「T」を「5」で割った余りを「Bar1」とする。
61   Select Case Bar1 変数値選択。「Bar1」の値によって表示を変える。
62   Case 1 : Lcd Chr(1) 「Bar1=1」ならばLCDにChr(1)を表示する。
63   Case 2 : Lcd Chr(2) 「Bar1=2」ならばLCDにChr(2)を表示する。
64   Case 3 : Lcd Chr(3) 「Bar1=3」ならばLCDにChr(3)を表示する。
65   Case 4 : Lcd Chr(4) 「Bar1=4」ならばLCDにChr(4)を表示する。
66   End Select 変数値選択ここまで。
67 End Sub サブルーチン「Bargraph2」ここまで。

 1℃あたりバーの長さが2⁄5桁分なので、26行目「T = T * 2」で温度値を2倍しています。25行目を「T = A / 1.024」と書いてもいいのですが、あとから見たときに何をやっているかわからなくなりそうだったので2行に分けました。

 サブルーチン「Bargraph1」は5℃分のバーを表示するプログラム、サブルーチン「Bargraph2」は1℃分のバーを表示するプログラムです。それぞれ「変数値選択」(私が勝手に付けた名前です)によって表示する文字(バーの長さや形)を変えます。「変数値選択」については「LCDの表示(その6)」を見てください。

 温度値が10〜15℃のときの変数の値とLCDの表示は次のようになります。

 第6図

温度(T)x2Bar5Bar1 表示する文字LCDの表示
10℃2040 Chr 5, 6, 5, 6 10℃
11℃2242 Chr 5, 6, 5, 6, 2 10℃
12℃2444 Chr 5, 6, 5, 6, 4 10℃
13℃2651 Chr 5, 6, 5, 6, 5, 1 10℃
14℃2853 Chr 5, 6, 5, 6, 5, 3 10℃
15℃3060 Chr 5, 6, 5, 6, 5, 6 10℃