テキストからは逸れるが、基準電圧IC REF5020AID (2.048 V±0.1%)をADコンバーターの基準電圧に使ってみる。1 LSBが丁度2 mVになるので計算が楽。
#define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> #include "LCDClass.h" const uint16_t mVREF = 2048; const uint16_t RESOLUTION = 1024; const uint8_t LSB = mVREF / RESOLUTION; int main(){ LCDClass lcd("PB0","PD7","PD6","PD5","PB7","PB6"); // (RS,EN,D4,D5,D6,D7)の順番で指定する。 lcd.init(); //ADMUX &= ~(1 << REFS1) | (1 << REFS0); // 基準電圧はAREF。これがデフォルト。 ADCSRA |= (0b111) | (1 << ADEN); // 128分周。ADCペリフェラルをオン。 uint16_t adc; uint16_t mV; uint16_t ppm; while(1){ ADCSRA |= (1 << ADSC); // 変換を開始して、 loop_until_bit_is_clear(ADCSRA, ADSC); // 変換し終えるのを待って、 adc = ADC; // AD変換値を取得して、 mV = LSB * adc; // 電圧に変換して、 if(mV < 200){ lcd.clearDisplay(); lcd.gotoRowCol(1, 1); lcd.print("fault"); } else if(200 <= mV && mV < 400){ lcd.clearDisplay(); lcd.gotoRowCol(1, 1); lcd.print("preheating ..."); } else{ ppm = (25 * (mV - 400) + 4) / 8; // ppmに変換する。+4は小数点以下を四捨五入するため。 lcd.clearDisplay(); lcd.gotoRowCol(1, 1); lcd.print("AD:"); lcd.gotoRowCol(1, 4); lcd.print(adc); lcd.gotoRowCol(1, 9); lcd.print("mV:"); lcd.gotoRowCol(1, 12); lcd.print(mV); lcd.gotoRowCol(2, 1); lcd.print("ppm:"); lcd.gotoRowCol(2, 5); lcd.print(ppm); } _delay_ms(1000); } return 0; }