Измерение Vcc с внутренним источником опорного напряжения 1,1 В не работает на Atmega328 с питанием 3,3 В.
Мне нужно контролировать аккумулятор, подключенный к ATmega, работающему в автономном режиме.
Я использую загрузчик «ATmega на макетной плате (внутренняя тактовая частота 8 МГц)». Подробнее здесь
Когда ATmega питается от напряжения 5 В, скетч выдает хорошие значения: около 5100 мВ.
Но когда я подаю на него напряжение 3,3 В, скетч дает странные значения: около 178619 мВ.
Вот мой код: Взято отсюда
void setup()
{
Serial.begin(9600);
Serial.println(F("Internal Voltage Sensor"));
}
void loop()
{
Serial.println( readVcc());
delay(1000);
}
long readVcc()
{
long voltage=0;
uint8_t wADC;
// Чтение опорного напряжения 1,1 В относительно AVcc
// устанавливаем опорное значение Vcc, а измерение — внутреннее опорное напряжение 1,1 В
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRA |= _BV(ADEN); // включаем АЦП
delay(20); // Подождем, пока Vref установится
ADCSRA |= _BV(ADSC); // Начать преобразование
while (bit_is_set(ADCSRA,ADSC)); // измерение
// Регистр чтения «ADCW» сначала заботится о том, как читать ADCL, а затем ADCH.
wADC = ADCW;
voltage = 11253000L / wADC; // Вычисляем Vcc (в мВ); 1125,3 = 1,1*1023*1000
return voltage; // Vcc в милливольтах
}
Я не понимаю, что происходит. Возвращаемое значение при Vcc=3,3 В должно быть ниже, чем при VCC=5 В. Что-то вроде 3300 мВ!
@feuille osier, 👍2
Обсуждение1 ответ
▲ 2
Спасибо за ваши ответы! Джот дал решение: wADC должен быть uint16_t.
Вот исправленный код:
void setup()
{
Serial.begin(9600);
Serial.println(F("Internal Voltage Sensor"));
}
void loop()
{
Serial.println(readVcc());
delay(1000);
}
long readVcc()
{
long voltage=0;
uint16_t wADC;
// Чтение опорного напряжения 1,1 В относительно AVcc
// устанавливаем опорное значение Vcc, а измерение — внутреннее опорное напряжение 1,1 В
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRA |= _BV(ADEN); // включаем АЦП
delay(20); // Подождем, пока Vref установится
ADCSRA |= _BV(ADSC); // Начать преобразование
while (bit_is_set(ADCSRA,ADSC)); // измерение
// Регистр чтения «ADCW» сначала заботится о том, как читать ADCL, а затем ADCH.
wADC = ADCW;
voltage = 1125300L / wADC; // Вычисляем Vcc (в мВ); 1125300 = 1,1*1023*1000
return voltage; // Vcc в милливольтах
}
,
@feuille osier
Смотрите также:
- Запрограммировать ATMega328P и использовать его без платы Arduino.
- SIM800C, CPIN: НЕ ГОТОВ (КОД ОШИБКИ: +CME ОШИБКА: 10)
- Atmega328p — переход на низкое энергопотребление 1,8 В с использованием генератора 4 МГц — прошивка загрузчика
- Как загрузить скетч на atmega328 через FTDI FT232RL UART и Arduino IDE?
- Вызов функций одного класса из другого класса — Обратный вызов
- Функция freeMemory() из библиотеки memoryfree не возвращает уменьшенное значение в arduino UNO
- Ardutester Millenium I2c Lcd ничего не показывает!
- Автономный ATMega328 — нужно ли прожигать загрузчик?
Попробуйте добавить в свой код еще несколько Serial.printlns. Например,
Serial.println(wADC);
, @GerbenADCL — это младший байт, ADCH — старший байт, и сначала необходимо прочитать ADCL, а затем ADCH. ADCW сообщает компилятору прочитать два байта в правильном порядке. Использование ADCW, конечно, проще и даже лучше, потому что оно не может пойти не так... если только вы не попытаетесь поместить 16 бит ADCW в байт и выбросить старший байт. Сделайте wADC uint16_t., @Jot