Измерение питания Arduino c помощью bandgap

FreeManGH
Offline
Зарегистрирован: 27.08.2012
Доброго времени суток!
Сразу сорри если не в ту ветку.
Есть необходимость мониторить ардуинку запитаную от 3-х элементов АА(4,5 В) по питанию и при падении напряжения до 3-х и меньше Вольт подавать сигнал(пищалку включать или мигать светиком). Наткнулся на статейку Как измерить Vcc?, с ходу получаю такие результаты: 
3.79 v_bat
3.78 v_bat
3.74 v_bat
3.73 v_bat
3.73 v_bat
3.73 v_bat
3.73 v_bat
3.74 v_bat
3.77 v_bat
3.79 v_bat
3.79 v_bat
3.77 v_bat
3.74 v_bat
3.73 v_bat
Питание в данный момент от USB. Мультиметр показывает 5.02 В на ножках питания ATMega328P-PU.
Еще непонятен вопрос относительно замера:
V_BAT=(1.1*1024)/analogRead(14);

и

analogReference(DEFAULT);
raw_bandgap = analogRead(14);

analogReference(DEFAULT) - говорит использовать питание Vcc как опорное.

Далее , поправьте если не прав, снимаем показания с 14 канала который подключен к Vcc?
Каким образом тогда тут притянуто 1.1 В ?
Прошу знатоков помочь в вопросе!
Заранее благодарен.
maksim
Offline
Зарегистрирован: 12.02.2012

FreeManGH пишет:

Далее , поправьте если не прав, снимаем показания с 14 канала который подключен к Vcc?
 
 
Нет, ничего никуда подключать не надо. Читайте даташит.
 
FreeManGH пишет:
Каким образом тогда тут притянуто 1.1 В ? 

Читайте даташит 23. Analog-to-Digital Converter.

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  int Value = readVcc();
  Serial.print(Value/100);
  Serial.print(".");
  Serial.println(Value%100);
  delay(100);
}


int readVcc() 
{
  ADMUX = (1<<REFS0) | (1<<MUX3) | (1<<MUX2) | (1<<MUX1); 
  delay(10);
  ADCSRA |= _BV(ADSC);
  while (ADCSRA & (1<<ADSC)); 
  uint8_t low  = ADCL; 
  uint8_t high = ADCH;
  long result = (high<<8) | low;
  result = 1125300L / result / 10; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; 
}

 

toc
Offline
Зарегистрирован: 09.02.2013
FreeManGH
Offline
Зарегистрирован: 27.08.2012

toc пишет:

FreeManGH, http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-...  функция readVcc

 

Сделал для себя перевод этой статейки, может кому еще пригодится http://blog.unlimite.net/?p=224

P.S.: не ругайте сильно если что не так!

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

FreeManGH пишет:

Сделал для себя перевод этой статейки, может кому еще пригодится.

Полезно тексты гонять через спеллчекер, а то у Вас, например, слово "Мало известная" почему-то с пробелом пошло. Дальше там вообще порядок слов не по русски. Вобщем, перевод - штука тонкая.

FreeManGH
Offline
Зарегистрирован: 27.08.2012

:)

Перечитаю на выходных....

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Отличная ссылка. А я все по старинке на аналоговом порту через делитель мерию :(

axill
Offline
Зарегистрирован: 05.09.2011

sav13 пишет:

Отличная ссылка. А я все по старинке на аналоговом порту через делитель мерию :(

ну такая фишка bandgap была не всегда) поэтому раньше и измеряли "по старинке". Bandgap появился в какой-то момент в мегах. Мне очень полезным оказался совет - читать даташиты на те МК, которыми пользуешься. Если внимательно прочитать даташит то сделать такую вещь можно без всяких чужих статей. Там ничего сложного. В некоторых мегах кстати есть еще и встроенный датчик температуры ))

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

axill пишет:

ну такая фишка bandgap была не всегда) поэтому раньше и измеряли "по старинке". Bandgap появился в какой-то момент в мегах. Мне очень полезным оказался совет - читать даташиты на те МК, которыми пользуешься. Если внимательно прочитать даташит то сделать такую вещь можно без всяких чужих статей. Там ничего сложного. В некоторых мегах кстати есть еще и встроенный датчик температуры ))

То есть это не аппаратная функция AVR а реализация платы Arduino Mega?

На других версиях Arduino и голых AVR работать не будет?

axill
Offline
Зарегистрирован: 05.09.2011

sav13 пишет:

То есть это не аппаратная функция AVR а реализация платы Arduino Mega?

На других версиях Arduino и голых AVR работать не будет?

как раз наоборот - это аппаратная функция atmel МК. Все семейства не изучал, но начиная с mega8 bandgap есть в семействе мега, а вот в тиньках нет (или если есть то не во всех, за все не скажу) хотя и тиньки и мега это семество AVR. В МК atmega328p кроме возможности измерить напряжение питания используя bandgap можно еще воспользоваться встроенным в МК термоментром, в даташите это канал ADC8. Наверняка в более старших моделях есть еще какие-то фишки - этим и полезно читать даташиты на свой МК, чтобы максимально хорошо знать возможности и ограничения

 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Здравствуйте
Опять проблемка с функцией vccRead()

long readVcc() {
  long result;
  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = (1100L * 1023)/result;
  return result;
}

На голой Atmega328 сильно врет.

Причем чем выше напряжение, тем меньше врет:

Реально Показывает
3,3 2,61
3,72 3,06
4,1 3,52
5,11 4,45

Куда можно копать?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

sav13, от чего питаете МК во время этих экспериментов? Хорошо бы попробовать что-то другое, или убедиться осциллографом (с пропускной полосой не менее тактовой частоты мк!) , что по шине питания шум не более 20-30mV. Ещё можно измерить фактическое напряжение ИОН, для этого дать команду analogReference(INTERNAL) в пустом скетче, и мультиметром измерить на ноге aRef. 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

dimax пишет:

sav13, от чего питаете МК во время этих экспериментов? Хорошо бы попробовать что-то другое, или убедиться осциллографом (с пропускной полосой не менее тактовой частоты мк!) , что по шине питания шум не более 20-30mV. Ещё можно измерить фактическое напряжение ИОН, для этого дать команду analogReference(INTERNAL) в пустом скетче, и мультиметром измерить на ноге aRef. 

Спасибо. Направление поисков получено - разобрался

Питаю от разных источников.
analogReference(INTERNAL) на AREF показывает 1.1 В с погрешностью 1-2%
analogReference(DEFAULT) на AREF то самое непонятное напряжение, которое и показывает 

Оказывается AVCC висел в воздухе. Подцепил его к питанию - все стало нормально

Осталось вывести процент разряда в зависимости от напряжения. Зависимость то явно нелинейная.
Думаю, подключу батарейный датчик к умному дому. Прогоню пару раз до полного разряда.