Еще один кирпичик в копилку знаний о микроконтроллерах в общем и об Arduino в частности.

Обычно при построении различных вольтметров на базе Arduino предполагают, что напряжение питания Vcc строго равно 5В. Но это далеко не так, точнее — совсем не так. Как результат — немалая погрешность в измерениях.

Малоизвестной особенностью Arduino и многих других AVR является возможность измерения внутреннего опорного напряжения 1.1В.

Эта возможность может быть использована для повышения точности функции Arduino analogRead () или для измерения питающего напряжения (Vcc), что обеспечивает средство мониторинга напряжения питания (например, батареи) без задействования драгоценного аналогового входа.

В сети гуляют, кроме описываемого здесь, еще два способа «особо точного» измерения опорного напряжения. Один основан на изменении стандартной библиотеки wiring_analog.c и затем чтения analogRead(14). Другие «знатоки» считают, что указание analogReference(INTERNAL) или DEFAULT более чем достаточно. Разброд и шатания в стане «специалистов» не желающих копнуть чуть глубже, чем первая страница выдачи поиска гугла.

Мои натурные испытания выяснили, что возможно вышеуказанные способы и сработали у их авторов на их же китайских репликах Arduino, но лично на моей оба способа выдали полную галиматью. Т.е. они не верны в принципе.

А теперь правильный ответ ниже.

Зачем всё это

Не проще ли просто мигать светодиодиками как все и радоваться жизни, что вы — крутые микроэлектронщики ?

Есть как минимум две причины, чтобы точно и правильно измерить напряжение, подаваемое на ваш Arduino (Vcc). Первая причина — если наш проект на батарейках или аккумуляторах и мы хотим следить за напряжением Vcc как мерилом уровня заряда батарей. Вторая — когда питание производится от батареи или от USB, Vcc не будет равно 5В, так что, если мы хотим сделать точные аналоговые измерения мы должны либо использовать внутреннее опорное напряжение 1.1В, либо внешнее опорное напряжение. Почему?

Предполагают, что при использовании analogRead () аналоговое опорное напряжение равно 5.0В, но в действительности оно может быть другим. Даже официальная документация по Arduino analogRead также приводит нас к этому неправильному допущению. Факт, что напряжение по умолчанию не 5.0 вольт. Если ваше питание не идеально отрегулировано или если вы работаете от батареи, это напряжение может немного изменяться. Вот пример, иллюстрирующий проблему:

Я экспериментальным путем выяснил, что на разных ПК при питании от USB напряжение пина 5V на Arduino составляет около 4.5В; при питании от аккумулятора типа «Крона» (8.4В) — 4.97В.

Для того, чтобы точно измерить аналоговое напряжение, нам нужен точный источник опорного напряжения. Большинство AVR микросхем обеспечивают три возможных источника:

  • внутренний источник 1.1В (в некоторых 2.56В)
  • внешний опорный источник
  • Vcc

Внешний источник опорного напряжения является наиболее точным, но требует дополнительного оборудования. Внутренний reference стабилен, но имеет погрешность +/- 10%. Голый Vcc полностью ненадежен в большинстве случаев.

Выбор внутреннего reference оправдан, но в большинстве случаев мы бы хотели измерять более широкий диапазон, поэтому выбор Vcc является наиболее практичным, но потенциально наименее точным и в некоторых случаях полностью ненадежным!

Как правильно

Многие AVR чипы, включая серию ATmega и многие из ряда Attiny обеспечивают средства для измерения внутреннего опорного напряжения. Зачем это кому-то надо? Причина проста — путем измерения опорного напряжения мы можем определить точное значение Vcc.
Вот как это делается:

  1. Сначала устанавливаем опорное (reference) напряжение в значение Vcc
  2. Измеряем внутреннее опорное напряжение
  3. Рассчитываем величина Vcc

Наше измеренное напряжение

Vcc * (АЦП-измерение) / 1023

которое, как мы знаем равно 1.1В. Согласно даташиту на ATMEGA 328 оно может быть равно:

  • минимально 1.0В,
  • обычно 1.1В,
  • максимально 1.2В.

Забегая вперед скажу, что эта константа требует ручной калибровки, у меня она получилась равной 1.179В.

АЦП у Arduino имеет разрядность 10 бит, это означает, что входное напряжение от 0В до 5В преобразовывается в целочисленное значение от 0 до 1023. Вот откуда здесь число 1023.

Далее рассчитываем Vcc и получаем:

Vcc = 1.1 * 1023 / АЦП-измерение

Другими словами, вся фишка в том, чтобы выяснить реальное напряжение питания Vcc, читая internal 1.1V reference и используя Vcc в качестве эталона. Затем с помощью простой математики высчитываем реальное Vcc.

Кусок кода функции выглядит так:

Примечание. Функцию analogReference() для смены опорного напряжения применять не нужно.

Подробности скетча будут ниже.

Где применять

Одно из применений — проверка Vcc или напряжения питающей батареи. Вы можете вызывать эту функцию, если вы хотите контролировать Vcc. Например, для проверки уровня заряда аккумулятора. Вы также можете использовать её, чтобы определить — вы подключены к источнику питания или работаете от батарей.

Вы также можете получить правильное значение Vcc для использования с функцией Arduino analogRead () при установке использования опорного напряжения по умолчанию (Vcc). Если у вас нет стабилизированного источника питания, то вы не можете быть уверены, что Vcc составляет точно 5.0В. Эта функция обеспечит вам правильное значение.

Однако есть один нюанс.

Как я указывал выше, спецификация на чип дает номинальное значение напряжения 1.1В, но заявляет, что оно может варьироваться от 1.0 до 1.2В. Это означает, что погрешность измерения Vcc может составить целых 10%. А это уже много!

Как повысить точность

Просто измерим два значения Vcc: реальный Vcc с помощью вольтметра (на пине AREF или 5V) и Vcc с помощью нашей функции. Затем заменим нашу константу (1.1 * 1023.0 * 1000) на новую:

scale_constant = internal1.1Ref * 1023 * 1000

где

internal1.1Ref = 1.1 * Vcc1 (с вольтметром) / Vcc2 (с нашей функцией)

где

Vcc1 — значение Vcc измеренное вручную с вольтметром
Vcc2 — значение Vcc определенное с помощью нашей функции

Это эталонное значение будет индивидуальным для конкретного AVR чипа и будет зависеть от колебаний температуры. Не стесняйтесь экспериментировать!

Чуть подробнее про поделку и исходный код программы.

Arduino. TRUE voltmeter

Arduino. TRUE voltmeter

Вся поделка представляет собой элементарный вольтметр на Arduino с пределом измерений 0—50В, определяемым делителем напряжения на резисторах.

Если у вас резисторы других номиналов, то в сети вы найдете множество онлайн калькуляторов для расчета делителя напряжения.
Данные считываются с аналогового пина 1, поскольку аналоговый пин 0 уже занят дисплеем. Далее значение напряжения выводится на LCD 16×2 экран, который мы долго мучали в прошлой серии. В первой строке видим значение напряжения, во второй — время в формате ЧЧ:ММ:СС.

Arduino. TRUE voltmeter

Arduino. TRUE voltmeter

Полная версия скетча здесь.
Для тех, кто любит картинки «вместо тысячи слов» снято видео.

По материалам статьи Scott Daniels «Secret Arduino Voltmeter – Measure Battery Voltage», 2012.

Но это еще не все. Продолжение следует.

Подписывайтесь на RSS.

Автор не является продвинутым электронщиком, посему делитесь замечаниями по существу в комментариях ниже.