Представлена полезная схема для любителей поэкспериментировать с Ардуино. Это простой цифровой вольтметр, которым надежно можно измерять постоянное напряжение в диапазоне 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 и ПК и передавать на ПК данные с АЦП. Программа для Windows написана с использованием Visual C++ 2008 Express. Программа вольтметра очень проста и имеет обширное поле для улучшений. Основной её целью было показать работу с COM-портом и обмен данными между компьютером и Arduino.
Связь между Arduino и ПК:
- Снятие показаний с АЦП начинается, когда компьютер посылает Arduino команды 0xAC и 0x1y. у – номер канала АЦП (0-2);
- Снятие показаний прекращается после получения Arduino команд 0xAC и 0×00;
- Во время снятия показаний Arduino раз в 50 мс посылает компьютеру команды 0xAB 0xaa 0xbb, где aa и bb максимальные и минимальные результаты измерения.
Программа для Arduino
Подробнее о последовательной связи Вы можете прочесть на arduino.cc. Программа достаточно проста, большую её часть занимает работа с параллельным портом. После окончания снятия данных с АЦП мы получаем 10 битное значение напряжения (0×0000 – 0×0400) в виде 16-битных переменных (INT). Последовательный порт (RS-232) позволяет передавать данные в пакетах по 8 бит. Необходимо разделить 16-битные переменные на 2 части по 8 бит.
Serial.print(voltage>>8,BYTE);
Serial.print(voltage%256,BYTE);
Мы смещаем байты переменной на 8 бит вправо и потом делим на 256 и результат отправляем на компьютер.
Полный исходник ПО для Arduino вы можете скачать
Visual C++
Я предполагаю, что у Вас уже есть базовые знания в области программирования на C + + для Windows, если нет, то используйте Google. Интернет полон уроков для начинающих.
Первое, что нужно сделать, это добавить последовательный порт из панели инструментов в нижнюю форму. Это позволит изменить некоторые важные параметры последовательного порта: имя порта, скорость передачи данных, битность. Это полезно для добавления элементов управления в окно приложения, для изменения этих настроек в любое время, без перекомпиляции программы. Я использовал только возможность выбора порта.
После поиска доступных последовательных портов первый порт выбирается по умолчанию. Как это сделано:
array< String ^>^ serialPorts = nullptr;
serialPorts = serialPort1->GetPortNames();
this->comboBox1->Items->AddRange(serialPorts);
this->comboBox1->SelectedIndex=0;
Последовательный порт на ПК может быть использован только одним приложением одновременно, так что порт должен быть открыт перед использованием и не закрываться. Простые команды для этого:
serialPort1->Open();
serialPort1->Close();
Для правильного чтения данных из последовательного порта необходимо использовать события (в нашем случае прерывание). Выберите тип события:
Раскрывающийся список при двойном нажатии "DataReceived".
Код события генерируется автоматически:
Если первый байт прибывший по последовательному порту 0xAB, если это означает, что остальные байты несут данные о напряжении.
private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
unsigned char data0, data1;
if (serialPort1->ReadByte()==0xAB) {
data0=serialPort1->ReadByte();
data1=serialPort1->ReadByte();
voltage=Math::Round((float(data0*256+data1)/1024*5.00),2);
data_count++;
serialPort1->ReadByte();
Запись и чтение данных последовательного порта
Для меня небольшой проблемой было послать шестнадцатиричные RAW-данные через последовательный порт. Была использованна команда Write(); но с тремя аргументами: массив, номер стартового байта, кол-во байтов для записи.
private: System::Void button2_Click_1(System::Object^ sender, System::EventArgs^ e) {
unsigned char channel=0;
channel=this->listBox1->SelectedIndex;
array^start ={0xAC,(0x10+channel)};
array^stop ={0xAC,0x00};
serialPort1->Write(start,0,2);
this->button2->Text="Stop";
} else {
serialPort1->Write(stop,0,2);
this->button2->Text="Start";
На этом все!
Оригинал статьи на английском языке (перевод: Александр Касьянов для сайта cxem.net)
Аналоговые входы платы Ардуино.
Плата 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, позволяющие воплощать в жизнь интересные задумки.
Основное преимущество готовых схем Arduino заключается в уникальном блочно-модульном принципе: каждая плата может быть добавлена дополнительными интерфейсами, бесконечно расширяя возможности для создания различных проектов.
Модули Arduino построены на универсальном микроконтроллере с собственным загрузчиком, что позволяет легко прошивать его необходимым программным кодом, без использования дополнительных устройств. Программирование осуществляется на стандартном языке С++.
Одним из простейших примеров использования Arduino может стать реализация на базе этой сборки вольтметра постоянного напряжения повышенной точности с диапазоном измерения от 0 до 30 В.
Аналоговые входы Arduino предназначены для постоянного напряжения не более пяти вольт, поэтому, использование их при превышающих это значение напряжениях возможно с делителем напряжения.
Схема подключения Areduino через делитель напряжения
Делитель напряжения состоит из двух последовательно соединенных сопротивлений. Расчет его производится по формуле:
Внешний USB-разъем в автомагнитоле
Описано как собрать самодельный двойной вольтметр на основе платформы Arduino UNO с использованием ЖК-дисплея 1602A. В некоторых случаях необходимо измерять одновременно два постоянныхнапряжения и сравнивать их. Это может потребоваться, например, при ремонте или налаживании стабилизатора постоянного напряжения, чтобы измерять напряжение на его входе и выходе, либо в других случаях.
Принципиальная схема
Используя универсальный микроконтроллерный модуль ARDUINO UNO и двухстрочный ЖК-дисплей типа 1602А (на основе контроллера HD44780) можно легко сделать такой прибор. В одной строке он будет показывать напряжение U1, в другой - напряжение U2.
Рис. 1. Принципиальная схема двойного вольтметра с дисплеем 1602A на Arduino UNO.
Но, прежде всего, хочу напомнить, что ARDUINO UNO это относительно недорогой готовый модуль, - небольшая печатная плата, на которой расположен микроконтроллер ATMEGA328, а так же вся его «обвязка», необходимая для его работы, включая USB-программатор и источник питания.
Тем, кто незнаком с ARDUINO UNO, советую сначала ознакомиться со статьями Л.1 и Л.2. Схема двойного вольтметра показана на рис. 1. Он предназначен для измерения двух напряжений от 0 до 100V (практически, до 90V).
Как видно из схемы, к цифровым портам D2-D7 платы ARDUINO UNO подключен модуль жидкокристаллического индикатора Н1 типа 1602А. Питается ЖК-индикатор от стабилизатора напряжения 5V, имеющегося на плате стабилизатора напряжения 5V.
Измеряемые напряжения поступают на два аналоговых входа А1 и А2. Всего аналоговых входов шесть, - А0-А5, можно было выбрать любые два из них. В данном случае, выбраны А1 и А2. Напряжение на аналоговых портах может быть только положительным и только в пределах от нуля до напряжения питания микроконтроллера, то есть, номинально, до 5V.
Выход аналогового порта преобразуется АЦП микроконтроллера в цифровую форму. Для получения результата в единицах вольт, нужно его умножить на 5 (на опорное напряжение, то есть, на напряжение питания микроконтроллера) и разделить на 1024.
Для того чтобы можно было измерять напряжение более 5V, вернее, более напряжения питания микроконтроллера, потому что реальное напряжение на выходе 5-вольтового стабилизатора на плате ARDUINO UNO может отличаться от 5V, и обычно немного ниже, нужно на входе применить обычные резистивные делители. Здесь это делители напряжения на резисторах R1, R3 и R2, R4.
При этом, для приведения показаний прибора к реальному значению входного напряжения, нужно в программе задать деление результата измерения на коэффициент деления резистивного делителя. А коэффициент деления, обозначим его «К», можно вычислить по такой формуле:
К = R3 / (R1+R3) или К = R4 / (R2+R4),
соответственно для разных входов двойного вольтметра.
Очень любопытно то, что резисторы в делителях совсем не обязательно должны быть высокоточными. Можно взять обычные резисторы, затем измерить их фактическое сопротивление точным омметром, и уже в формулу подставить эти измеренные значения. Получится значение «К» для конкретного делителя, которое и нужно будет подставлять в формулу.
Программа для вольтметра
Программа на языке C++ приведена на рисунке 2.
Рис. 2. Исходный код программы.
Для управления ЖК-индикатором решено было использовать порты с D2 по D7 платы ARDUINO UNO. В принципе, можно и другие порты, но я вот так, решил использовать именно эти.
Для того чтобы индикатор взаимодействовал с ARDUINO UNO нужно в программу загрузить подпрограмму для его управления. Такие подпрограммы называются «библиотеками», и в программном комплекте для ARDUINO UNO есть много разных «библиотек». Для работы с ЖК-индикатором на основе HD44780 нужна библиотека LiquidCrystal. Поэтому программа (таблица 1) начинается с загрузки этой библиотеки:
Эта строка дает команду загрузить в ARDUINO UNO данную библиотеку. Затем, нужно назначить порты ARDUINO UNO, которые будут работать с ЖК-индикатором. Я выбрал порты с D2 по D7. Можно выбрать другие. Эти порты назначены строкой:
LiquidCrystal led(2, 3, 4, 5, 6, 7);
После чего, программа переходит собственно к работе вольтметра. Для измерения напряжения решено было использовать аналоговые входы А1 и А2. Эти входы заданы в строках:
int analogInput=1;
int analogInput1=2;
Для чтения данных с аналоговых портов используется функция analogRead. Чтение данных с аналоговых портов происходит в строках:
vout=analogRead(analogInput);
voutl=analogRead(analoglnput1);
Затем, производится вычисление фактического напряжения с учетом коэффициента деления делителя входного напряжения:
volt=vout*5.0/1024.0/0.048 ;
volt1=vout1*5.0/1024.0/0.048;
В этих строках число 5.0 - это напряжение на выходе стабилизатора платы ARDUINO UNO. В идеале должно быть 5V, но для точной работы вольтметра это напряжение нужно предварительно измерить. Подключите источник питания и измерьте достаточно точным вольтметром напряжение +5V на разъеме POWER платы. Что будет, то и вводите в эти строки вместо 5.0, например, если будет 4.85V, строки будут выглядеть так:
volt=vout*4.85/1024.0/0.048;
volt1=vout1*4.85/1024.0/0.048;
На следующем этапе нужно будет измерить фактические сопротивления резисторов R1-R4 и определить коэффициенты К (указаны 0.048) для этих строк по формулам:
К1 = R3 / (R1+R3) и К2 = R4 / (R2+R4)
Допустим, К1 = 0.046, а К2 = 0.051, так и пишем:
volt=vout*4.85/1024.0/0.046 ;
volt1=vout1*4.85/1024.0/0.051;
Таким образом, в текст программы нужно внести изменения соответственно фактическому напряжению на выходе 5-воль-тового стабилизатора платы ARDUINO UNO и согласно фактическим коэффициентам деления резистивных делителей. После этого прибор будет работать точно и никакого налаживания или калибровки не потребует.
Изменив коэффициенты деления резистивных делителей (и, соответственно, коэффициенты «К») можно сделать другие пределы измерения, и совсем не обязательно одинаковые для обоих входов.
Каравкин В. РК-2017-01.
Литература:
- Каравкин В. - Ёлочная мигалка на ARDUINO как средство от боязни микроконтроллеров. РК-11-2016.
- Каравкин В. - Частотомер на ARDUINO. РК-12-2016.