Амперметр arduino: пример реализации устройства

Вольт-ампер-energy-метр на Arduino. Часть 2. Амперметр

Главная » Статьи » Мои статьи

Вольт-ампер-energy-метр на Arduino. Часть 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

Ссылки

Железо

Категория: Мои статьи | Добавил: alexeevd (07.02.2016)

Источник: http://alexeevd.narod.ru/publ/arduino_vametr/1-1-0-9

Вольт ампер метр на Arduino мини часть 1,2 | Пелинг Инфо солнечные батареи – ветрогенераторы DIY своими руками 2011 г-2018г

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

И так первоисточник:  http://rexpirando.blogspot.ru/2011/01/volt-amperimetro-com-arduino-parte-1.html

Автор : Renato

Дополнительная ссылка на схему принципиальную : http://rexpirando.blogspot.ru/2011/01/volt-amperimetro-com-arduino-parte.html

Схемы :

Что вам понадобится:

  • 1 —  Arduino — любая;
  • Монтажная плата — у меня их ушло две.
  • 1 — Дисплей 1602A (16×2 с подсветкой);
  • 1 — зуммер — не обязательно;
  • 2  — переходники клемники двойной;
  • 3  —  (кнопки);
  • 1  — Потенциометр 10k;
  • 6 — резисторы 10k;
  • 2 — резисторы 100k;
  • 1 — резистор 100R;
  • 1 — резистор 10R;
  • 1 — резистор 0.47R с 5W власти — я ставил на 10W -25W сопротивлением от 0.10 ом до 1 Ом — все работает —  с обычными шунтами не получилось!

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

//version #define NAME “Arduino Ammeter” #define VERSION “0.9” //debug flag (avoid enabling. it makes your device slower) //#define DEBUG //pins const int PIN_BACKLIGHT = 7; const int PIN_BUZZER = 3; const int PIN_VOLTAGE = 0; const int PIN_CURRENT = 1; const int PIN_BUTTON_UP = 6; const int PIN_BUTTON_SETUP = 5; const int PIN_BUTTON_DOWN = 4; // includes #include #include // initialize the library with the numbers of the interface pins LiquidCrystal lcd(13, 12, 11, 10, 9, 8); //variables //voltage int VOLTAGE_CURRENT; int VOLTAGE_LAST=99999; unsigned long VOLTAGE_MILLIS; float VOLTAGE_CALCULATED; float VOLTAGE_MAP = 50; //default voltage map… calibration needed //current int CURRENT_CURRENT; int CURRENT_LAST=99999; unsigned long CURRENT_MILLIS; float CURRENT_CALCULATED; float CURRENT_MAP = 10; //default current map… calibration needed //buttons boolean BUTTON_PRESSED = false; unsigned long BUTTON_MILLIS = false; byte BUTTON_LAST; boolean SETUP_MODE = false; byte SETUP_ITEM; boolean SETUP_DELAYBEEP; //… unsigned long MILLIS; unsigned long SETUP_BLINKMILLIS; boolean SETUP_BLINKSTATE; //parameters const int SENSOR_INTERVAL = 500; const int BUTTON_HOLDTIME = 2000; const int SETUP_MAXITEMS = 2; const int SETUP_BLINKINTERVAL = 300; const byte EEPROM_VALIDATOR = 73; //random number const float VOLTAGE_STEP = 0.1; const float CURRENT_STEP = 0.1; //configuration const byte EEPROM_CONFIGADDRESS = 0; struct config_t { byte Validator; ///////////////////// float VOLTAGE_MAP; float CURRENT_MAP; ///////////////////// byte ValidatorX2; } EEPROM_DATA; void setup() { //configure pins pinMode(PIN_BACKLIGHT, OUTPUT); pinMode(PIN_BUZZER, OUTPUT); pinMode(PIN_VOLTAGE, INPUT); pinMode(PIN_CURRENT, INPUT); pinMode(PIN_BUTTON_UP, INPUT); pinMode(PIN_BUTTON_SETUP, INPUT); pinMode(PIN_BUTTON_DOWN, INPUT); //set up LCD lcd.begin(16, 2); //initial message lcd.setCursor(0, 0); lcd.print(NAME); lcd.setCursor(0, 1); lcd.print(“Version “); lcd.print(VERSION); //lights up digitalWrite(PIN_BACKLIGHT, HIGH); #ifdef DEBUG delay(2000); lcd.setCursor(0, 1); lcd.print(“Debug enabled! “); lcd.print(VERSION); Serial.begin(9600); Serial.println(“============================”); Serial.println(NAME); Serial.println(“Version “); Serial.println(VERSION); Serial.println(“============================”); Serial.println(“Debug messages:”); Serial.println(“—————————-“); #endif //try to load the configuration loadConfiguration(); //show initial message for a while then clear and beep delay(2000); lcd.clear(); showLabels(); //beep beepStart(); } void loop() { processButtons(); MILLIS = millis(); if ( (MILLIS – VOLTAGE_MILLIS) >= SENSOR_INTERVAL ) { readVoltage(); if (!SETUP_MODE || SETUP_ITEM!=1) { showVoltage(); } VOLTAGE_MILLIS = MILLIS; } if ( (MILLIS – CURRENT_MILLIS) >= SENSOR_INTERVAL ) { readCurrent(); if (!SETUP_MODE || SETUP_ITEM!=2) { showCURRENT(); } CURRENT_MILLIS = MILLIS; } if (SETUP_MODE) { if ( (MILLIS – SETUP_BLINKMILLIS) >= SETUP_BLINKINTERVAL ) { if (SETUP_BLINKSTATE) { if (SETUP_ITEM==1) showVoltage(); else if (SETUP_ITEM==2) showCURRENT(); SETUP_BLINKSTATE = false; } else { if (SETUP_ITEM==1) hideVoltage(); else if (SETUP_ITEM==2) hideCURRENT(); SETUP_BLINKSTATE = true; } SETUP_BLINKMILLIS = MILLIS; } } } void processButtons() { if (digitalRead(PIN_BUTTON_UP) == HIGH) { if (!BUTTON_PRESSED) { #ifdef DEBUG showDebug(“Pressed UP”); #endif BUTTON_LAST = PIN_BUTTON_UP; BUTTON_PRESSED = true; } } else if (digitalRead(PIN_BUTTON_SETUP) == HIGH) { if (!BUTTON_PRESSED) { #ifdef DEBUG showDebug(“Pressed SETUP”); #endif beepButton(); BUTTON_LAST = PIN_BUTTON_SETUP; BUTTON_MILLIS = millis(); BUTTON_PRESSED = true; SETUP_DELAYBEEP = false; } else { if ((millis() – BUTTON_MILLIS) > BUTTON_HOLDTIME) if (!SETUP_DELAYBEEP) { beepButton(); SETUP_DELAYBEEP = true; } } } else if (digitalRead(PIN_BUTTON_DOWN) == HIGH) { if (!BUTTON_PRESSED) { #ifdef DEBUG showDebug(“Pressed DOWN”); #endif BUTTON_LAST = PIN_BUTTON_DOWN; BUTTON_PRESSED = true; } } else { if (BUTTON_PRESSED) { if (BUTTON_LAST == PIN_BUTTON_SETUP) { #ifdef DEBUG showDebug(“Released SETUP”); #endif if (!SETUP_MODE && (millis() – BUTTON_MILLIS) > BUTTON_HOLDTIME) { #ifdef DEBUG showDebug(“Entered setup mode!”); #endif lcd.setCursor(0, 1); lcd.print(” Setup Mode “); SETUP_MODE = true; SETUP_ITEM = 1; } else { if (SETUP_ITEM == SETUP_MAXITEMS) { #ifdef DEBUG showDebug(“Exited setup mode!”); #endif showLabels(); SETUP_MODE = false; SETUP_ITEM = 0; saveConfiguration(); } else { SETUP_ITEM++; } showVoltage(); showCURRENT(); } } else if (BUTTON_LAST == PIN_BUTTON_UP) { #ifdef DEBUG showDebug(“Released UP”); #endif if (SETUP_MODE) { beepButton(); if (SETUP_ITEM==1) { //voltage VOLTAGE_MAP+=VOLTAGE_STEP; readVoltage(); #ifdef DEBUG startDebug(“New VOLTAGE_MAP: “); Serial.println(VOLTAGE_MAP,6); #endif } else if (SETUP_ITEM==2) { //current CURRENT_MAP+=CURRENT_STEP; readCurrent(); #ifdef DEBUG startDebug(“New CURRENT_MAP: “); Serial.println(CURRENT_MAP,6); #endif } } } else if (BUTTON_LAST == PIN_BUTTON_DOWN) { #ifdef DEBUG showDebug(“Released DOWN”); #endif if (SETUP_MODE) { beepButton(); if (SETUP_ITEM==1) { //voltage VOLTAGE_MAP-=VOLTAGE_STEP; readVoltage(); #ifdef DEBUG startDebug(“New VOLTAGE_MAP: “); Serial.println(VOLTAGE_MAP,6); #endif } else if (SETUP_ITEM==2) { //current CURRENT_MAP-=CURRENT_STEP; readCurrent(); #ifdef DEBUG startDebug(“New CURRENT_MAP: “); Serial.println(CURRENT_MAP,6); #endif } } } BUTTON_PRESSED = false; } } } #ifdef DEBUG void showDebug(char* Message) { Serial.print(millis()); Serial.print(“: “); Serial.println(Message); } void startDebug(char* Message) { Serial.print(millis()); Serial.print(“: “); Serial.print(Message); } #endif void showLabels() { lcd.setCursor(0, 1); lcd.print(“Volts Amps”); } void showVoltage() { lcd.setCursor(0, 0); lcd.print(VOLTAGE_CALCULATED, 2); lcd.print(” V”); if (VOLTAGE_CALCULATED

Читайте также:  Syma x5c explorers: квадрокоптер с камерой - arduino+

Источник: https://peling.ru/volt-amper-metr-na-arduino-mini-chast-1-2/

Nano вольт – амперметр 2 канала

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

По сути, arduino, если с микроконтроллером , то это  МК семейства AVR, с обвязкой и bootloader’ом, позволяющем заливать прошивку с помощью  COM порта (или его USB эмулятора).

BootLoader  это небольшая программка которая сидит в специальной области памяти микроконтроллера и слушает когда к ней будет «обращение», далее все работает как по-маслу, новая программа «заливается» в контролер очень быстро. Фишка удобная и применять можно  часто…

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

Я так же решил использовать  весьма распространенную  готовую платку .

Заказал в Китае, эту платку Arduino Nano V3 , и использую тут удобство бутлоадера  для заливки прошивки.
Для этого случая написал программу хорошенького показометра ВольтАмперметра с графическим экраном 128х64 (чип ST7920)

Схема Nano вольт-амперметра , с платкой arduino

и второй вариант этой же схемы, для отдельного взятого  МК

Из интернета нашлось, что Arduino Nano можно прошивать любым .нех файлом  , с помощью маленькой и удобной программы XLoader.

Программка имеет простейший интерфейс и работать с ней предельно просто:
— подключаем нашу платку Arduino через шнур в USB-порт (отдельного питания не нужно)
— выбираем Hex файл ВольтАмперметра
— выбираем тип Arduino Nano
— выбираем COM порт, который создался при подключении Arduino к USB
— жмем Upload

Прошивка за три секунды записывается в МК, по сравнению с моим USB «свистком» это очень – очень быстро.
И все! Ничего сложного.

Программа сразу по окончании записи начинает работать

Еще для общей информации, про Arduino Nano V3 , в интернете нашел рисунок с распиновкой платы.

Работу программы вольт амперметра, можно посмотреть также в протеусе

Прошивка и протеус “Nano  вольт амперметра” в архиве.

Фьюзы для работы АТmega328 с загрузчиком.

Архив с прошивкой для загрузчика ATmega328.

Ну, вот кратко и все, теперь есть полезная программа для вольтметра – амперметра , и практическое понятие, как можно воспользоваться удобством загрузчика.

Форум

You have no rights to post comments.
Недостаточно прав для комментирования

Источник: http://sxem.org/2-vse-stati/20-voltmetry/197-nano-volt-ampermetr-2-kanala

Секретный вольтметр в Arduino — измерение напряжения батареи средствами микроконтроллера

В основном перевод статьи Secret Arduino Voltmeter – Measure Battery Voltage с некоторыми дополнениями.

Мало известная фишка Ардуино и многих других 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 обеспечивает три источника опорного напряжения:

  • внешний источник опорного наптяжения, на ардуинке подписан  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 В по формуле:
Читайте также:  Инженер-радиотехник - arduino+

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

Источник: http://blog.unlimite.net/?p=25

Выводы (пины) arduino

Опубликовано 28.10.2013 12:04:00

Казалось бы, вот стоит у нас задача поуправлять реле модулем, как известно он управляется цифровым выводом. Так в чем проблема? К примеру, на плате Arduino UNO у нас их аж целых  14, так лепи к какому хочешь. Ну вот и начнем по порядку. Пусть будет D0. С одной стороны верно, работать то будет.

Но вот одним вечером мы решаем, что теперь нам хочется управлять нашей релюшкой дистанционно, возьмем к примеру блютуз. Вот тут и возникает проблема, ведь он работает по интерфейсу UART, а это цифровые пины 0 и 1.  Теперь придется переподключать.

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

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

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

1. Интерфейсы

На мой взгляд, в категорию “неприкасаемых, пока есть другие свободные” следует, в первую очередь, отнести выводы отвечающие за интерфейсы.

Раз уж заговорили про UNO, то и рассмотрим на примере контроллера который установлен в нем – ATmega328. 

ATmega328 имеет 3 интерфейса:

UART

D0 – RX (Прием данных)

D1 – TX  (Отправка данных)

SPI

D13 – CSK (Выход тактирования данных)

D12 – MISO  (Вход данных для последовательного программирования)

D11 – MOSI  (Выход данных для последовательного программирования)

I2C

A4 – SDA (последовательная линия данных)

A5 – SCL  (последовательная линия тактирования)

Вот уже 5 цифровых из 14ти и 2 аналоговых из 6ти можно зарезервировать на самый крайний случай.

2. Цифровые выводы с поддержкой ШИМ (PWM)

Далее я бы присмотрелся к цифровым входам/выходам которые имеют поддержку ШИМ. На понятии ШИМ останавливаться не будем, более подробно можно почитать здесь.

 Скажем вкратце, что с помощью ШИМ'а мы сможем регулировать яркость светодиодов, задавать скорости вращения двигателей, управлять сервоприводами с помощью стандартной библиотеки servo.

h (правда для управления сервами используется не совсем ШИМ).

Цифровые пины с поддержкой ШИМ Atmega328:

D3, D5, D6, D9, D10, D11 (D11 задействует интерфейс SPI).

Казалось бы все, да нет). Дам вам еще один совет.

Для рассмотрения в статье, я специально за пример взял контроллер Atmega328 в DIP корпусе. Как мы знаем, у меги 328ой имеются два младших брата, также поддерживаемых средой Arduino IDE – это Atmega168 и Atmega8.

ATmega168 не намного дешевле ATmega328 и отличается только количеством памяти.  А вот ATmega8 намного дешевле 328, её и можно будет и вставлять в готовый проект (если конечно хватит памяти).

Однако расплатой за более низкую цену, помимо маленького объема памяти, является еще и урезанное количество цировых выводов с поддержкой ШИМ.

Цифровые пины с поддержкой ШИМ Atmega8:

D9, D10. D11 (D11 задействует интерфейс SPI).

3. Выводы поддерживающие прерывания

Важное дополнение было написано в комментариях.

twsdwf: “Я бы не стал называть “пустышками” выводы D2 и D3 на atmega328. На них можно вешать внешние аппаратные прерывания”.

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

4. Итог: Рекомендуемая последовательность

Как мы видим, пустышками остается очень мало пинов.

Ну что, составим таблицу рекомендуемой последовательности:

Пустышки. Используем в первую очередь:

D4, D7, D8, A0, A1. A2. A3

ШИМ выводы, если в конечном проекте планируется переход на Atmega 8:

D5, D6

ШИМ выводы, если в конечном проекте планируется переход на Atmega 328:

D5, D6, D9, D10

Прерывания

D2, D3

Выводы интерфейсов. Пускаем в ход по крайней необходимости:

D0, D1, D11, D12, D13, A4, A5

Иллюстрация вышеописанного

Полезная информация

Кстати хочется упомянуть еще одну очень полезную штуку. Все аналоговые входы могут работать как цифровые выходы. Инициализация и работа абсолютно одинаковая с обычными цифровыми выводами. Необходимо просто в коде задавать порты A0…A5  как  14…19.

К примеру для того чтобы поморгать светодиодом c аналогового входа А0:

void setup() {               
pinMode(14, OUTPUT); // инициализируем аналоговый вход как цифровой
}
void loop() {
  digitalWrite(14, HIGH); // зажигаем светодиод
  delay(1000); // ждем секунду
  digitalWrite(14, LOW); // выключаем светодиод
  delay(1000); // ждем секунду
}

В данный момент еще реализованы не все элементы нашего сообщества. Мы активно работаем над ним и в ближайшее время возможность комментирования статей будет добавлена.

Источник: http://zelectro.cc/development_of_the_device

Аналоговые измерения с Arduino | РОБОТОША

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

Сегодня я расскажу об использовании и проведу тест производительности аналого-цифрового преобразователя (АЦП) Arduino. Тест я буду производить, используя оригинальную плату Arduino Mega 2560, в основе которой лежит микроконтроллер ATMega2560, работающий на частоте 16 Мгц.

Микроконтроллер ATMega328, на котором основаны Arduino Uno и Arduino Nano, также работает на частоте 16 МГц, так что все вышеизложенное, скорее всего, справедливо и для этих и аналогичных плат.

analogRead

Давайте посмотрим сколько же времени занимает аналого-цифровое преобразование с использованием стандартной функции analogRead.

Для определения моментов начала и конца преобразования я буду использовать 12 вывод в качестве маркера. Для начала повторим эксперимент, который я описывал в статье Оптимизируем digitalWrite на Arduino. Будем изменять уровень напряжения на 12 цифровом пине между состояниями LOW и HIGH. Для чистоты эксперимента я помещу внутрь loop бесконечный цикл.

Скетч, реализующий простые переключения на 12 цифровом выводе выглядит следующим образом:

Читайте также:  Программист микроконтроллеров stm32f/инженер встраиваемых систем
void setup(){DDRB = B01000000; //устанавливаем 12 пин в режим выхода}void loop(){while(1){  PORTB = B01000000; // устанавливаем пин 12 в состояние HIGH    PORTB = B00000000; // устанавливаем пин 12 в состояние LOW}}

Воспользуемся осциллографом и посмотрим на временные параметры работы этой программы:

Отсюда видно, что время переключения состояния пина занимает у нас 62 нс (длительность положительного импульса).

Теперь немного изменим скетч и добавим между переключениями функцию чтения аналогового сигнала analogRead на 3 аналоговом пине:

123456789101112131415161718 int analogPin = 3; // входной аналоговый пинint analogValue = 0; // значение аналогового сигналаvoid setup(){DDRB = B01000000; // устанавливаем 12 пин в режим выхода}void loop(){while(1){  PORTB = B01000000; // устанавливаем пин 12 в состояние HIGH  analogValue = analogRead(analogPin); // читаем аналоговый сигнал  PORTB = B00000000; // устанавливаем пин 12 в состояние LOW  analogValue = analogRead(analogPin); // читаем аналоговый сигнал}}

Осцилограмма сигнала на 12 цифровом пине теперь будет выглядеть следующим образом:

Длительность переключения в 62 нс и время циклического возврата к началу работы программы в 124 нс не превышают погрешность измерения на этом временном масштабе и мы можем пренебречь этими временными промежутками. Отсюда видно, что время, которое затрачивается на аналого-цифровое преобразование примерно равно 112 мкс, поэтому максимальная частота выборки при использовании функции analogRead не превышает 8.9 кГц.

Недостатком использования analogRead является еще и то, что Arduino не может выполнять другой код во время ожидания результата преобразования.

Используем прерывания АЦП

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

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

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

Разовая выборка

Разовая выборка — это на самом деле то, что Arduino делает при вызове функции analogRead. Мы не сможем получить значительных преимуществ, реализовав разовую выборку с помощью других средств. Поскольку перед запуском АЦП, в первую очередь проверяется флаг готовности АЦП, то это означает, что проверка флага в цикле ничем не отличается от того, что делает Arduino.

Непрерывная выборка

Хорошей идеей при непрерывной выборке сигнала является использование прерываний. Микроконтроллеры ATMega328 и ATMega2560 могут быть переведены в режим непрерывной выборки (free running mode).

В этом режиме АЦП запускается автоматически после завершения предыдущей обработки.

Каждый раз преобразование заканчивается генерированием прерывания, которое вызывает функцию обработки прерывания ISR (ADC_vect), в которой результат аналого-цифрового преобразования может быть считан и обработан.

Для включения режима непрерывной выборки необходимо установить три регистра: ADMUX, ADCSRA и ADCSRB. Детальное описание этих регистров можно найти в технических руководствах к микроконтроллерам.

Внутреннее опорное напряжение 1.1 В и входной аналоговый канал ADC3 выбираются при помощи ADMUX. Тактовая частота задается при помощи ADCSRA и в нашем примере установлена в виде делителя ÷16.

Одно аналоговое преобразование занимает 13 тактовых периодов. Частота дискретизации может быть вычислена, исходя из тактовой частоты микроконтроллера: 16 Мгц/(16*13) ≈ 77 кГц.

Установкой 6 бита регистра ADCSRA в состояние HIGH,  запускается непрерывная выборка.

Результат аналого-цифрового преобразования считывается в функцию обработки прерывания ISR (ADC_vect). Поскольку, результат имеет длину 10 бит, то он делится на два регистра ADCL и ADCH, размером в один байт каждый. Для корректного чтения значения сначала нужно считать значение регистра ADCL, а затем — регистра ADCH.

Пример скетча, в котором результат, полученный из АЦП копируется в целочисленную переменную analogValue:

12345678910111213141516171819202122232425 int analogValue = 0; // значение аналогового сигналаvoid setup(){DDRB = B01000000; // pin 12 в режиме OUTPUTDIDR0 = 0x3F; // отключаем цифровые входыADMUX = 0x43; // измеряем на ADC3, используем внутреннее опорное напр.= 1.1ВADCSRA = 0xAC; // включаем АЦП, разрешаем прерывания, делитель = 16ADCSRB = 0x40; // включаем АЦ коналы MUX, режим скользящей выборкиbitWrite(ADCSRA, 6, 1); // Запускаем преобразование установкой бита 6 (=ADSC) в ADCSRAsei(); // устанавливаем флаг прерывания}void loop(){}/*** Процедура обработки прерывания АЦП ***/ISR(ADC_vect){PORTB = B00000000; // пин 12 переводим в состояние LOWanalogValue = ADCL; // сохраняем младший байт результата АЦПanalogValue += ADCH

Источник: http://robotosha.ru/arduino/analog-measurements-arduino.html

Измерение постоянного тока с помощью AVR. Простой вольт-амперметр

Дата публикации: 28 августа 2013.

Рейтинг:  5 / 5

Для измерения напряжения и тока потребуется 2 канала АЦП, используем каналы ADC0 и ADC1, к которым соответственно будут подходить сигналы измеряемых тока и напряжения.

Источник опорного напряжения внутренний на 2,56V, разрядность аналого-цифрового преобразователя 10 бит. Подопытный микроконтроллер Atmega8, тактируется от внутреннего генератора частотой 4MHz.

Схема устройства представлена ниже:

Измерение напряжения

С измерением напряжения все понятно, я писал об этом на одном из прошлых занятий. Измеряемое напряжение подается на делитель напряжения, и уже с делителя сигнал подается на вход ADC1.

Номиналы сопротивления резисторов делителя 100 кОм и 10кОм, значит соотношение входного и выходного сигналов 10:1. Максимальное напряжение подаваемое на вход делителя равно 28,13 V.

Коэффициент пересчета в реальное значение напряжения будет равен 2,75(11/4).

Измерение тока

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

Чем меньше сопротивление шунта тем лучше, т.к. меньше энергии рассеивается на нем. Возьмем шунт сопротивлением 0,1 Ом, используем обычный мощный резистор.

Расчитаем падение напряжения на нем при силе тока 1 А по формуле:U = I * R

U = 1А * 0,1 Ом = 0,1 V

Для тока 2А падение напряжение на шунте будет 0,2V. Величина достаточно малая чтобы напрямую подавать ее на вход АЦП, но есть способ усилить ее с помощью операционного усилителя.

Для нашего примера подойдет схема неинвертирующего усилителя, которая имеет бесконечно большое входное, и бесконечно малое выходное сопротивление, что является её несомненным достоинством.

Коэффициент усиления ОУ расчитывается по формуле:

Kу = 1 + (R2 / R1)

Этот коэффициент сделаем равным примерно 10, так чтобы измеряемый ток величиной 2 А соответствовал напряжению на выходе усилителя в 2 В. Так как ИОН на 2,56 V, больше этого значения на вход АЦП мы подать не можем, расчитаем разрядность измерителя тока:

2,56А / 1024 = 2,5 mA, что вполне достаточно.

На коэффициент 2,5(10/4) необходимо умножить измеренное значение АЦП, чтобы получить реальные показания тока на экране LCD.

Программа

Измерение напряжения и тока будем производить по прерыванию окончания преобразования АЦП.

Если был выбран канал ADC1(напряжение) то снимаем показания c АЦП, суммируем с прошлыми показаниями и помещаем в буфер, затем выбираем канал ADC0 и проделываем те же самые действия для измерения тока.

Этот цикл повторяется 400 раз, затем вычисляем средние значения измеренных величин напряжения и тока, умножаем на необходимые коэффициенты и выводим на экран. Исходный код нашей программы с подробными комментариями представлен ниже:

// Измерение постоянного тока с помощью AVR #include #include #include unsigned int voltage, current, adc_counter; volatile unsigned long voltage_value, current_value; // Функции работы с LCD #define RS PD0 #define EN PD2 // Функция передачи команды void lcd_com(unsigned char p) { PORTD &= ~(1

Источник: https://radioparty.ru/prog-avr/program-c/488-lesson-ammeter-avr

Ссылка на основную публикацию
Adblock
detector