Измерение литий-ионого аккумулятора, от которого работает Arduino
Я использую Arduino pro mini 5 В (со снятыми регулятором и индикатором питания).
Я читал, как точно измерить литий-ионные аккумуляторы при питании от того же аккумулятора, от которого вы пытаетесь измерить. Использование внутреннего аналогового опорного напряжения 1,1 В для измерения расхода источника VCC с помощью делителя напряжения на нем и математических расчетов для отображения преобразованного значения.
Читая форумы Arduino, я наткнулся на этот ответ.
long readVcc() {
long result;
// Чтение ссылки 1,1 В относительно AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Подождите, пока Vref установится
ADCSRA |= _BV(ADSC); // Конвертировать
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Обратный расчет AVcc в мВ
return result;
}
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println( readVcc(), DEC );
delay(1000);
}
Однако я не вижу аналогового чтения нигде в этом скетче. (Это строго внутренняя ссылка?) В конце темы кто-то говорит, что вы можете сделать это без делителя напряжения на аналоговом выводе.
Может ли кто-нибудь подтвердить или объяснить это? Я не хочу сломать свой Arduino...
@Lindsay Cox, 👍7
3 ответа
Лучший ответ:
Использование внутреннего аналогового эталона 1,1 В для измерения разряда VCC источник с помощью делителя напряжения на нем
Вы действительно можете использовать делитель напряжения и измерить уменьшенное значение Vcc. относительно внутреннего опорного напряжения 1,1 В. Однако это не то, код, который вы разместили, делает. Вместо этого он измеряет внутреннюю ссылка на Vcc, как указано в комментарии в коде. Бит REFS0 выбирает Vcc в качестве эталона для АЦП. Биты MUX1...MUX3 выберите внутреннюю ссылку в качестве входного канала.
result = ADCL; result |= ADCH<<8;
Эта идиома восходит к тому времени, когда компилятор не знал, как
читать 16-битные регистры ввода-вывода: вам нужно было явно читать по одному байту за раз
а затем объединить их в 16-битное слово. Это время давно прошло,
и теперь вы можете просто получить доступ к 16-битному регистру как ADC
напрямую. я
даже избавился бы от переменной result
и просто:
return 1126400L / ADC; // Vcc в мВ
Правка: как было предложено Busybee, вот объяснение коэффициент 1126400: АЦП измеряет отношение своего входного напряжения к его опорное напряжение и возвращает это отношение, масштабированное с коэффициентом 1024. В в этом случае
ADC = 1024 × (Vbg ÷ Vcc)
где Vbg — опорное напряжение запрещенной зоны 1,1 В. Таким образом,
Vcc = 1024 × Vbg ÷ АЦП
Если нам нужно напряжение Vcc в милливольтах, мы добавляем к нему напряжение Vbg в милливольтах. приведенное выше уравнение и получить
Vcc (в мВ) = 1024 × 1100 ÷ АЦП = 1126400 ÷ АЦП
Вместо вызова analogRead()
этот скетч выполняет эквивалентные действия, напрямую манипулируя аппаратными регистрами, чтобы начать преобразование, дождаться завершения преобразования и получить преобразованное значение.
Простое чтение конечного значения выполняется операторами:
result = ADCL;
result |= ADCH<<8;
Все операторы, следующие за delay(2)
и включая два вышеперечисленных, вместе взятые, делают то, что делает analogRead()
.
Относительно «_Все операторы после delay(2)
_”: обратите внимание, что analogRead()
[устанавливает ADMUX](https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores /arduino/wiring_analog.c#L63-L72)., @Edgar Bonet
Да - я пропустил это. Спасибо, @EdgarBonet., @JRobert
Если кого-то еще это смущает:
Не повредит ли это вашему Arduino?
- Нет, это внутреннее опорное напряжение между VCC & внутренний аналоговый источник опорного напряжения 1,1 В.
Нужен ли делитель напряжения?
- Нет, если только вам не нужно измерять что-то внешнее по отношению к Arduino!
Действительно ли внутреннее опорное напряжение составляет 1,1 В?
- Нет, кажется, что каждый pro mini, который у меня есть, эталонное напряжение 1,1 В немного отличается. У моих pro mini нет разъема для контакта AREF, поэтому вам нужно выяснить, какое значение имеет значение для каждого отдельного Arduino.
Я использовал это,
1.15 x 1023 x 1000 = [значение в кавычках от второй до последней строки в функции]
return "1125300L" / ADC;
Я просто несколько раз увеличивал опорное напряжение 1,1 В на 0,01, пока выходное напряжение не совпало с показаниями напряжения на моем цифровом мультиметре. Я бы подумал, что с известным напряжением вы могли бы выполнить эту математику в обратном порядке, чтобы найти, что такое AREF на самом деле. Я уверен, что это было бы проще.
Большое спасибо JRobert & @ EdgarBonnet за ответы!
- Arduino Nano: ОГРОМНОЕ падение напряжения на VIN
- Arduino 16 МГц только с 3,3 В?
- Самая низкая мощность, возможная в Arduino
- Как перевести ATtiny/ATmega в режим глубокого сна (чтобы годами работать от батарей), но при этом обнаруживать нажатие кнопки?
- Arduino PRO Mini — площадки [были «перемычками»] на задней панели и низкое энергопотребление
- Как узнать максимальный ток через VIN на плате NodeMCU?
- Питание моторного щита от Arduino pro mini 5v RAW Pin 150mAh не может запустить сервопривод
- Почему SoftwareSerial не работает как надо на Arduino Pro Mini 3v3?
Можно добавить, что 1126400 — это 1024*1100, что масштабирует результат, и почему., @the busybee
@thebusybee: Спасибо за предложение. Добавлен., @Edgar Bonet
Выдающийся ответ, как обычно. (проголосовали), @Duncan C
Спасибо за очень подробное объяснение!, @Lindsay Cox
разве это не 1.1vx **1023** x 1000? 1023 - это 10-битное общее значение для АЦП?, @Lindsay Cox
@LindsayCox: Нет, это 1024, хотя 1023 — очень распространенная ошибка, предположительно потому, что это самое высокое значение, которое вы можете получить. Согласно техническому описанию, «_максимальное значение представляет собой напряжение на выводе AREF **минус 1 LSB**._» (выделено мной) и «ADC = Vin ⋅ **1024** ÷ Vref». Таблица данных является _единственным_ авторитетным источником. Обратите внимание, что, учитывая неопределенность в Vbg, это не имеет большого значения., @Edgar Bonet