Многоканальный вольтметр c LCD дисплеем на ATmega 8.
- Войдите на сайт для отправки комментариев
Итак, открываю тему потому что берусь за новый проект, это будет моя дипломная робота. Идея состоит в чём? Зашить в ATmega 8 загрузчик arduino ну и дуиновскими функциями уже запрограммировать контролер под многоканальный вольтметр. Выводить информацию буду на дисплей 16 символов 2 строчки. Есть некоторые мысли сделать ещё отправку цифр в UART ну а потом на комп где программа будет рисовать графики всякие и т.д.
Итак, диапазоны для каждого канала вольтметра будут разные, планирую сделать под напряжения:
два до 13.5 В.
Два до 6 В.
Для чего? буду делать тестер блоков питания ПК, во избежания ненужной роботы тема звучит многоканальный вольтметр а не тестер блоков питания.
Вот набросал код:
/*The circuit: * LCD RS pin to digital pin 2(PD2) * LCD Enable pin to digital pin 3(PD3) * LCD D4 pin to digital pin 4(PD4) * LCD D5 pin to digital pin 5(PD5) * LCD D6 pin to digital pin 6(PD6) * LCD D7 pin to digital pin 7(PD7) * LCD R/W pin to ground * 10K resistor: * ends to +5V and ground * wiper to LCD VO pin (pin 3)*/ #include <LiquidCrystal.h> LiquidCrystal lcd(PD2, PD3, PD4, PD5, PD6, PD7); unsigned long previousMillis = 0; byte interval = 250; // обновление дисплея void setup() { Serial.begin(115200); // больше скорости, больше lcd.begin(16, 2); lcd.print(" ******* "); // факультет lcd.setCursor(0,1); lcd.print(" ******** "); // група delay(2000); } void loop() { ////////////////////////////////////////////////////// unsigned int sensorValue0 = analogRead(0); unsigned int sensorValue1 = analogRead(1); unsigned int sensorValue2 = analogRead(2); unsigned int sensorValue3 = analogRead(3); unsigned int sensorValue4 = analogRead(4); unsigned int sensorValue5 = analogRead(5); ////////////////////////////////////////////////////// float voltage0 = sensorValue0 * (13.50 / 1023.00); float voltage1 = sensorValue1 * (13.50 / 1023.00); float voltage2 = sensorValue2 * (6.00 / 1023.00); float voltage3 = sensorValue3 * (6.00 / 1023.00); float voltage4 = sensorValue4 * (265.0 / 1023.0); // для тестов float voltage5 = sensorValue5 / 4; // аналогично ////////////////////////////////////////////////////// Serial.print(voltage0); Serial.print(","); Serial.print(voltage1); Serial.print(","); Serial.print(voltage2); Serial.print(","); Serial.print(voltage2); Serial.print(","); Serial.print(voltage3); Serial.print(","); Serial.print(voltage4); Serial.print(","); Serial.print(voltage5 * 6); Serial.println(); ////////////////////////////////////////////////////// unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis - 1; lcd.clear(); lcd.setCursor(0,0); lcd.print(voltage0); lcd.print(" "); lcd.print(voltage1); lcd.print(" "); lcd.print(voltage2); //lcd.print(" V"); lcd.setCursor(0,1); lcd.print(voltage3); lcd.print(" "); lcd.print(voltage4); lcd.print(" V"); lcd.print(" "); lcd.print(voltage5); } }
Всё вроде как работает:
Но при программной симуляции МК постоянно перегружается, пробовал прошивать мегу 8-ю, то вроде как всё было норм:
http://www.youtube.com/watch?v=qqzBh1T4fI0
На видео генератор случайных цифр в определённом диапазоне, сварганить делитель ну и саму схему ещё не успел.
Вообщем приглашаю всех к обсуждению как моей схемы, задумки и кода.
Кстати, код занимает почти всю память "Размер скетча в двоичном коде: 6 048 байт (из 7 680 байт максимум)" Помогите с оптимизацией и ускорением отправки даных в UART для построения более точных графиков, очень хочется.
ЗЫ на схеме выше нету кварцевого резонатора на 16 мГц, в схеме он обязательно будет, ядро будет используватся Optiboot.
.
Сам в ближайшем будущем планирую что то подобное сделать с питанием от батареи LiPo в одну банку. Но только хочу мерять и ток и напряжение и ватты, и потребленные ваты, с записью в ЕЕПРОМ. В общем если питать от батареи нужно наверно делать стабильный источник питания.
Зашить в ATmega 8 загрузчик arduino...
Кстати, код занимает почти всю память "Размер скетча в двоичном коде: 6 048 байт (из 7 680 байт максимум)"
не шейте загрузчик, если места и так мало - будет maximum_size=8192
ядро будет используватся Optiboot.
чем обусловлена замена дефолтного ядра ардуино на ядро оптибут??
Я думал что без загрузчика дуиновский код мега не примет.
Читал, что оптибут вроде как меньше места занимает и оптимизация круче.
Да и вообще выбрал путь дуиновских функции потому что тут всё проще и понятней, по крайней мере мне.
.
Сам в ближайшем будущем планирую что то подобное сделать с питанием от батареи LiPo в одну банку. Но только хочу мерять и ток и напряжение и ватты, и потребленные ваты, с записью в ЕЕПРОМ. В общем если питать от батареи нужно наверно делать стабильный источник питания.
Сам бы не против, но не хочется усложнять себе жизнь, возись ещё с ОУ... вот бы использовать внутренний опорник для измерений, но но вроде как неточный.
Да и моя цель - тестер для блоков питания ПК, есть ещё мысли сделать нагрузку на транзисторах для полноценного тестирования БП на исправность. Хотелось бы видеть пульсации напряжения в нагрузке чтобы находить больную линию в БП.
Я думал что без загрузчика дуиновский код мега не примет.
не примет по юарту - программатором по ISP нормально прошьётся.
Читал, что оптибут вроде как меньше места занимает и оптимизация круче.
код загрузчика меньше места занимает - код дуино можно проверить, скомпилив в ядре оптибут и дефолтном, но сильно сомневаюсь, что так.
Судя по строке : "Размер скетча в двоичном коде: 6 048 байт (из 7 680 байт максимум)"
размер загрузчика 512 байт - это и так минимум
А на счет оптимизации - надо аналог читать напрямую без адруиновских функций
забей на бутлоадер. из иде можно напрямую программатором писать, и это удобнее, если конечно UART не использовать
поставь маленький конденсатор по каждому входу чтобы цифры не бегали сильно
может для диплома поставишь получше дисплей? или это устраивает?
ну хоть 20*4. подпишешь что должно быть через двоеточие измеренное. так было бы лучше мне кажется
http://www.ebay.com/itm/New-2004-204-20X4-Character-LCD-Module-Display-For-Arduino-/350560713502?pt=LH_DefaultDomain_0&hash=item519f0bfb1e
http://www.ebay.com/itm/1-8-Serial-128X160-SPI-TFT-LCD-Modul-Display-PCB-Adapter-SD-Socket-4-Arduino-/280937300096?pt=UK_BOI_Electrical_Components_Supplies_ET&hash=item41692b0080
для второго незнаю требуется большой видеобуфер или нет
7 баксов? Дороговато, да и 16х2 у меня уже есть, а этот покупать нужно.
И без того будет на что тратить денежку, схему нужно распечатать на листе А1 ну и ещё чего-то там на 3 таких же листа, фото монтажной платы, блок-схема и ещё что-то.
Да и зачем 20х4 если всё помещается на 16х2:
V1=13.50 V2=6.00
V3=13.50 V4=6.00
Ровно 16 символов, то что мне надо.
А насчёт прошивки по UARTу - а почему бы и нет? Тем более, шью я дуинкой, ещё есть программатор Громова, но я его сделал почти одноразовым, весь разваливается.
А насчёт прошивки по UARTу - а почему бы и нет? Тем более, шью я дуинкой, ещё есть программатор Громова, но я его сделал почти одноразовым, весь разваливается.
по SPI...
*шото смущают меня такие будущие спенциалисты - потом ракеты падают.
Я не волшебник, я только учусь, рано мне ещё ракеты сбивать.
Кстати, не всё так плохо, есть ещё спецы покруче.
Итак, набросал примерно части вольтметра:
Жду критики...
У меня появилась идея, чтобы нормально защитить свою схемку "от дурака" резшыл поставить вместо диодов диодные мосты:
При таком раскладе юзер не сможет убить МК переполюсовкой, никак + можно будет мерить даже переменку, но для неё нужно по электролиту на каждый АЦП.
да но вы же измеряете низкое напряжение: до 14 и до 6 вольт. а диодный мост даст падение напряжения, и соотвтетственно неправильные измеренные значения
мне кажется лучше мост убрать
но если измерять например в диапазоне 3-6В и 9-14В (не от нуля) то теоретически можно и так. но надо проверять
Ну так подстроечным резистором откалибрую чтобы всё правильно показывало.
Мосты купил, буду тестить, что-то мне говорит что у них будет линейная характеристика.
HWman, мост на входе вольтметра это изврат. Стабилитрон на 5 вольт на входе АЦП ставят только когда analogReference гораздо меньше чем 5 вольт. Подстроечный резистор не должен регулировать в таких широких пределах. И вообще нет смысла что-то подстраивать для единичного образца. Рассчитать делитель, и при отладке измерить точно полученный коэффициент, и внести его в скетч. Аналоговый вход питания avcc желательно через индуктивность, и емкость на общий. А на на ноге Aref желательно конденсатор 10н..100н.
Спасибо, учту.
Итак, с мостами ничего не получилось, нелинейно там всё, скорей всего буду делать как-то так только стабилитрон будет на 5.6 В чтобы почти не мешал на всём диапазоне АЦП, тест на переполюсовку и завышение напряжения дуинка выдержала.
Вот другая проблема, почему то цыфры бегают:
На входе 12 В аккум... Может кто что подскажет?
На дуинке мега8-я, вольтметр собран по такой схеме
Только ещё по + резистор на 2 к, ато если подстроечник выкрутить вверх то запросто можно схечь стабылитрон, и он превращается в КЗ.
HWman, Для начала отказаться от подстроечнного резистора, от него вреда больше чем пользы. Поставьте 10 ком от ноги ацп на общий, и как можно ближе к выводам контроллера, это важно. Второй резистор рассчитать под нужное максимальное входное напряжение стандартной формулой делителя напряжения. От дефолтового референсного 5 вольт лучше отказаться. Как минимум использовать внутренний ИОН, а ещё лучше внешний, а какой нибудь REF195/198 вообще шикарно. Если ничего не поможет, тогда можно пробывать усреднять программно. Но лучше выжать масимально аппаратно прежде чем усреднять результаты. У меня от внутреннего reference в меге168 девиация показаний analogRead не более +/- 1 единицы счёта. Не думаю, что в меге 8 хуже. Судя по вашим цифрам у вас (13,04-12,93)*1023/5=22 Т.е. +/- 11 единиц счёта, что явно много.
ref198 вообще шикарно))
Я на днях юзал lm317 и очень понравился уровень стабилизации напряжение, на вход подавал 5-25 В на выходе стабильно было 1.500 +/- 1 мВ, вот и думаю а может сделать как-то на 317-ке? тем более у меня их есть 2 штуки. Вот только думаю делать только для одной ножки, или же сделать всё питание? Сделать по входу и выходу норм фильтры(кроме керамики ещё конденсаторы на 1000 мкФ). Всё это дело будет питаться от трансформаторного БП на 10-12 В.
Вот набросал схему на 5 В:
В моём случае стабилитрон не только защищает АЦП от перенапряжения а и при переполюсовке выполняет дополнительную защиту - шунтируя АЦП.
Единственное - он немного влияет на делитель, но это я определю экспериментальным путём и постараюсь как-то программно учесть.
А ещё в моей схеме будет 2 перемычки, каждая будет задавать напряжение 0-15В и 0-6В на пару АЦП, тоесть если замкнуто тогда 0-15В, нет - 0-6В, тоесть перепаиваем резисторы и вуаля у нас 4 кан. вольтметр на 15В, или на 6В.
Мда, а вот с шумом АЦП я такого не ожидал, думал что будет как у dimax"а +/- 1 значение АЦП.
PS С каждой новой железкой мне нужно будет искать и переводить на неё документацию чтобы что-то по ней было в работе. Хочется сделать как бы максимально просто.
HWman, у лм 317 может быть шум на выходе, который вы подручными тестерами не увидите, разве что очень хорошим осциллографом. Этот шум будет только усиливать пляску показаний вольтметра. Лучше используёте внутренний ион меги, или ставьте что-то приличное.
Собрал делитель по схеме и...
Похоже на то что я использовал слишком большой номинал в резисторе делителя, аж 100 кОм.
HWman, неплохо бы комментировать что вы измеряете. Как я понял, на входе снова 12 вольт с аккумулятора, а вертикальная шкала в "попугаях" команды analogRead ? Если так, то девиация соответствует норме. Можете остальное добить программно.
Да, вертикальная шкала это значение которое возвращает АЦП, по питанию дуинки стоит ещё конденсатор на 3300 мкФ, без него больше "скачет".
Точность если уж грубо получилась по линиях 0-15 +/- 0.05 что есть вполне терпимо для моей задачи, А можно как-то спрятать те цифры что идут после десятых? Гуглил на тему округление ардуино и толком ничего не нашёл, может кто подскажет что? Мне нужно на ЛСД выводить например 12.8 а выводит 12.83, причём нужно не округлять а игнорировать цифры после десятых, вот такой у меня каприз.
На ум приходит умножить число на 10 и преобразовать его в инт потом обратно, но, дуинка почему-то выводит не 12.8 а 12.80 если использовать тип флоат...
HWman, с ёмкостью правильно, а источник опорного напряжения в итоге так и остался дефолтовый?
Спрятать лишние цифры легко:
lcd.print(voltage0,1);
Цифра после запятой -количество цифр выводимых после запятой.На скорую руку потестил и очень то большой разницы между ИОН или напр. пит. не увидел, но время покажет.
/*Спрятать лишние цифры легко:
lcd.print(voltage0,1);
Цифра после запятой -количество цифр выводимых после запятой.*/Спасибо.
Как считаете, сколько раз нужно считать значение АЦП чтобы нормально усреднить?
Как-то больше шума при внутренем ИОНе.
Как считаете, сколько раз нужно считать значение АЦП чтобы нормально усреднить?
Вообще выбор метода усреднения, это огромная тема для дискуссий. По моему мнению усреднять нужно тогда, когда необходимо вывести точность измерения до цены одного отсчёта. Если у вас полная шкала будет 20 вольт, то один отсчёт будет примерно 20 милливольт. Как я понял вам такая точность не нужна, следовательно лучше не усреднять, а убирать избыточность. Проще всего это сделать так:
И дальнейшее преобразование в вольты делать из value. По поводу внутреннего ион меги8 -были мнения, что он слабоват.
Спасибо, только не совсем понял что делает этот код, типо плавное увеличение и плавное уменьшение value ?
HWman, эта команда просто не пропускает нестабильные данные на единицу отличающиеся от прочтённых ранее. Вариант программного устранения шума ацп вместо традиционного усреднения. Ваш график нарисовал бы ровную линию.
А можно и порог "шумодава" задавать, если слегка модифицировать код:
в данном случае значение переменной threshold и есть порог срабатывания. здесь он равен величине 2.
Спасибо за код.
Так как я выведу ноги RXD TXD RES GND то в принципе можно будет шить через этот разъём правда? Ардуиновский загрузчик уже в меге зашит ещё со времён как я в уно поджёг 328р, перебивался 8-й мегой, тогда и зашил загрузчик.
Вот только не могу найти информации по прошивке дуинки по юарту, может подскажет кто?
Вот только не могу найти информации по прошивке дуинки по юарту, может подскажет кто?
так, а чего искать-то - цепляешь к RX-TX дуино TX-RX железки сом-порта и шьёшь как и всякую дуино.
Вот что есть на данный момент:
Схему ещё не нарисовал, LC фильтр по питанию, везде конденсаторы на 0.1 мкФ, и по питанию меги и на АЦП, делитель собрал как тут, только делитель рассчитал на 15 В макс.(10к и 20 к ) пока без диодов, стабилитрон начинает влиять на измерения где-то на 95% значения АЦП, в целом это вполне терпимо.
Иногда Непонятно от чего LCD дисплей начинает выводить всякие кракозябры хотя в юарт идут нормальные цифры, подозреваю что это из за того что я для удлинения использую IDE шлейф от ПК, хотя может что-то и с самим дисплеем.
Позже может видео сниму.
HWman, ну и наворотили вы дел...., всю секцию от начала loop и до вывода на экран нужно переделывать. Там полный хаос...
Почему же? Сначала обнулим переменные, потом 10 раз делаем измерение, подавляем шумы, получаем среднее арифметическое, выводим цыфри в сериал.
Я переделаю с удовольствием но что?
HWman, тот метод "шумодава", о котором я писал выдаёт уже полностью усреднённый результат, и он не совместим с методом высчитывания среднего-арифметического. Получается сначала вы восстанавливаете максимальную точность, потом всё полученное снова срезаете, в чём смысл? Нужно выбрать либо одно либо другое.
Просто с подавлением шума меньше дёргаются сотые на линии 0-15В, надо будет ещё поэкспериментировать...
Вот так на данный момент выглядит плата:
Как видите стабилитроны только на 2-х каналах пока, на одному 0-15В и второй на 0-6В, хочу увидеть на сколько они влияют на измерения. Вот график разряда конденсатора который удалось получить при помощи моего вольтметра:
Синий - с стабилитроном, зелёный просто делитель, как видим стабилитрон начинает влиять уже после 6.2 В, но я делаю 2 канала на 0-6В так что всё что выше 6В будет игнорироваться и выводить что на максимальное напряжение на канале.
Земля делителей соединяется с землёй контролера только в одной точке(чистая земля), все минуса LCD подключении к земле делителя(грязная земля).
Не знаю правильно я сделал что разместил дроссель LC фильтра питания около кварца.
Видео работы http://www.youtube.com/watch?v=ybsw6OIVI74
А вот глюки при выводе напряжения на LCD http://www.youtube.com/watch?v=Oy2KahrZnE0
Иногда появляются когда землю прикоснуться до "-" аккума, иногда сами по себе появляются, если коснуться почти любого контакта LCD то иногда глюки пропадают и начинает нормально выводить цифры, как я говорил, в юарт цифры идут нормальные не зависимо кракозябры ли на LCD или нет.
HWman, в плане избавления от мандража показаний метод среднего арифметического малоэффективен. Либо используйте то, что я предложил, либо ищите более эффективный способ. Для статических состояний нужна примерно такая методика - брать порядка 50 замеров, и определить математически, какой из результатов отсчётов был самый частый, и этот результат считать правильным. По поводу lcd не совсем ясно, для начала керамику ему по питанию, я бы ещё качество земли проверил. После lcd.begin и перед первым обращением на вывод не помешает небольшую паузу вставить.
http://www.youtube.com/watch?v=Sz7y-EXY3nY
Если минусовой провод "чиркать" по минусу аккума то появляются/пропадают кракозябры, а если держать тот же провод пальцом и чиркать тогда всё нормально. Наверное я зря землю LCD развёл на грязную землю, я думал что это не на столько критично...
HWman, шлейф тоже нужно ликвидировать, сантиметров 15 оставить максимум. Ещё лучше без разъёмов, всё на пайку. И керамику по питанию само собой.
А делаю 10 раз измерение АЦП потому что если разово мерять то шумы достигают +/- 8-10, если же 10 раз измерять то +/- 2-3 с подавлением шума вообще +/- 1-2.
Ну, пока ещё проект не закончил, роботы ещё много, хочу если не весь код так большую его часть перевести на Си, ато итак "Размер скетча в двоичном коде: 6 276 байт (из 7 680 байт максимум)".
Ещё вынашиваю идею сделать перевод порта в Z состояние когда АЦП будет возвращать 1023, такая себе программная защита от перенапряжения...
А ещё думаю что было бы не плохо считывать напряжение питания чтобы при критическом падении напряжения отключать подсветку дисплея и уходить в глубокий сон, если уж использовать возможности МК так на всю.
Сложил шлейф гармошкой оставив примерно сантиметров 10 и теперь очень сложно сделать так чтобы появились кракозябры, видимо шлейф работает как антенна, а чувствительная электроника самого дисплея успешно ловит всё что попало...
Дисплей на чистую землю не разводил по банальной причине - кончился припой.
Захотелось уменьшить энергопотребление отключая подсветку дисплея и переходом на 2 сек в сон если напряжение меньше 0.1 В на портах, но тут у меня возникла проблема, почему-то не работает прерывание по таймеру, оно как бы работает и как бы нет, дело в том что МК переходит в ресет после пробуждения а не продолжается выполнение кода где было вызвано прерывание по таймеру.
Вот код:
Может кто подскажет что у меня не так в коде?
Во всех апноутах по улучшению качества АЦП рекомендуют применять оверсемплинг -- суммирование большого числа измерений, с последующим вычислением среднего. Вычисление среднего может использовать небольшую хитрость, когда деление заменяется операциями сдвига. Сдвиг на один разряд вправо соответствует целочисленному делению на 2 с округлением. Если мы берем среднее по шестнадцати семплам, то код может выглядеть следующим образом:
Но это еще не вся "магия". Если брать число замеров кратное "4 в степени х" (4, 16, 64, 256...), то вместе с усреднением можно получить и увеличение разрядности АЦП, а следовательно, точности, если "недосдвинуть" полученную сумму вправо. Так, если в предыдущем примере сдвинуть переменную aSum не на 4, а на 3, то результатом будет представление среднего от 16 измерений в одиннадцати-битном разрешении. Если сдвинуть только на два, то, соответственно, в двенадцати-битном.
Шестнадцать семплов это все-таки маловато для качественного усреднения, а по сему лучше не зажиматься особо, а брать по 256 или 1024, если конечно измеряемый сигнал не является быстро меняющимся. По своему опыту знаю, что 256 семплов при последущем приведении к 12 битам дает и приемлемое усреднение и отчетливое увеличение точности.
Оу, спасибо, неплохо.
Черт, только что заметил, что шестая строка с опечаткой, а отредактировать форум не дает. Правильно она должна выглядеть так: return aSum >> 4; Знака равенства там не должно быть.
Что "return aSum >>=4;" что "return aSum >> 4;" возвращает одно и тоже. Код работает чётко, удалось повысить точность до десятых вольта, использую во такой код:
Функция возвращает от 0 до 16368 что соответствует 14-ти битному АЦП, МК считывает 4 канала АЦП таким образом около 30 раз на секунду против 100 как раньше, но шумы поменьше, вообщем не велика потеря. При таком расширении можно спокойно делать делитель на 25 В, получится вольтметр на 20В, остальные 5В уже будет впрягаться стабилитрон, сделаю это мёртвой зоной, он как мне кажется будет и защищать от переполюсовки шунтируя АЦП при не правильном подключении.
В целом очень доволен такой вещью как оверсемплинг АЦП и скетч в целом не сильно вырос :) .
Вот пока не разобрался ещё с прерываниям по ватчдогу, может кто подскажет что у меня не так.