Измерение переменного напряжения микроконтроллером схема. Многофункциональный ваттметр с гальванической развязкой

Измерение переменного напряжения микроконтроллером схема. Многофункциональный ваттметр с гальванической развязкой

Дистанционный вольтметр на микроконтроллере AVR - устройство, позволяющее удалённо измерять уровень переменных напряжений от нескольких источников (в данном исполнении - 6 каналов) и отображать полученные данные на шести дисплеях, каждый из которых это трёхразрядный семисегментный индикатор. Цифровой вольтметр на AVR обеспечивает постоянный контроль энергоснабжения оборудования, которое расположено на некотором расстоянии от рабочего места оператора. Сейчас устройство используется для измерения напряжения трех фаз на входе и на выходе промышленного нормализатора напряжения – трехфазного стабилизатора. Место оператора удалено от стабилизатора на расстояние около 800м.

Конструкция цифрового вольтметра представляет собой два модуля:

  • модуль измерения и передачи, расположенного непосредственно в месте измерения;
  • модуль приёма и отображения, установлен на рабочем месте оператора.

Соединение частей вольтметра выполнено обычной телефонной парой (лапшой). Для повышения устойчивости канала связи к радиопомехам может быть использована витая пара. Линия связи имеет гальваническую развязку от других элементов устройства, которые находятся под высоким напряжением, данные по каналу связи передаются токовым сигналом, величиной до 30мА.

Характеристики устройства:

  • Диапазон измеряемых напряжений: 100 – 330В переменного тока;
  • Частота измеряемых напряжений: 50Гц;
  • Частота измерений: 0,5 сек. (частота обновления измеряемых значений по 6 каналам);
  • Напряжение оперативного питания модуля приёма и отображения: 7 - 25В постоянного тока;
  • Уровень гальванической развязки модулей: 5,0кВ;
  • Погрешность измерения напряжения: ±1,5%.

В схеме цифрового вольтметра преобразование аналогового сигнала в цифровой производится с помощью АЦП, на базе микроконтроллера AVR - ATmega8. Измерение действующего значения напряжения реализовано на алгоритме определения пика синусоидального сигнала с последующим умножением его на амплитудный коэффициент синусоиды.

Оперативное питание модуля измерения и передачи цифрового вольтметра обеспечивается бестрансформаторным блоком питания от одного из каналов измеряемого напряжения, в данной схеме от первого канала. Уровень напряжения в канале должен быть не менее 90В – минимальный уровень напряжения, при котором сохраняется работоспособность модуля.

Индикация работы линии связи между модулями устройства обеспечивается светодиодом HL1, расположенным в модуле измерения.

Принципиальная схема модуля приёма и индикации цифрового вольтметра:

Оперативное питание модуля приёма и отображения обеспечивается внешним источником 7-25В постоянного тока. При нормальном функционировании вольтметра на AVR индикаторы отображают значения измеряемых напряжений. При нарушении канала связи или неисправности модуля измерения и передачи, то есть при отсутствии поступления данных от измерительного модуля в течении более 2-х периодов обновления данных (около 1,4 сек.) на индикаторах отображается - “Err”. При восстановлении связи индикация восстанавливается автоматически. Падение уровня напряжения на любом из каналов, за исключением первого, ниже 100В, вызывает отображение на соответствующем индикаторе прочерков “---”, а на остальных индикаторах выводятся измеряемые значения напряжений, соответственно.4.08 (12 Голосов)

Как известно многие современные микроконтроллеры имеют встроенный многоканальный АЦП, как правило, физически АЦП всего один, а многоканальность обеспечивается с помощью мультиплексирования. Диапазон напряжений с которыми может работать АЦП определяют уровни опорных напряжений(+VREF и -VREF ), они не должны выходить за диапазон питания микроконтроллера. Диапазон напряжений, питающих микроконтроллер, может быть от 0 до 3.3, либо от 0 до 5 вольт. Отсюда становится понятно что измерять отрицательные напряжения АЦП не может, а это бывает необходимо.

Для измерения отрицательных напряжений с помощью АЦП существует несколько способов, во всех примерах будем считать что -VREF = 0 , а +VREF = 5 вольт.

Необходимо измерять только отрицательные напряжения, например, от -5 до 0.
В таком случае можно применить инвертирующий усилитель, построенный на операционном усилителе(ОУ), с коэффициентом усиления равным -1.

Когда на вход схемы будет приходить -1 вольт, на вход АЦП будет поступать +1 вольт. Если же сигнал, который хотим измерить нужно усилить, достаточно изменить номиналы резисторов R1 и R2.

Необходимо измерять только отрицательные напряжения, например, от -15 до 0.
В таком случае можно применить сумматор построенный на ОУ


Номиналы резисторов R1 и R2 рассчитываются следующим образом, когда Uвх = -15 вольт, суммарное падение напряжение на резисторах R1 и R2 равно 20 вольт. В этом случае на прямом входе ОУ должно быть 0 вольт, отсюда становится понятно, что на R1 упадёт 5 вольт, а на R2 упадёт 15 вольт, из этого следует, что номиналы резисторов должны соотносится как R2/R1 = 3/1. С другой стороны, так как резисторы соединены последовательно и через них течёт один и тот же ток, можно записать формулу.


Идём дальше, так как в схеме присутствует отрицательная обратная связь, напряжение на прямом и инверсном выводе должны быть равны. Когда Uвх = 0 на выходе ОУ будет 5 вольт(в данном случае ноль на входе - максимальное значение, значит на выходе должно быть максимальное значение равное 5 вольтам). В это же время на прямом входе ОУ будет 3.75 вольта, и эти же 3.75 будут на инверсном входе. Так как на выходе ОУ 5 вольт, а на инверсном входе 3.75, легко рассчитать соотношение R3 к R4(обычный делитель напряжения).


Предположив, что R1 и R4 равны 10К, получаем


R1 = 10К

R2 = 30К

R3 = 30К

R4 = 10К

Необходимо измерить напряжение, которое может изменяться от -10 до 10 вольт.

Сделать это очень просто, для этого надо создать смещение, чтобы при подаче -10 вольт на вход схемы на входе АЦП было 0 вольт, тогда при подаче 10 вольт на входе АЦП будет 5 вольт.

Реализовать это можно несколькими способами:

  • на резисторах


Номиналы резисторов рассчитываются очень просто, когда мы подаём на левый вход R2 -10 вольт на его правом выводе должно быть 0 вольт, в таком случае ток через R3 не течёт, так как на его концах отсутствует разность потенциалов.

Ток, протекающий через R2, равен


Ток, протекающий через R1, равен


Так как резисторы R1 и R2 соединены последовательно, то и токи, протекающие через них равны.


Предположим R2 равен 10K, тогда R1 равен 5K.

Ток через R2 равен току через R3, получаем


получаем

R1 = 5К

R2 = 10К

R3 = 10К

Минус схемы на резисторах, это то что R2 ограничивает ток, поступающий на вход АЦП и то что любой шум в цепи питания будет попадать на вход АЦП. Хотелось бы обратить внимание на то, что у АЦП есть такой параметр, как входное сопротивление, которое, как правило, зависит от частоты сэмплирования , ниже изображена таблица в которой показано как зависит сопротивление входа от периода преобразования АЦП для STM32


сопротивление источника сигнала должно быть меньше этого значения, а последовательно включеный резистор R2 явно его не уменьшает. Говоря простыми словами за короткий промежуток времени АЦП должно получить достаточный заряд чтобы работать с ним, а резистор, включённый последовательно с входом, не даёт этого сделать.

Этот недостаток можно исправить, собрав схему, которая обладает низким выходным сопротивлением, то есть может отдать большой ток.

  • сумматор на операционном усилителе


И снова нам поможет сумматор на операционном усилителе, как рассчитываются номиналы резисторов описано выше, но суть одна, надо взять два крайних значения, поступающего напряжения, при минимальном значении на выходе ОУ должен быть ноль, при максимальном должно быть 5 вольт(не забываем, что -VREF = 0 , а +VREF = 5 вольт). Если необходимо измерять положительное и отрицательное напряжение, в качестве смещения удобно использовать половину опорного напряжения, то есть 2.5 вольта.
Вот что получилось в микрокапе, картинку можно увеличить кликнув по ней.


Схема на ОУ обладает низким выходным сопротивлением, то есть может отдавать большой ток и может быть пересчитана для измерения других напряжений, например, ±2.5 вольта.
мы рассмотрим ещё несколько способов измерения отрицательного напряжения с помощью АЦП.

Ibrahim Kamal (IKALOGIC)

Примечание. Выборки исходного кода, размещенные в тексте описания, использовать в своих проектах не рекомендуется. В конце описания имеется ссылка на архив с полным исходным кодом к проекту.

Данная статья преследует учебные цели. Мы рассмотрим аппаратное решение и программную реализацию в задаче измерения уровня напряжения батареи (аккумулятора) с помощью микроконтроллера, который питается от этого же источника. Предполагается, что пользователи знакомы с программированием микроконтроллеров AVR и имеют базовые знания языка Си. Используемый компилятор - WinAVR.

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

Существует множество способов и решений для отслеживания уровня напряжения батареи питания, многие из них требуют использования внешних компонентов и узлов. Рассматриваемое нами решение не требует внешних компонентов, мы будем использовать лишь ресурсы и периферию микроконтроллера - встроенный АЦП.

Использовать будем микроконтроллер компании ATMEGA48 , но программный код полностью совместим с микроконтроллерами ATMEGA88 , ATMEGA168 , ATMEGA328 . Кроме того, немного исправив исходный код, можно применить данное решение для микроконтроллеров AVR со встроенным АЦП.

Пользователи, наверное задаются вопросом: «Неужели настолько сложен процесс измерения напряжения питания микроконтроллера?» Для решения этой задачи у нас есть микроконтроллер, и нам необходимо преобразовать аналоговую величину напряжения в цифровое значение, которое может использоваться микроконтроллером для дальнейших вычислений и действий.

Вы, наверное, скажете: «Так в чем же дело. Мы подключим положительный вывод батареи, от которой питается микроконтроллер, к входу АЦП и преобразуем величину напряжения в цифровое значение!».

Однако в этом случае вы будете не правы, это не так просто. Проблема в том, что источник напряжения используется для питания самого микроконтроллера (Vcc), а также в качестве источника опорного напряжения АЦП.

Если рассмотреть данную проблему с математической точки зрения, если вы понимаете проблему. В общем случае соотношение между измеренным напряжением и величиной в цифровой форме, преобразованной 8-разрядным АЦП, следующее:

,

где ADC_VALUE - значение полученное при аналого-цифровом преобразовании,
V_measure - измеренная величина напряжения, V_REF - опорное напряжение для АЦП.

Теперь, по условиям нашей задачи, мы знаем что V_measure = V_REF = Vcc и в итоге результатом уравнения всегда будет значение равное 255 и оно не будет изменяться при изменении напряжения батареи. Такая ситуация всегда будет иметь место при измерении напряжение батареи, которое также используется в качестве источника опорного напряжения.

Для решения задачи без использования каких-либо внешних компонентов, AVR микроконтроллер имеет очень полезный встроенный узел, называемый внутренний Band Gap источник опорного напряжения (Band Gap Reference Voltage). Выходное напряжение этого источника около 1.1 В, и оно остается неизменным при изменении температуры и напряжения питания микроконтроллера. Это напряжение может подаваться на вход АЦП, как и любое внешнее напряжение, с единственным исключением, что делается это программно, без включения дополнительных внешних компонентов.

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

Рассмотрим наше уравнение

ADC_VALUE = V_measure * 255/V_REF ,

Но, решая измерить опорное напряжение V_BG , мы получим следующее выражение

ADC_VALUE = V_BG * 255/V_REF

И так как в нашем случае опорное напряжение АЦП равно Vcc (основной момент нашей задачи), то уравнение примет вид

ADC_VALUE = V_BG * 255/Vcc

Зная, что V_BG=1.1 В , из уравнения мы можем вычислить напряжение питания микроконтроллера

Vcc = 1.1 * 255/ADC_VALUE

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

Рассмотрим пример реализации.

Принципиальная схема

Мы используем три NiCad аккумулятора для питания микроконтроллера. Напряжение питания, при полностью заряженных аккумуляторах, составит 4.2 В. Нам необходимо включить светодиод, подключенный к порту PB0, если напряжение будет ниже 3.2 В.

Листинг

#include avrio.h #include avrinterrupt.h
// Global variables
float vcc;//variable to hold the value of Vcc
void setup_adc(void)
{
ADMUX = 0xE; //Set the Band Gap voltage as the ADC input
ADCSRA = (1ADEN)|(1ADATE)|(1ADIE)|(1ADSC)|5;
}
ISR(ADC_vect) //ADC End of Conversion interrupt
{
unsigned char adc_data;
adc_data = ADC>>2; //read 8 bit value
vcc = 1.1 * 255 / adc_data;
}
// Main program
// ***********************************************************
int main(void)
{
DDRB = DDRB | (1PB0); //set PB0 as output (for the LED).
sei(); //Activate interrupts setup_adc();
//setup the ADC

while(1)
{
// Infinite loop
if (vcc < 3.2)
{
PORTB |= (1PB0);
}
else
{
PORTB &= ~(1PB0);
}
}
}

Следует учитывать, что напряжение V_BG будет разное у разных микроконтроллеров, особенно из разных партий, и может находиться в пределах 1.01 В - 1.2 В, следовательно необходима будет калибровка. Таким образом, если вычисленное значение Vcc с использованием данного кода неправильное, необходимо проделать следующие действия: измерить вольтметром напряжение питания Vсс и, используя уравнение ниже и зная значение ADC_VALUE , вычислить значение V_BG

Предисловие

В былые, доцифровые времена любому из нас приходилось довольствоваться стрелочными измерительными приборами, начиная от обыденных часов, весов и заканчивая… хм, так вот сразу даже и не найти границу их применения! Ну, скажем – прецизионный лабораторный микро- или еще внушительнее – пикоамперметр. И классов точности их тоже имелось достаточно много, в зависимости от назначения.

Вот, к примеру, обыкновенный указатель количества топлива в баке автомобиля является ярчайшим примером максимальной неточности показаний! Не знаю ни одного автомобилиста, который бы полагался на этот «показометр» и не заправлялся бы заблаговременно. Отпетые пессимисты от шоферов вообще без канистры топлива в багажнике не выезжали!

Зато в лабораториях, особенно в Госповерке, имелись стрелочники с зеркальной шкалой и класом точности много лучше 0,5.

И практически все из нас были довольны и счастливы. А если не были довольны, то приобретали более точные приборы, конечно по-возможности!

Но вот настал цифровой век. Все мы ему обрадовались, — теперь видим на индикаторах сразу числа и счастливы от предлагаемой нам «точности». Причем в нынешние времена эти вездесущие «цифровики» стоят на порядок меньше ставших раритетом «неточных стрелочников». Однако мало кто задумывается, что показываемые нам в цифре величины по-прежнему остались аналоговыми, будь это вес или сила тока – значения не имеет. А это значит, что измеряются эти величины по-прежнему аналогово! И лишь для обработки и представления преобразуются в цифровую величину. Вот тут-то и скрываются погрешности, приводящие нас к удивлению, когда два различных комнатных термометра в одном и том же месте показывают разные значения!

Путь от измеряемой величины к индикатору

Давайте взглянем на весь процесс измерения-индикации. Причем я умышленно выбираю электрическую величину. Во-первых, мы всё-таки на сайте электронщиков, а не теплофизиков или пекарей, да простят они мою вольность сравнения! Во-вторых, хочу укрепить рассуждения примерами из личного опыта.

Для начала я выбираю силу тока!

Мне придется повторить банальность, что для получения цифрового представления аналоговой величины необходим аналогово-цифровой преобразователь (АЦП). Но поскольку сам по себе он нам еще мало пригоден, то понадобятся и другие узлы для завершения всего задуманного. А именно:

  1. перед самим АЦП нужно нормирующее устройство, скажем: нормирующий усилитель или ослабитель, в зависимости от соотношения входной величины к диапазону преобразования АЦП;
  2. декодер после АЦП, для представления преобразованного числового эквивалента в цифровой код соответствующего индикатора.

Существуют готовые микросхемы, объединяющие в себе и АЦП и декодер. Например, ICL7136 или подобные, применяемые в мультиметрах.

По существу, все эти узлы в том или ином виде просто необходимы. Я еще не назвал самого датчика – в данном случае – преобразователь тока в напряжение, или просто шунт.

Итак, пробежимся вкратце по всей цепочке. Ток, протекающий через шунт (мощный резистор с очень низким сопротивлением), создает на его полюсах разность потенциалов. Guten Tag, Herr Ohm! Но эта разность довольно мала и не каждый АЦП способен эту величину в полной мере преобразовать, поэтому сигнал (напряжение) с шунта необходимо усилить до приемлемой величины. Для этого и нужен нормирующий усилитель. Теперь АЦП, получив на вход удобоперевариваемое напряжение, выполнит преобразование с минимально возможной погрешностью. На выходе из него получим число, соответствующее текущему значению измеренного тока в выбранном диапазоне, которое для вывода на индикатор нужно соответствующим образом декодировать. К примеру, преобразовать в код семисегментного индикатора.

Здесь я не вижу необходимости более подробно останавливаться на каждом из приведенных этапов, поскольку в статье я преследую иную цель. А подробности найдутся в интернете с избытком.

Конкретика

Есть у меня т.н. электронная нагрузка с индикатором силы протекающего тока. Базовая схема самой нагрузки есть и , но там для более точной установки тока потребуется внешний амперметр. Я же решил соединить оба устройства, чтобы экономить место и не разводить целую стаю мультиметров.

Мой встроенный амперметр собран и запрограммирован на МК Tiny26L. Частью этого амперметра является второй (свободный) ОУ микросхемы LM358, входящей в составбазовой схемы балласта. Т.е. это мой нормирующий усилитель, поскольку максимальное падение напряжения на шунте (5 А х 0,1 ом) составляет всего 0,5 вольта, что явно недостаточно для полного диапазона преобразования с внутренним опорным напряжением.

Согласно Т.О. (англ.= Datasheet) номинальное напряжение встроенного опорного источника (ИОН) составляет 2,56 вольта. Очень удобная величина! Однако, на практике получается не так уж и здорово: выверенное напряжение ИОН-а моего МК оказалось 2,86 вольта! Каким образом я это определил – отдельная тема. Давайте все-таки вернемся к удобным 2,56 вольтам. Смотрите, что получается: на шунте падает максимально 0,5 вольта, АЦП преобразует максимально 2,56 вольта. Напрашивается нормирующий усилитель с коэффициентом усиления 5, тогда и полученное при преобразовании число не потребует какой-либо развитой арифметики для представления результата: 5 ампер = 2,5 вольта = 250 единиц (для 8-битного преобразования). Придется всего лишь умножить результат на два и поставить десятичную точку между сотнями и десятками, чтобы получить совсем удобное представление: единицы, десятые и сотые доли ампера. Конечное преобразование в семисегментные знаки – дело техники. Всё прекрасно, можно воплощать в «железо»!

Однако, как я уже показал на примере встроенного ИОН-а, приемлемой (я уже не говорю – высокой!) точности на используемых компонентах получить так легко не получится. Можно пойти по пути компенсации погрешностей математически, с помощью программы в МК, хотя для этого придется производить градуировку. Этот путь довольно просто реализуется на Си и других языках высокого уровня. Но мне, упертому ассемблерщику, разводить математику инструкциями RISC – лишняя головная боль!

Я выбрал другой путь, — коррекцию коеффициента усиления нормирующего усилителя (НУ). Много для этого не потребуется – один подстроечный резистор! Значение его нужно правильно выбрать, чтобы диапазон подстройки был достаточным, но не преувеличенным.

Подбор элементов нормирующего усилителя

Итак, необходимо определить диапазон подстройки. Первым делом нужно определиться с допусками компонентов. Например, мой шунт имеет допустимую погрешность 1%. Прочие резисторы в схеме нормирующего усилителя могут имеют допуск до10%. И не забываем неточность нашего ИОН-а, которая составила в моем случае почти +12%! Это значит, что реально преобразованное число будет меньше почти на 12%. Но поскольку эта погрешность у меня уже известна, то я учитываю ее в коэффициенте усиления НУ, который должен составить 5,72. А поскольку реальные погрешности прочих компонентов не известны, то остается найти максимально возможную суммарную погрешность, чтобы расчитать диапазон подстройки.

Напрашивается простая сумма этих вот «процентов»: 1% шунта плюс 2 раза по 10% резистороров обратной связи ОУ. Итого: 21%.

Посмотрим, так ли это на самом деле. Для этого взглянем на часть схемы, где представлен этот НУ с уже подобранными номиналами:

Как видно, имеет место неинвертирующий усилитель с перестраиваемым коэффициентом передачи, теоретически регулируемым от 4,979 до 6,735 при указанных на схеме номиналах. Но, если учесть наши ±10% возможной погрешности каждого из резисторов, то получим при найхудшем сочетании Ку = 5,864 – 8,009 , что явно превышает необходимый коэффициент! Если это сочетание будет иметь место, то придется взять другие номиналы. А лучше сразу увеличить номинал подстроечного резистора, например, до 39к. Тогда нижняя граница Ку будет 5,454 , что уже приемлемо.

Ну, мне – «настоящему радиохламеру» — пришлось выбирать подстроечник из того, что было, и просто повезло вложиться в диапазон! Был бы подстроечник другого номинала – не беда, пересчитал бы R2 и R3, которые в моем случае имеют допуск 5%, поэтому мне не пришлось брать другой подстроечник.

Преодоление своих недочетов и упущений

Казалось бы, всё продумано и расчитано – разводи плату. А давай-ка испытаем эту конструкцию сперва на макетке! Сказано – сделано! Ку перестраивается не совсем как ожидалось, но в пределах необходимого. Однако индикатор не собирался показывать 0.00 при отсутствии тока нагрузки! Первым делом я заподозрил программу в МК, но при закорачивании входа АЦП на общий провод заветные нолики появлялись. Значит, что-то таки приходит на вход МК, отличное от нуля вольт. Проверка мультиметром подтвердила это предположение и поставила очередную задачу. Не вдаваясь в подробности моих изысканий, опишу лишь их результат.

Причина оказалась в следующем: я совершенно не учел, что примененный мною ОУ далеко не лучшего качества. Он даже не т.н. «rail-to-rail». Это означает, что его выходной потенциал никогда не достигнет ни одного из полюсов питания, т.е. в моем случае никогда не будет равен 0 вольт! Вот если бы он питался от двуполярного источника, тогда бы на выходе получился ожидаемый ноль. Но у меня источник питания однополярный и усложнять схему каким-либо преобразователем я не намеревался. Выход был найден в создании «виртуальной земли», т.е. благодаря отдельному источнику питания (в отличие от базовой схемы) мне удалось с помошью диода сдвинуть потенциал общего провода относительно минусового полюса батареи.

Итак, плата вытравлена и спаяна. Пора бы эту конструкцию упаковать в корпус. Что, собственно, и было сделано. Однако, во время эксплуатации вылез еще один маленький недочет – дрейф входных цепей ОУ. Это выражалось в отрицательном сдвиге показаний, т.е. при токе в пару десятков миллиампер на индикаторе по-прежнему были нули, что меня не устраивало! Я бы допустил сдвиг в несколько мА – все равно единицы миллиампер не отображаются. Пришлось вводить схему смещения на вход НУ.

Номиналы R4 и RZ подобраны так, что бы обеспечить смещение плюс/минус несколько десятков милливольт относительно «виртуальной земли». У меня не было желания переделывать готовую плату и я довесил необходимый подстраиваемый делитель на место подстроечника Ку.

В общем и целом получившийся приборчик удовлетворяет мои потребности. Усовершенствовать его, конечно же, можно еще долго, но пока нет необходимости!

О цифровой части и математике я расскажу в следующий раз на примере вольт-амперметра лабораторного блока питания.

Микроконтроллеры ATmega (как и некоторые модели семейства ATtiny) имеют 10-битные модули АЦП, которые могут использоваться для измерения аналогового напряжения. Эти АЦП являются логометрическими , то есть они производят измерение относительно некоего базового уровня (обычно Vcc).
В случае Arduino-совместимых плат, которые запитываются стабилизированным напряжением 5 В, это означает, что у вы можете производить измерения в диапазоне 0..5 В, различая уровни 0..1023, достигая при этом разрешения около 5 мВ на шаг.
Если есть “вольтметр”, то рано или поздно возникнет желание контролировать с его помощью напряжение, подаваемое на выводы питания микроконтроллера.
Первое решение, приходящее в голову – соединить ногу Vcc с одним из аналоговых входов и вызвать функцию analogRead(). Не тут то было – какое бы напряжение ни подавалось в качестве питания микроконтроллера, АЦП будет возвращать одну и ту же величину – 1023.
Так как же определить, что за напряжение питает наш микроконтроллер? Ведь это жизненно необходимо при автономном питании, так как может своевременно выявить момент исчерпания заряда батарей.
На помощь может прийти имеющийся в каждой (ну, ладно – почти в каждой) модели ATmega/ATtiny источник опорного напряжения, выдающий ровно (ну, ладно – примерно) 1,1 В. Если мы прочитаем это напряжение, используя в качестве опорного напряжение питания (Vcc), то, выполнив нескольких арифметических действий, сможем получить вожделенное значение. Итак:

  • предположим, что наш АЦП вернул значение “x”, которое соответствует напряжению 1.1 В
  • имея 5 В в качестве Vcc, мы должны будем получить значение, примерно равное 1100 / 5000 * 1023 = 225
  • ну, а если бы то же самое мы проделали бы при Vcc=3.3 В, то должны были получить значение 1100 / 3300 * 1023 = 341
  • или в общем случае: 1100 / Vcc * 1023 = x
  • выполнив несложные преобразования, найдем, что Vcc = 1100 / x * 1023

То есть, нам необходимо измерить внутреннее опорное напряжение 1,1 В, и тогда мы сможем сказать, что же за напряжение Vcc питает наш микроконтроллер!
“Нормально, Григорий? Отлично, Константин!”
Но погодите радостно потирать руки: к превеликому сожалению широко используемую в Arduino-кругах функцию analogRead() не удастся заставить измерить внутреннее опорное напряжение. Придется идти в обход…

А точнее – заглянуть в даташит и, почерпнув там некоторые сведения, произвести нужное преобразование вручную. Вот так это будет выглядеть для Arduino:

Static int vccRead(byte us =250) { ADMUX = 1<

В код функции vccRead введена задержка us, позволяющая стабилизировать результаты измерений и повысить их точность. Небольшой числовой эксперимент показывает, что оптимальные результаты достигаются при задержке от 100 мкс.

Вот какие результаты получились у меня для разных значений задержки при питании от USB:

10 мкс 50 мкс 100 мкс 200 мкс 300 мкс
3049
4278
4295
4137
4167
4311
4311
4152
4121
4311
3827
4829
4871
4808
4748
4829
4850
4829
4829
4808
4669
5068
5091
5068
5068
5091
5091
5068
5068
5091
5138
5138
5138
5138
5161
5138
5138
5138
5161
5138
3641
4688
4768
4768
4688
4748
4768
4768
4748
4650