Atmega328p напряжение 18650

делаю радиодатчик температуры на amega328p + HC 12 из темы радиокота Монитор погоды на ESP32 , у автора темы датчик питается от 4.5в . я перевел питание на 18650 сама atmega переведена на режим 3.3в 8мгц , все работает . Пытаюсь организовать правильное измерение напряжения 18650. Через делитель никак не получается точных значений получить , есть такой документ AN2447 в нем описываеся что можно без делителя обойтись , но я так понимаю что это для варианта когда atmega питается фиксированным напряжение , а не как в маем случае от 18650.

У кого - нибудь есть опыт измерения напряжения 18650?

1 лайк

У ATmega328p , как и у других МК AVR есть внутреннее опорное напряжение…
Почитайте даташит, раздел про АЦП

да про опорное напряжение я читал 1.1в , при использовании делителя автора темы 47к и 240к хрень какая-то получается

напр на плате 4.148в А1 = 585

analogRead(pin_read) 1.1) / 1023;
585*1.1 / 1023=0.629

R2/(R1+R2) 47к / (47к + 240к) = 0.1637

0.629 /0.1637= 3.842

1 лайк

может неправильно делитель сделан нужны другие сопротивление какая метода подбора резисторов ?

Почитай форум Ника Гаммона, просто кладезь знаний для начинающего

Конкретно, вот в этой теме, в “Ответе №2” есть тошонадо.

R1 = 240K(лучше взять 150К), R2 = 47K.
(R1 + R2) / R2 (240 + 47)/47 = 6.106 коэффициент делителя. Т.е. при 4.3в на входе делителя - на выходе будет 4.3/6.106 = 0.704в

Петрович приводил чисто внутренний метод измерения, но тему не помню. Код такой

//
// Возвращает напряжение питания в десятых долях вольта
// Параметр - внутреннее опорное напряжение, умноженное на 10000
// Внутреннее опорное напряжение нужно замерить с как можно большей точностью
//
inline static int getBatteryVoltage(const int internalRefference = 11000) {
  ADCSRA = (bit(ADPS2) | bit(ADPS1) | bit(ADPS0));
  ADCSRA |= bit(ADEN);
  ADMUX = 0;
  ADCSRB = 0;
  ADMUX = (ADMUX & 0x2F) | 0x40;
  ADMUX &= ~bit(ADLAR);
  ADMUX = (ADMUX & 0xF0) | 14;
  delay(1); // пусть "пропитается"
  for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Первый замер ни о чём
  for (ADCSRA |= bit(ADSC); ADCSRA & bit(ADSC);); // Замеряем
  while (ADCSRA & bit(ADSC));
  const int adc = ADC;
  return (((internalRefference * 1024L + adc / 2) / adc) + 500) / 1000;
}


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

void loop(void){
  Serial.println(getBatteryVoltage(10522)); // внутреннее опорное напряжение 1,0522В
  delay(2000);
}

// при напряжении питания 4.5В выводит 45



1 лайк

Что означают эти слова? Особенно подчёркнутое? У неё нет такого режима. Вы её через стабилизатор питаете именно от 3.3В или напрямую от аккумулятора (от 4.2)? (схемы, как всегда, нет – всё как мы любим!)

Если второе, то у Вас вопрос сводится к другому: “Как измерить собственное питание?” Это несложно сделать и описано это как раз в упомянутой AN2447. Вам там что-то непонятно?

2 лайка

Так это практически по той же AN2447, которая ТС чем-то не устроила.

А в той теме, я, кстати, ещё советовал как лучше всего внутреннее опорное замерять.

2 лайка

я имел ввиду 8мгц для пониженного питания , питаю напрямую от 18650 4.2в

Ну, т.е. Вам надо измерить “собственное питание”. А что Вам непонятно в AN2447?

AREF сидит через конденсатор на землю , я так понял надо измерить измерить напр на этом выводе для мах точности ?

если честно в AN2447 мне не очень понятен код , сложновато пока для меня , вот и пытаюсь разобраться.

Ну, да, лучше бы измерить, т.к. там напряжение может гулять на ±10% в зависимости от конкретного экземпляра микросхемы.

Только здесь надо знать задачу (Вы ж нам её не сообщили!) и, соответственно, требования к точности результата. Если Вы делаете вольтметр, то да, надо измерять. А если Вы просто контролируете батарею, чтобы вовремя подать сигнал о разряде, то нахрен не нужно, просто считаете, что там 1.1В по даташиту и не паритесь, такой точности вполне хватит.

А измерять – там всё очень непросто, если Вам это реально надо, могу найти ту старую тему (ну, или ещё раз пересказать, если не найду)

Принципиально он ничем не отличается от кода из сообщения №7 выше. Идейно это одно и тоже. Открывайте даташит контроллера и построчно разбирайтесь, что делает код. Все словесно-идейные пояснения есть в аппноте. Или Вы английский неуверенно понимаете?

супер точность не нужна конечно , у меня это обычный радиодатчик . попробую пока 1.1в

попробовал код из сообщения №7 , при 11000 выводит 4 без десятых , хотя в реальности 4.158в

Ну, это нормально. Я же Вам говорил, что 1.1В там может гулять на 10% и результат, соответственно, тоже. Всё укладывается. Так что, нормально. Если Вас устраивает точность ±10%, то и не парьтесь. А если нет, скажите, я скажу как лучше поступить с замером.

а десятые я уж про сотые молчу при том коде не будет выводить ?

хотелось бы по точнее сделать , Евгений если не трудно подскажите как поступить с замером да и десятые вольта хотелось бы видеть?

Ну, там же написано

Т.е. если реальное напряжение 4,7 В, он должен возвращать целое число 47.

Если Вам нужны сотые (не знаю, зачем), нет вопросов, надо чуток изменить код. Могу также поискать код, который возвращает результат в милливольтах (тоже целым числом), если надо и выложить. Только зачем? Дело в том, что, чтобы реально (а не для красоты) иметь точность в единицы милливольт, Вам надо пользоваться не ардуиниой, а самому разводить цепи питания микроконтроллера по даташиту (в ардуине сэкономили на конденсаторе и индуктивности - их там просто нет). Кроме того, замерять надо в режиме “подавления шумов” - это немного другой код. Он у меня есть и мне не жалко, могу дать, но без правильной разводки питания результат всё равно будет так себе.

в том то и дело что просто пишет число 4 при этом коде ни 41 ни 40 , что то не так . если бы в десятых долях выводил меня бы это устроило и я бы наконец успокоился . счас попробую в ардуино платку залить посмотреть что будет показывать?

Не знаю, как у вас, а у меня выдает вот так (питание от USB)