Продолжаем осваивать LGT8F328P…
На сей раз понадобилось измерить напряжение питания. Что из этого вышло
Обычно напряжение питания микроконтроллера узнают замером «калиброванного» опорного напряжения (в ATMega328 это 1.1В) относительно напряжения питания (это высказывание не совсем верное, но короткое).
Применяют описанную во многих местах функцию readVCC()
long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }
В результате получают напряжение питания в милливольтах. Очень удобно! Быстро! И достаточно точно!
НО!!!
Для LGT8F328P такой трюк у меня не прошел 🙁
Конечно, я учел, что там и разрядность АЦП другая, и опорное напряжение иное, и битами регистров я «щелкал» разными способами — не получилось!
Пришлось вернуться к стандартному замеру напряжения через вход АЦП. Через делитель 1:2 подключил вход А1 к VCC и воспользовался стандартным analogRead(A1). Все работает. Судя по считанному значению (0х8ED), по умолчанию используется Vref = VCC (у меня питание было от LiPo 18650).
Для получения адекватного значения надо взять «опору по надежнее».
И тут стало интересно: какие константы используются для указания AnalogReference?
Оказалось — никакого «мудрежа» — прекрасно распознаются компилятором и работают для LGT8xxx следующие константы:
INTERNAL1V024 для 1,024В
INTERNAL2V048 для 2,048В
INTERNAL4V096 для 4,096В
для делителя 1:2 выбрал INTERNAL2V048 и сразу получил милливольты на выходе функции analogRead().
void setup() { Serial.begin(9600); // initialize serial while (!Serial); analogReference(INTERNAL2V048); } void loop() { int VA1 = analogRead(A1); int vA1i = VA1 * 0.9935; //делитель получился не совсем 1:2 Serial.print(VA1); //даже пересчитывать ничего не надо Serial.print(" "); Serial.println(vA1i); delay(1000); }