PIC16F88のA/Dコンバータを利用して温度計を作ってみます。
温度センサーは、まず定番のLM35DZを使ってみます。
LM35DZは、0mV+10.0mV/℃の出力を持つ3端子センサーです。
20℃で、0.200Vを出力します。
回路図です。Vref+(RA3)に加える電圧は、10kΩのボリュームで調整できるようにします。
センサーの出力は、今回AN4(RA4)に加えていますが、アナログポートのどこでもかまいません。
温度は、USBシリアル変換モジュールFT234Xを通してTeraTermに表示します。通信速度は9600bpsです。
これは、TeraTermのデフォルトの通信速度が9600bpsだからです。当然もっと早くもできます。
7セグメントLEDやLCD表示にしてみるのも良いと思います。
1秒ごとにセンサーの電圧を読み、過去4個のデータとの移動平均をとっています。
A/D変換結果ADresとVrefとVinの関係は、ADres = Vin / (Vref / 1024) ですから
Vref = 4.096 V とすると ADres = Vin / (4.096 / 1024) = Vin * 250 となります。
20℃の時、LM35DZの出力は、0.200Vですから ADres = 0.200 * 250 = 50 となります。
これを℃の数値と一致させるために、ADresの値を4倍して、10で割っています。
小数点以下の数値を得るには、10の剰余をとっています。
unsigned int temp[5];
void main() {
OSCCON = 0b01110000;//内部クロック8MHz
/* A/D変換設定 */
TRISA = 0b00111000; //RA3,RA4,RA5はinput 他はoutput
ANSEL = 0b00010000; //AN4を使う。他はデジタルポート
TRISB = 0b00001000; //RB3はinput 他はoutput
/* A/D変換クロックの設定 クロック8MHz 16Tosc 2.0us */
ADCON1bits.ADCS2 = 1;
ADCON0bits.ADCS1 = 0;
ADCON0bits.ADCS0 = 1;
/* 基準電圧の設定 Vref+ = Vref+(RA3),Vref- = Vss */
ADCON1bits.VCFG1 = 1;
ADCON1bits.VCFG0 = 0;
/* A/D変換結果の格納方法の設定 */
ADCON1bits.ADFM = 1;//右詰め
/* A/D変換を有効にする */
ADCON0bits.ADON = 1;
/* A/D変換対称ボートの選択 AN4を選択*/
ADCON0bits.CHS2 = 1;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
PORTA = 0x00; //PORTA初期化
PORTB = 0x00; //PORTB初期化
serial_init(); //シリアル通信初期化
while(1){
/* A/D変換 */
__delay_us(50); //50us待つ
ADCON0bits.GO_nDONE = 1; //A/D変換開始
while(ADCON0bits.GO_nDONE); // A/D変換終了まで待つ
temp[4] = temp[3];
temp[3] = temp[2];
temp[2] = temp[1];
temp[1] = temp[0];
/* A/D変換結果を読み取る */
unsigned int val = ADRESH;
temp[0] = (val<<8)+ADRESL;
int avetemp =(temp[0]+temp[1]+temp[2]+temp[3]+temp[4])/5;
avetemp = avetemp * 4;
int tempH = avetemp / 10;
int tempL = avetemp % 10;
printf("%d",tempH);
printf(".%d C\r\n",tempL);
__delay_ms(1000);
}
}
OSCCON = 0b01110000;//内部クロック8MHz
/* A/D変換設定 */
TRISA = 0b00111000; //RA3,RA4,RA5はinput 他はoutput
ANSEL = 0b00010000; //AN4を使う。他はデジタルポート
TRISB = 0b00001000; //RB3はinput 他はoutput
/* A/D変換クロックの設定 クロック8MHz 16Tosc 2.0us */
ADCON1bits.ADCS2 = 1;
ADCON0bits.ADCS1 = 0;
ADCON0bits.ADCS0 = 1;
/* 基準電圧の設定 Vref+ = Vref+(RA3),Vref- = Vss */
ADCON1bits.VCFG1 = 1;
ADCON1bits.VCFG0 = 0;
/* A/D変換結果の格納方法の設定 */
ADCON1bits.ADFM = 1;//右詰め
/* A/D変換を有効にする */
ADCON0bits.ADON = 1;
/* A/D変換対称ボートの選択 AN4を選択*/
ADCON0bits.CHS2 = 1;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
PORTA = 0x00; //PORTA初期化
PORTB = 0x00; //PORTB初期化
serial_init(); //シリアル通信初期化
while(1){
/* A/D変換 */
__delay_us(50); //50us待つ
ADCON0bits.GO_nDONE = 1; //A/D変換開始
while(ADCON0bits.GO_nDONE); // A/D変換終了まで待つ
temp[4] = temp[3];
temp[3] = temp[2];
temp[2] = temp[1];
temp[1] = temp[0];
/* A/D変換結果を読み取る */
unsigned int val = ADRESH;
temp[0] = (val<<8)+ADRESL;
int avetemp =(temp[0]+temp[1]+temp[2]+temp[3]+temp[4])/5;
avetemp = avetemp * 4;
int tempH = avetemp / 10;
int tempL = avetemp % 10;
printf("%d",tempH);
printf(".%d C\r\n",tempL);
__delay_ms(1000);
}
}
ブレッドボードと左から温度センサーの電圧、実際の温度、TeraTermの画面です。
温度センサーの出力0.23Vに対して、測定値は22.4℃です。
やはり、0.1℃の値は、ふらつきます。A/D変換まわりのノイズ対策をもっと徹底する必要がありそうです。
または、精度を落として1℃単位で表示すると良いかもしれません。