В этой статье показано как связать Arduino и ПК и передавать на ПК данные с АЦП. Программа для Windows написана с использованием Visual C++ 2008 Express. Программа вольтметра очень проста и имеет обширное поле для улучшений. Основной её целью было показать работу с COM-портом и обмен данными между компьютером и Arduino.
Связь между Arduino и ПК:
Программа для 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 . В ней представлен простой цифровой вольтметр, который может безопасно измерять постоянное напряжение в диапазоне от 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 из строя!
Используемые элементы:
Итак к этому момент у нас есть вольтметр постоянного напряжения с пределом 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 "); }
Описано как собрать самодельный двойной вольтметр на основе платформы 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 и android. В предыдущей публикации я рассказал про , а сегодня речь пойдет про DIY bluetooth вольтметр. Еще такой девайс можно назвать смарт вольтметр, «умный» вольтметр или просто умный вольтметр, без кавычек. Последнее название является неправильным с точки зрения грамматики русского языка, тем не менее частенько встречается в СМИ. Голосование на эту тему будет в конце статьи, а начать предлагаю с демонстрации работы устройства, чтобы понять о чем же пойдет речь в статье.
Скетч
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);
}