6 канальный вольтметр на ардуино. Bluetooth вольтметр на базе arduino

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

  • В уроке мы использовали плату совместимую с Ардуино - SunFounder Uno / Mars (http://bit.ly/2tkaMba)
  • USB-кабель для передачи данных
  • 2 потенциометра (50k)
  • LCD1602 - http://bit.ly/2ubNEfi
  • Макетная плата - http://bit.ly/2slvfrB
  • Несколько перемычек

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

Используйте плату SunFounder Uno для основной части обработки данных вольтметра, LCD1602 в качестве экрана, потенциометр для регулировки контрастности ЖК-дисплея, а другой - для разделения напряжения.

Когда вы вращаете потенциометр, подключенный к плате Uno, резистор потенциометра изменяется, тем самым изменяя напряжение на нем. Сигнал напряжения будет отправлен на плату Uno через контакт A0, а Uno преобразует полученный аналоговый сигнал в цифровую форму и записывает на ЖК-дисплей. Таким образом, вы можете увидеть значение напряжения при текущем сопротивлении емкости.

LCD1602 имеет два режима работы: 4-битный и 8-битный. Когда IO MCU недостаточны, вы можете выбрать 4-битный режим, при котором используются только контакты D4 ~ D7.

Следуйте таблице, чтобы подключить их.

Шаг 4: Подключаем потенциометр к LCD1602

Подключите средний контакт потенциометра к контакту Vo на LCD1602, а любой из остальных контактов - к GND.

Подсоедините средний контакт потенциометра к контакту A0 от SunFounder Uno, а один из остальных - к 5V, когда другой - к GND.

Шаг 6: Загружаем код

Такой код:

#include /****************************************************/ const int analogIn = A0;//potentiometer attach to A0 LiquidCrystal lcd(4, 6, 10, 11, 12, 13);//lcd(RS,E,D4,D5,D6.D7) float val = 0;// define the variable as value=0 /****************************************************/ void setup() { Serial.begin(9600);//Initialize the serial lcd.begin(16, 2);// set the position of the characters on the LCD as Line 2, Column 16 lcd.print("Voltage Value:");//print "Voltage Value:" } /****************************************************/ void loop() { val = analogRead(A0);//Read the value of the potentiometer to val val = val/1024*5.0;// Convert the data to the corresponding voltage value in a math way Serial.print(val);//Print the number of val on the serial monitor Serial.print("V"); // print the unit as V, short for voltage on the serial monitor lcd.setCursor(6,1);//Place the cursor at Line 1, Column 6. From here the characters are to be displayed lcd.print(val);//Print the number of val on the LCD lcd.print("V");//Then print the unit as V, short for voltage on the LCD delay(200); //Wait for 200ms }

Вращайте потенциометр, чтобы проверить напряжение на LCD1602 в режиме реального времени.

Вот хитрая штука. После того, как я запустил код, на ЖК-дисплее отобразились символы. Затем я отрегулировал контрастность экрана (постепенное изменение от черного до белого), вращая потенциометр по часовой стрелке или против часовой стрелки, пока экран не отобразил символы четко.

Возьмите две батареи, чтобы измерить их напряжение: 1,5 В и 3,7 В. Отцепите соединение второго потенциометра с контактом A0 и GND, что означает удаление потенциометра из цепи. Зажмите конец провода A0 до анода батареи и цепь GND на катод. НЕ подключайте их обратно, иначе получите короткое замыкание на батарее. Значение 0V - это обратное соединение.

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

PS: Если у вас проблемы с отображением на дисплее - смотрите этот FAQ для ЖК-дисплеев - http://wiki.sunfounder.cc/index.php?title=LCD1602/I2C_LCD1602_FAQ.

Представлена полезная схема для любителей поэкспериментировать с Ардуино. Это простой цифровой вольтметр, которым надежно можно измерять постоянное напряжение в диапазоне 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)

С некоторыми дополнениями.

Мало известная фишка Ардуино и многих других AVR чипов это возможность измерить внутренний источник опорного напряжения 1.1 В. Эта функция может быть использована для повышения точности функции Arduino — analogRead при использовании стандартного опорного напряжения 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на платформах с напряжением питания 3.3 В). Она также может быть использована для измерения Vcc , поданного на чип , обеспечивая средство контроля напряжения батареи без использования драгоценных аналоговый выводов .

Мотивация

Есть, по крайней мере, две причины для измерения напряжения, питающего наш Arduino (Vcc). Одним из них является наш проект, питающийся от батареи, если мы хотим следить за уровнем напряжения батареи. Кроме того, когда питание от батареи (Vcc) не может быть 5,0 вольт(например питание от 3-х элементов 1.5 В), а мы хотим сделать аналоговые измерения более точными - мы должны использовать либо внутренний источник опорного напряжения 1,1 В либо внешний источник опорного напряжения. Почему?

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

Double Vcc = 5.0; // не обязательно правда int value = analogRead(0); / читаем показания с А0 double volt = (value / 1023.0) * Vcc; // верно только если Vcc = 5.0 вольт Для того чтобы измерить напряжение точно, необходимо точное опорное напряжение. Большинство чипов AVR обеспечивает три источника опорного напряжения:

  • 1,1 в от внутреннего источника, в документации он проходит как bandgap reference (некоторые из них 2,56 В, например ATMega 2560). Выбор осуществляется функцией analogReference() с параметром INTERNAL : analogReference(INTERNAL) ;
  • внешний источник опорного наптяжения, на ардуинке подписан AREF. Выбор: analogReference(EXTERNAL);
  • Vcc - источник питания самого контроллера. Выбор: analogReference(DEFAULT).

В Arduino нельзя просто взять и подключить Vcc к аналоговому пину напрямую - по умолчанию AREF связан с Vcc и вы всегда будете получать максимальное значение 1023, от какого бы напряжения вы не питались. Спасает подключение к AREF источника напряжения с заранее известным, стабильным напряжением, но это - лишний элемент в схеме.

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

Источник внешнего опорного напряжения является наиболее точным, но требует дополнительных аппаратных средств. Внутренний ИОН стабильным, но не точен + / - 10% отклонение. Vcc является абсолютно ненадежен в большинстве случаев. Выбор внутреннего источника опорного напряжения является недорогим и стабильным, но большую часть времени, мы хотели бы измеряет большее напряжение чем 1.1 В, так что использование Vcc является наиболее практичным, но потенциально наименее точным. В некоторых случаях оно может быть очень ненадежным!

Как это сделать

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

  1. Установить источник опорного напряжения по умолчанию: analogReference(DEFAULT); . Используем как источник - Vcc.
  2. Снять показания АЦП для внутреннего источника 1.1 В.
  3. Расчитать значение Vcc основываясь на измерении 1.1 В по формуле:

Vcc * (Показания АЦП) / 1023 = 1.1 В

Из чего следует:

Vcc = 1,1 В * 1023 / (Показания АЦП)

Собираем все вместе и получаем код:

long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(75); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }

Использование

Проверка напряжения Vcc или батареи

Вы можете назвать эту функцию – readVcc(), если Вы хотите мониторить Vcc. Примером может служить для проверка уровня заряда батареи. Вы также можете использовать её для определения подключены ли Вы к источнику питания или работаете от батареи.

Измерение Vcc для опорного напряжения

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

В одной из статей я сделал заявление, что эта функция может использоваться, чтобы улучшить точность аналоговых измерений в тех случаях, когда Vcc было не совсем 5.0 вольт. К сожалению, эта процедура не будет давать точный результат. Почему? Это зависит от точности внутреннего источника опорного напряжения. Спецификация дает номинальное напряжение 1.1 вольт, но говорится, что оно может отличаться до 10%. Такие измерения могут быть менее точными, чем наш источник питания Arduino!

Повышаем точность

Пока большие допуски внутреннего источника питания 1.1 В. значительно ограничивают точность измерений при использовании в серийном производстве, для индивидуальных проэктов мы можем добиться большей точности. Сделать это просто, просто измерив Vcc с помощью вольтметра и нашей функции readVcc(). Далее заменяем константу 1125300L новой переменной:

scale_constant = internal1.1Ref * 1023 * 1000

internal1.1Ref = 1.1 * Vcc1 (показания_вольтметра) / Vcc2 (показания_функции_readVcc())

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

Вывод

С этой маленькой функцией можно сделать многее. Вы можете использовать стабильное опорное напряжение близкое к 5.0 В не имея на самом деле 5.0 В на Vcc. Вы можете измерять напряжение вашей батареи или даже увидеть на каком вы питание от батареи или от стационарного источника питания.

И наконец, код будет поддерживать все Arduino, включая новый Leonardo, а также чипы ATtinyX4 и ATtinyX5 серий.

Широкий интерес для любителей самодельных электронно-программируемых устройств представляют многофункциональные сборки Arduino, позволяющие воплощать в жизнь интересные задумки.

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

Модули Arduino построены на универсальном микроконтроллере с собственным загрузчиком, что позволяет легко прошивать его необходимым программным кодом, без использования дополнительных устройств. Программирование осуществляется на стандартном языке С++.

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

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


Схема подключения Areduino через делитель напряжения

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

Внешний USB-разъем в автомагнитоле

Идея

Идея устройства для измерения напряжения, тока, емкости, разряда, а может и заряда возникла давно и не только у меня. Можно найти немало игрушек под названием USB Tester (Doctor) для тестирования различных устройств с USB. Мне же интересно несколько более универсальное устройство, независимое от интерфейса, а просто рассчитанное на определенные напряжения и токи. Например, 0 - 20.00в, 0 - 5.00а, 0 - 99.99Ач. Что касается функций, то я вижу так

  • Отображение текущих напряжения и тока, то есть вольт-ампер-метр. Впринципе, можно и мощность сразу отразить.
  • Подсчет и отображение накопленной емкости. В ампер-часах и всего скорее в ватт-часах.
  • Отображение времени процесса
  • И, всего скорее, настраиваемые нижний и верхний пороги отключения по напряжению (ограничения разряда и заряда)

Разработка

Для реализации расчетов и измерений нам понадобится контроллер. Я вспомнил эту идею в рамках знакомства с Arduino, поэтому контроллером будет простая популярная Atmega328 и программироваться она будет в среде Arduino. С инженерной точки зрения выбор наверно не самый хороший - контроллер для задачи слегка жирноват, а его АЦП не назовешь измерительными, но... будем пробовать.

  • Паять в этом проекте много не будем. В качестве основы возьмем готовый модуль Arduino Pro Mini, благо китайцы готовы их поставлять по $1.5 в розницу.
  • В качестве устройства отображения будет выступать дисплей 1602 - еще $1.5. У меня вариант с интерфейсным модулем I2C, но в этом проекте он не сильно нужен ($0.7).
  • Для разработки нам понадобиться макетная плата. В моем случае это небольшая BreadBoard за $1.
  • Разумеется понадобятся провода и некоторое количество резисторов разного номинала. Для дисплея 1602 без I2C нужен также подбор контрастности - делается переменным резистором на 2 - 20 кОм.
  • Для реализации амперметра понадобится шунт. В первом приближении им может быть резистор 0.1 Ом, 5 Вт.
  • Для реализации автоматики отключения понадобится реле с контактами рассчитанными на максимальный ток устройства и напряжением равным напряжению питания. Для управления реле нужен npn транзистор и защитный диод.
  • Устройство будет питаться от внешнего источника питания, очевидно, что не менее 5 в. Если питание будет сильно варьироваться, то так же потребуется интегральный стабилизатор типа 7805 - он и определит напряжение реле.
  • В случае Arduino Pro Mini для заливки прошивки потребуется USB-TTL конвертер.
  • Для наладки понадобится мультиметр.

Вольтметр

Я реализую простой вольтметр с одним диапазоном примерно 0 - 20в. Это замечанием важно, тк АЦП нашего контроллера имеет разрядность 10 бит (1024 дискретных значения), поэтому погрешность составит не менее 0.02 в (20 / 1024). Для реализации железно нам нужен аналоговый вход контроллера, делитель из пары резисторов и какой-нибудь вывод (дисплей в законченном варианте, для отладки можно последовательный порт).

Принцип измерения АЦП состоит в сравнении напряжения на аналоговом входе с опорным VRef. Выход АЦП всегда целый - 0 соответствует 0в, 1023 соответствует напряжению VRef. Измерение реализовано путем серии последовательных чтений напряжения и усреднения по периоду между обновлениями значения на экране. Выбор опорного напряжения важен, поскольку по умолчанию оно равно напряжению питания, которое может быть не стабильно. Это нам совершенно не подходит - за основу мы будем брать стабильный внутренний опорный источник напряжением 1.1в, инициализируя его вызовом analogReference(INTERNAL). Затем мы откалибруем его значение по показаниям мультиметра.

На схеме слева - вариант с прямым управлением дисплея (он просто управляется - смотрите стандартный скетч LiquidCrystal\HelloWorld). Справа - вариант с I2C, который я и буду использовать дальше. I2C позволяет сэкономить на проводах (коих в обычном варианте - 10, не считая подсветки). Но при этом необходим дополнительный модуль и более сложная инициализация. В любом случае, отображение символов на модуле надо сначала проверить и настроить контрастность - для этого надо просто вывести после инициализации любой текст. Контрастность настраивается резистором R1, либо аналогичным резистором I2C модуля.

Вход представляет собой делитель 1:19, который позволяет при Vref = 1.1 получить максимальное напряжение около 20в (обычно параллельно входу ставят конденсатор + стабилитрон для защиты, но нам пока это не важно). Резисторы имеют разброс, да и опорное Vref контроллера тоже, поэтому после сборки надо измерить напряжение (хотя бы питания) параллельно нашим устройством и эталонным мультиметром и подобрать Vref в коде до совпадения показания. Так же стоить отметить, что любой АЦП имеет напряжение смещения нуля (которое портит показания в начале диапазона), но мы пока не будем в это углубляться.

Также важным будет разделение питающей и измерительной "земли". Наш АЦП имеет разрешение чуть хуже 1мВ, что может создавать проблемы при неправильной разводке, особенно на макете. Поскольку разводка платы модуля уже сделана и нам остается только выбор пинов. "Земляных" пинов у модуля несколько, поэтому мы должны сделать так, чтобы питание в модуль заходило по одной "земле", а измерения по другой. Фактически для изменений я всегда использую "земляной" пин ближайший к аналоговым входам.

Для управление I2C используется вариант библиотеки LiquidCrystal_I2C - в моем случае указывается специфическая распиновка модуля I2C (китайцы производят модули с отличающимся управлением). Так же отмечу, что I2C в Arduino предполагает использование именно пинов A4, A5 - на плате Pro Mini они находятся не с краю, что неудобно для макетирования на BreadBoard.

Исходный код

#include #include // Простой вольтметр с i2c дисплеем 1602. V 16.11 // Настройки i2c дисплея 1602 с нестандартной распиновкой #define LCD_I2C_ADDR 0x27 #define BACKLIGHT 3 #define LCD_EN 2 #define LCD_RW 1 #define LCD_RS 0 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D6 6 #define LCD_D7 7 LiquidCrystal_I2C lcd(LCD_I2C_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7); // Время обновления показаний, мс (200-2000) #define REFRESH_TIME 330 // Аналоговй вход #define PIN_VOLT A0 // Внутреннее опорное напряжение (подобрать) const float VRef = 1.10; // Коэффициент входного резистивного делителя (Rh + Rl) / Rl. IN <-[ Rh ]--(analogInPin)--[ Rl ]--|GND const float VoltMult = (180.0 + 10.0) / 10.0; float InVolt, Volt; void setup() { analogReference(INTERNAL); // Инициализация дисплея lcd.begin (16, 2); lcd.setBacklightPin(BACKLIGHT, POSITIVE); lcd.setBacklight(HIGH); // включить подсветку lcd.clear(); // очистить дисплей lcd.print("Voltage"); } void loop() { unsigned long CalcStart = millis(); int ReadCnt = 0; InVolt = 0; // Чтение из порта с усреднением while ((millis() - CalcStart) < REFRESH_TIME) { InVolt += analogRead(PIN_VOLT); ReadCnt++; } InVolt = InVolt / ReadCnt; // Смещение 0 для конкретного ADC (подобрать или отключить) if (InVolt > 0.2) InVolt += 3; // Перевод в вольты (Value: 0..1023 -> (0..VRef) scaled by Mult) Volt = InVolt * VoltMult * VRef / 1023; // Вывод данных lcd.setCursor (0, 1); lcd.print(Volt); lcd.print("V "); }

Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: