Точный вольтметр на arduino. Аналоговые входы и подтягивающие резисторы. Запись и чтение данных последовательного порта

Аналоговые входы платы Ардуино.

Плата Arduino UNO содержит 6 аналоговых входов предназначенных для измерения напряжения сигналов. Правильнее сказать, что 6 выводов платы могут работать в режиме, как дискретных выводов, так и аналоговых входов.

Эти выводы имеют номера от 14 до 19. Изначально они настроены как аналоговые входы, и обращение к ним можно производить через имена A0-A5. В любой момент их можно настроить на режим дискретных выходов.

pinMode(A3, OUTPUT); // установка режима дискретного вывода для A3
digitalWrite(A3, LOW); // установка низкого состояния на выходе A3

Чтобы вернуть в режим аналогового входа:

pinMode(A3, INPUT); // установка режима аналогового входа для A3

Аналоговые входы и подтягивающие резисторы.

К выводам аналоговых входов, так же как и к дискретным выводам, подключены подтягивающие резисторы. Включение этих резисторов производится командой

digitalWrite(A3, HIGH); // включить подтягивающий резистор к входу A3

Команду необходимо применять к выводу настроенному в режиме входа.

Надо помнить, что резистор может оказать влияние на уровень входного аналогового сигнала. Ток от источника питания 5 В, через подтягивающий резистор, вызовет падение напряжения на внутреннем сопротивлении источника сигнала. Так что лучше резистор отключать.

Аналого-цифровой преобразователь платы Ардуино.

Собственно измерение напряжение на входах производится аналого-цифровым преобразователем (АЦП) с коммутатором на 6 каналов. АЦП имеет разрешение 10 бит, что соответствует коду на выходе преобразователя 0…1023. Погрешность измерения не более 2 единиц младшего разряда.

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

Программные функции аналогового ввода.

int analogRead(port)

Считывает значение напряжения на указанном аналоговом входе. Входное напряжение диапазона от 0 до уровня источника опорного напряжения (часто 5 В) преобразовывает в код от 0 до 1023.

При опорном напряжении равном 5 В разрешающая способность составляет 5 В / 1024 = 4,88 мВ.

Занимает на преобразование время примерно 100 мкс.

int inputCod; // код входного напряжения
float inputVoltage; // входное напряжение в В

inputCod= analogRead(A3); // чтение напряжения на входе A3
inputVoltage= ((float)inputCod * 5. / 1024.); // пересчет кода в напряжение (В)

void analogReference(type)

Задает опорное напряжение для АЦП. Оно определяет максимальное значение напряжения на аналоговом входе, которое АЦП может корректно преобразовать. Величина опорного напряжения также определяет коэффициент пересчета кода в напряжение:

Напряжение на входе = код АЦП * опорное напряжение / 1024.

Аргумент type может принимать следующие значения:

  • DEFAULT – опорное напряжение равно напряжению питания контроллера (5 В или 3,3 В). Для Arduino UNO R3 – 5 В.
  • INTERNAL – внутреннее опорное напряжение 1,1 В для плат с контроллерами ATmega168 и ATmega328, для ATmega8 – 2,56 В.
  • INTERNAL1V1 – внутреннее опорное напряжение 1,1 В для контроллеров Arduino Mega.
  • INTERNAL2V56 – внутреннее опорное напряжение 2,56 В для контроллеров Arduino Mega.
  • EXTERNAL – внешний источник опорного напряжения, подключается к входу AREF.

analogReference(INTERNAL); // опорное напряжение равно 1,1 В

Двухканальный вольтметр на Ардуино.

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

Решим, что вольтметр должен измерять напряжение в пределах не меньше 0…20 В и разработаем схему подключения входов вольтметра к плате Arduino UNO.

Если мы зададим опорное напряжение равным 5 В, то аналоговые входы платы будут измерять напряжение в пределах 0…5 В. А нам надо как минимум 0…20 В. Значит надо использовать делитель напряжения.

Напряжение на входе и выходе делителя связаны соотношением:

Uвыхода = (Uвхода / (R1 + R2)) * R2

Коэффициент передачи:

K = Uвыхода / Uвхода = R2 / (R1 + R2)

Нам необходим коэффициент передачи 1/4 (20 В * 1/4 = 5 В).

Для сохранения максимальной точности (10 разрядов) необходимо, чтобы внутреннее сопротивление источника сигнала не превышало 10 кОм. Поэтому выбираем резистор R2 равным 4,22 кОм. Рассчитываем сопротивление резистора R1.

0,25 = 4,22 / (R1 + 4,22)
R1 = 4,22 / 0.25 – 4,22 = 12,66 кОм

У меня с ближайшим номиналом нашлись резисторы сопротивлением 15 кОм. С резисторами R1 = 15 кОм и R2 = 4,22:

5 / (4,22 / (15 + 4,22)) = 22,77 В.

Схема вольтметра на базе Ардуино будет выглядит так.

Два делителя напряжения подключены к аналоговым входам A0 и A1. Конденсаторы C1 и C2 вместе с резисторами делителя образуют фильтры нижних частот, которые убирают из сигналов высокочастотные шумы.

Я собрал эту схему на макетной плате.

Первый вход вольтметра я подключил к регулируемому источнику питания, а второй к питанию 3,3 В платы Ардуино. Для контроля напряжения к первому входу я подключил вольтметр. Осталось написать программу.

Программа для измерения напряжения с помощью платы Ардуино.

Алгоритм простой. Надо:

  • с частотой два раза в секунду считывать код АЦП;
  • пересчитывать его в напряжение;
  • посылать измеренные значения по последовательному порту на компьютер;
  • программой монитор порта Arduino IDE отображать полученные значения напряжений на экране компьютера.

Приведу скетч программы сразу полностью.

// программа измерения напряжения
// на аналоговых входах A0 и A1

#include

время периода измерения
#define R1 15. // сопротивление резистора R1
#define R2 4.22 // сопротивление резистора R2


float u1, u2; // измеренные напряжения

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

MsTimer2::start(); // разрешение прерывания
}

void loop() {

// период 500 мс
if (timeCount >= MEASURE_PERIOD) {
timeCount= 0;

//

// чтение кода канала 2 и пересчет в напряжение
u2= ((float)analogRead(A1)) * 5. / 1024. / R2 * (R1 + R2);

// передача данных через последовательный порт
Serial.print("U1 = "); Serial.print(u1, 2);
Serial.print(" U2 = "); Serial.println(u2, 2);
}
}

// обработка прерывания 1 мс
void timerInterupt() {
timeCount++;
}

Поясню строчку, в которой пересчитывается код АЦП в напряжение:

// чтение кода канала 1 и пересчет в напряжение
u1= ((float)analogRead(A0)) * 5. / 1024. / R2 * (R1 + R2);

  • Считывается код АЦП: analogRead(A0) .
  • Явно преобразуется в формат с плавающей запятой: (float) .
  • Пересчитывается в напряжение на аналоговом входе: * 5. / 1024. Точка в конце чисел показывает, что это число с плавающей запятой.
  • Учитывается коэффициент передачи делителя: / R2 * (R1 + R2) .

Загрузим программу в плату, запустим монитор последовательного порта.

Два бегущих столбика показывают значения измеренных напряжений. Все работает.

Измерение среднего значения сигнала.

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

Значения напряжения первого канала на экране монитора все время дергаются, скачут. А показания контрольного вольтметра вполне стабильны. Это объясняется тем, что контрольный вольтметр измеряет среднее значение сигнала, в то время как плата Ардуино считывает отдельные выборки каждые 500 мс. Естественно, момент чтения АЦП попадает в разные точки сигнала. А при высоком уровне пульсаций амплитуда в этих точках разная.

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

Решение – сделать несколько частых выборок и усреднить измеренное значение. Для этого:

  • в обработчике прерывания считываем код АЦП и суммируем его с предыдущими выборками;
  • отсчитываем время усреднения (число выборок усреднения);
  • при достижении заданного числа выборок – сохраняем суммарное значение кодов АЦП;
  • для получения среднего значения сумму кодов АЦП делим на число выборок усреднения.

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

// программа измерения среднего напряжения
// на аналоговых входах A0 и A1

#include

#define MEASURE_PERIOD 500 // время периода измерения
#define R1 15. // сопротивление резистора R1
#define R2 4.22 // сопротивление резистора R2

int timeCount; // счетчик времени
long sumU1, sumU2; // переменные для суммирования кодов АЦП
long avarageU1, avarageU2; // сумма кодов АЦП (среднее значение * 500)
boolean flagReady; // признак готовности данных измерения

void setup() {
Serial.begin(9600); // инициализируем порт, скорость 9600
MsTimer2::set(1, timerInterupt); // прерывания по таймеру, период 1 мс
MsTimer2::start(); // разрешение прерывания
}

void loop() {

if (flagReady == true) {
flagReady= false;
// пересчет в напряжение и передача на компьютер
Serial.print("U1 = ");
Serial.print((float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
Serial.print(" U2 = ");
Serial.println((float)avarageU2 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
}
}

// обработка прерывания 1 мс
void timerInterupt() {

timeCount++; // +1 счетчик выборок усреднения
sumU1+= analogRead(A0); // суммирование кодов АЦП
sumU2+= analogRead(A1); // суммирование кодов АЦП

// проверка числа выборок усреднения
if (timeCount >= MEASURE_PERIOD) {
timeCount= 0;
avarageU1= sumU1; // перегрузка среднего значения
avarageU2= sumU2; // перегрузка среднего значения
sumU1= 0;
sumU2= 0;
flagReady= true; // признак результат измерений готов
}
}

В формулу пересчета кода АЦП в напряжение добавилось /500 – число выборок. Загружаем, запускаем монитор порта (Cntr+Shift+M).

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

Число выборок надо выбирать, учитывая:

  • число выборок определяет время измерения;
  • чем больше число выборок, тем меньше будет влияние помех.

Основным источником помех в аналоговых сигналах является сеть 50 Гц. Поэтому желательно выбирать время усреднения кратное 10 мс – времени полупериода сети частотой 50 Гц.

Оптимизация вычислений.

Вычисления с плавающей запятой просто пожирают ресурсы 8ми разрядного микроконтроллера. Любая операция с плавающей запятой требует денормализацию мантиссы, операцию с фиксированной запятой, нормализацию мантиссы, коррекцию порядка… И все операции с 32 разрядными числами. Поэтому необходимо свести к минимуму употребление вычислений с плавающей запятой. Как это сделать я расскажу в следующих уроках, но давайте хотя бы оптимизируем наши вычисления. Эффект будет значительный.

В нашей программе пересчет кода АЦП в напряжение записан так:

(float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2)

Сколько здесь вычислений, и все с плавающей запятой. А ведь большая часть вычислений – операции с константами. Часть строки:

/ 500. * 5. / 1024. / R2 * (R1 + R2)

(float)avarageU1 * 0.00004447756

Умные компиляторы сами распознают вычисления с константами и рассчитывать их на этапе компиляции. У меня возник вопрос, насколько умный компилятор Андруино. Решил проверить.

Я написал короткую программу. Она выполняет цикл из 10 000 проходов, а затем передает на компьютер время выполнения этих 10 000 циклов. Т.е. она позволяет увидеть время выполнения операций, размещенных в теле цикла.

// проверка оптимизации вычислений

int x= 876;
float y;
unsigned int count;
unsigned long timeCurrent, timePrev;

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

void loop() {
count++;
// y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);
// y= (float)x * 0.00004447756 ;

if (count >= 10000) {
count= 0;
timeCurrent= millis();
Serial.println(timeCurrent - timePrev);
timePrev= timeCurrent;
}
}

В первом варианте, когда в цикле операции с плавающей запятой закомментированы и не выполняются, программа выдала результат 34 мс.

Т.е. 10 000 пустых циклов выполняются за 34 мс.

Затем я открыл строку:

y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);

повторяет наши вычисления. Результат 10 000 проходов за 922 мс или

(922 – 34) / 10 000 = 88,8 мкс.

Т.е. эта строка вычислений с плавающей запятой требует на выполнение 89 мкс. Я думал будет больше.

Теперь я закрыл эту строку комментарием и открыл следующую, с умножением на заранее рассчитанную константу:

y= (float)x * 0.00004447756 ;

Результат 10 000 проходов за 166 мс или

(166 – 34) / 10 000 = 13,2 мкс.

Потрясающий результат. Мы сэкономили 75,6 мкс на одной строке. Выполнили ее почти в 7 раз быстрее. У нас таких строк 2. Но ведь их в программе может быть и гораздо больше.

Вывод – вычисления с константами надо производить самим на калькуляторе и применять в программах как готовые коэффициенты . Компилятор Ардуино их на этапе компиляции не рассчитает. В нашем случае следует сделать так:

#define ADC_U_COEFF 0.00004447756 // коэффициент перевода кода АЦП в напряжение

Serial.print((float)avarageU1 * ADC_U_COEFF, 2);

Оптимальный по быстродействию вариант – это передать на компьютер код АЦП, а вместе с ним и все вычисления с плавающей запятой. При этом на компьютере принимать данные должна специализированная программа. Монитор порта из Arduino IDE не подойдет.

О других способах оптимизации программ Ардуино я буду рассказывать в будущих уроках по мере необходимости. Но без решения этого вопроса невозможно разрабатывать сложные программы на 8ми разрядном микроконтроллере.

На сайте появился еще один урок (

В этой статье приводится интересная схема для любителей экспериментов и Arduino . В ней представлен простой цифровой вольтметр, который может безопасно измерять постоянное напряжение в диапазоне от 0 до 30 В. Сама плата Arduino может питаться от стандартного источника 9 В.



Как известно, с помощью аналогового входа Arduino можно измерить напряжение от 0 до 5 В (при стандартном опорном напряжении 5 В). Но этот диапазон можно расширить, воспользовавшись делителем напряжения.


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



Аналоговый датчик в составе Arduino определяет напряжение на аналоговом входе и преобразует его в цифровой формат, воспринимаемый микроконтроллером. К аналоговому входу A0 мы подключаем делитель напряжения, образованный сопротивлениями R1 (100K) и R2 (10K). С такими значениями сопротивлений на Arduino можно подавать до 55 В, поскольку коэффициент деления в данном случае получается 11, поэтому 55В/11=5В. Для того, чтобы быть уверенным в безопасности измерений для платы, лучше проводить измерение напряжения в диапазоне от 0 до 30 В.



Если показания дисплея не соответствуют показанием поверенного вольтметра, следует использовать прецизионный цифровой мультиметр для нахождения точных значений R1 и R2. При этом в коде нужно будет заменить R1=100000.0 и R2=10000.0 своими значениями. Затем стоит проверить питание, измерив на плате напряжение между 5V и GND. Напряжение может быть 4.95 В. Тогда в коде vout = (value * 5.0) / 1024.0 нужно заменить 5.0 на 4.95. Желательно использовать прецизионные резисторы с погрешностью не более 1%. Помните, что напряжение выше 55 В может вывести плату Arduino из строя!



#include LiquidCrystal lcd(7, 8, 9, 10, 11, 12); int analogInput = 0; float vout = 0.0; float vin = 0.0; float R1 = 100000.0; // сопротивление R1 (100K) float R2 = 10000.0; // сопротивление R2 (10K) int value = 0; void setup(){ pinMode(analogInput, INPUT); lcd.begin(16, 2); lcd.print("DC VOLTMETER"); } void loop(){ // считывание аналогового значения value = analogRead(analogInput); vout = (value * 5.0) / 1024.0; vin = vout / (R2/(R1+R2)); if (vin<0.09) { vin=0.0;// обнуляем нежелательное значение } lcd.setCursor(0, 1); lcd.print("INPUT V= "); lcd.print(vin); delay(500); }


Используемые элементы:


Плата Arduino Uno
Резистор 100 КОм
Резистор 10 КОм
Резистор 100 Ом
Потенциометр 10 КОм
LCD-дисплей 16×2

Исходные данные и доработка

Итак к этому момент у нас есть вольтметр постоянного напряжения с пределом 0..20в (смотрите предыдущую часть). Теперь мы добавляем к нему амперметр 0..5а. Для этого немного модифицируем схему - она станет проходной, то есть имеет как вход так и выход.

Часть касающуюся отображения на LCD я убрал - она не будет меняться. Впринципе основной новый элемент - шунт Rx на 0.1 Ом. Цепочка R1-C1-VD1 служит для защиты аналогового входа. Такую же имеет смысл поставить и по входу A0. Поскольку мы предполагаем достаточно большие токи, есть требования к монтажу - силовые линии должны быть выполнены достаточно толстым проводом и соединяться с выводами шунта непосредственно (проще говоря, припаяны), иначе показания будут далеки от реальности. Есть так же замечание по току - впринципе опорное напряжение 1.1в позволяет регистрировать на шунте 0.1 Ом ток до 11 ампер с точностью немного хуже 0.01а, но при падении на Rх такого напряжения выделяемая мощность превысит 10 Вт, что совсем не весело. Для решения проблемы можно было бы использовать усилитель с коэффициентом усиления 11 на качественном ОУ и шунт на 10 мОм (0.01Ом). Но пока мы не будем усложнять себе жизнь и просто ограничимся в токе до 5а (при этом мощность Rx можно выбрать порядка 3-5 Вт).

На этом этапе меня ждал сюрприз - оказалось что АЦП контроллера имеет достаточно большое смешение нуля - около -3мВ. То есть АЦП просто не видит сигналы менее 3мВ, а сигналы чуть большего уровня видны с характерной неточностью -3мВ, что портит линейность в начале диапазона. Беглый поиск не дал явных ссылок на такую проблему (смещение нуля это нормально, но оно должно быть существенно меньше), поэтому вполне возможно это проблема конкретного экземпляра Atmega 328. Решение я выбрал двоякое - по напряжению - программную ступеньку в начале диапазона (отображение начинается с 0.06 вольт), по току - подтягивающий резистор на шину 5в. Резистор обозначен пунктиром.

Исходный код

Полную версию этого вольт-ампер-метра (в варианте с I2C) можно скачать по ссылке в конце статье. Далее я покажу изменения в исходном коде. Добавилось чтение аналогового входа A1 с таким же усреднением как и для вольтметра. По сути это тот же вольтметр, только без делителя, а амперы мы получаем по формуле Ома: I = U/Rx (например, если падение напряжения на Rx = 0.01 В, то ток равен 0.1А). Также я ввел константу усиления по току AmpMult - на будущее. Константу AmpRx с сопротивлением шунта вероятно придется подобрать - учесть неточность резистора шунта. Ну и раз уже это это вольт-ампер-метр и на дисплее 1602 еще осталось место, то осталось вывести текущую потребляемую мощность в ваттах, получив не сложный дополнительный функционал.

.... // Аналоговый вход #define PIN_VOLT A0 #define PIN_AMP A1 // Внутреннее опорное напряжение (подобрать) const float VRef = 1.10; // Коэффициент входного резистивного делителя (Rh + Rl) / Rl. IN 0.2) InVolt += 3; // Перевод в вольты (In: 0..1023 -> (0..VRef) scaled by Mult) float Volt = InVolt * VoltMult * VRef / 1023; float Amp = InAmp * VRef / AmpMult / AmpRx / 1023 ; // Для учета падения на шунте раскомментировать 2 строки //float RxVolt = InAmp * VRef / 1023 / AmpMult; // Volt -= RxVolt; float Watt = Volt * Amp; // Вывод данных lcd.setCursor (8, 0); lcd.print(Watt); lcd.print("W "); lcd.setCursor (0, 1); lcd.print(Volt); lcd.print("V "); lcd.setCursor (8, 1); lcd.print(Amp); lcd.print("A "); }

Ссылки

  • Библиотека LiquidCrystal_I2C , позволяющая задать распиновку

Представлена полезная схема для любителей поэкспериментировать с Ардуино. Это простой цифровой вольтметр, которым надежно можно измерять постоянное напряжение в диапазоне 0 – 30В. Плату Ардуино, как обычно, можно питать от 9В батареи.

Как вам вероятно известно, аналоговые входы Ардуино можно использовать для измерения постоянного напряжения в диапазоне 0 – 5В и этот диапазон можно увеличить,
используя два резистора в качестве делителя напряжения. Делитель уменьшит измеряемое напряжение до уровня аналоговых входов Ардуино. А затем программа вычислит реальную величину напряжения.

Аналоговый датчик на плате Ардуино определяет наличие напряжения на аналоговом входе и преобразует его в цифровую форму для дальнейшей обработки микроконтроллером. На рисунке напряжение подается на аналоговый вход (А0) через простой делитель напряжения, состоящий из резисторов R1 (100кОм) и R2 (10кОм).

При этих значениях делителя на плату Ардуино можно подавать напряжение от 0 до
55В. На входе А0 имеем измеряемое напряжение деленное на 11,т.е.55В / 11=5В. Иначе говоря, при измерении 55В на входе Ардуино имеем максимально допустимое значение 5В. На практике лучше на этом вольтметре написать диапазон “0 – 30В”, чтобы оставался
Запас по безопасности!

Примечания

Если показания дисплея не совпадают с показаниями промышленного (лабораторного) вольтметра, то необходимо точным прибором измерить величину сопротивлений R1 и R2 и вставить эти значения вместо R1=100000.0 и R2=10000.0 в коде программы. Затем следует измерить лабораторным вольтметром реальное напряжение между выводами 5В и “Земля” платы Ардуино. Получится значение меньшее, чем 5В, например, получилось 4.95В. Это реальное значение следует вставить в строке кода
vout = (value * 5.0) / 1024.0 вместо 5.0.
Кроме того, старайтесь применять прецизионные резисторы с допуском 1%.

Резисторы R1 и R2 обеспечивают некоторую защиту от повышенных входных напряжений.Однако следует помнить, что любые напряжения выше 55В могут вывести из строя плату Ардуино. Кроме того, в этой конструкции не предусмотрены другие виды защиты(от скачков напряжения, от переполюсовки или повышенного напряжения).

Программа цифрового вольтметра

/*
DC Voltmeter
An Arduino DVM based on voltage divider concept
T.K.Hareendran
*/
#include
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int analogInput = 0;
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // resistance of R1 (100K) -see text!
float R2 = 10000.0; // resistance of R2 (10K) – see text!
int value = 0;
void setup(){
pinMode(analogInput, INPUT);
lcd.begin(16, 2);
lcd.print(“DC VOLTMETER”);
}
void loop(){
// read the value at analog input
value = analogRead(analogInput);
vout = (value * 5.0) / 1024.0; // see text
vin = vout / (R2/(R1+R2));
if (vin<0.09) {
vin=0.0;//statement to quash undesired reading !
}
lcd.setCursor(0, 1);
lcd.print(“INPUT V= “);
lcd.print(vin);
delay(500);
}

Принципиальная схема Ардуино-вольтметра

Перечень компонентов

Плата Arduino Uno
100 кОм резистор
10 кОм резистор
100 Ом резистор
10кОм Подстроечный резистор
LCD дисплей 16?2 (Hitachi HD44780)

Привет, Хабр! Сегодня хочу продолжить тему «скрещивания» arduino и android. В предыдущей публикации я рассказал про bluetooth машинку , а сегодня речь пойдет про DIY bluetooth вольтметр. Еще такой девайс можно назвать смарт вольтметр, «умный» вольтметр или просто умный вольтметр, без кавычек. Последнее название является неправильным с точки зрения грамматики русского языка, тем не менее частенько встречается в СМИ. Голосование на эту тему будет в конце статьи, а начать предлагаю с демонстрации работы устройства, чтобы понять о чем же пойдет речь в статье.


Disclaimer: статья рассчитана на среднестатистического любителя arduino, который обычно не знаком с программированием под android, поэтому как и в прошлой статье, приложение для смартфона мы будем делать, используя среду визуальной разработки android-приложений App Inventor 2.
Чтобы сделать DIY bluetooth вольтметр нам нужно написать две относительно независимых друг от друга программы: скетч для ардуино и приложение для андроид.Пожалуй начнем со скетча.
Для начала следует знать, что существует три основных варианта измерения напряжения при помощи ардуино, не зависимо от того куда нужно выводить информацию: в com-порт, на подключенный к ардуино экранчик, или на смартфон.
Первый случай: измерения напряжения до 5 вольт. Здесь достаточно одной-двух строк кода, а напряжение подается напрямую на пин А0:
int value = analogRead(0);// читаем показания с А0
voltage = (value / 1023.0) * 5; // верно только если Vcc = 5.0 вольт
Второй случай: для измерения напряжения более 5 вольт используется делитель напряжения. Схема очень простая, код тоже.

Скетч

int analogInput = A0;
float val = 0.0;
float voltage = 0.0;
float R1 = 100000.0; //Battery Vin-> 100K -> A0
float R2 = 10000.0; //Battery Gnd -> Arduino Gnd and Arduino Gnd -> 10K -> A0
int value = 0;

Void setup() {
Serial.begin(9600);
pinMode(analogInput, INPUT);
}

Void loop() {
value = analogRead(analogInput);
val = (value * 4.7) / 1024.0;
voltage = val / (R2/(R1+R2));
Serial.println(voltage);
delay(500);
}


Arduino Uno
Блютуз модуль
Третий случай. Когда нужно получить более точные о напряжении в качестве опорного напряжения нужно использовать не напряжение питания, которое может немного меняться при питании от акб, например, а напряжение внутренного стабилизатора ардуино 1.1 вольт.Тут схема такая же, но код чуть длиннее. Подробно этот вариант разбирать не буду, так как он и так хорошо описан в тематических статьях, а мне вполне и достаточно второго способа, поскольку питание у меня стабильное, от usb-порта ноутбука.
Итак с измерением напряжения мы разобрались, теперь перейдем ко второй половине проекта: созданию андроид-приложения. Приложение будем делать прямо из браузера в среде визуальной разработки android-приложений App Inventor 2. Заходим на сайт appinventor.mit.edu/explore , авторизуемся с помощью гугл-аккаунта, нажимаем кнопку create, new project, и путем простого перетаскивания элементов создаем примерно такой дизайн:

Я сделал графику очень простой, если кому-то захочется более интересной графики, напомню, что для этого нужно использовать вместо.jpeg файлов, файлы формата.png с прозрачным фоном.
Теперь переходим во вкладку Blocks и создаем там логику работы приложения примерно так:


Если все получилось можно нажимать кнопку Build и save .apk to my computer, а затем уже скачиваем и устанавливаем приложение на смартфон, хотя есть и другие способы заливки приложения. тут уж кому как удобнее. В итоге у меня получилось вот такое приложение:


Понимаю, что мало кто использует среду визуальной разработки android-приложений App Inventor 2 в своих проектах, поэтому может возникнуть много вопросов по поводу работы в ней. Чтобы снять часть таких вопросов, я сделал подробное видео, о том как сделать такое приложение «с нуля»(для просмотра нужно перейти на ютуб):

P.S. Сборник из более 100 обучающих материалов по ардуино для начинающих и профи


Top