Arduino зарядное устройство с дисплеем. Измерение напряжения с помощью Arduino. Дальнейшая работа над лицевой панелью

Старый добрый "Выпрямитель
В14 зарядный" !
Был всегда ты как спаситель :
Выручал нас, ненаглядный!

При жаре и зимней стуже
Оживлял аккумулятор;
Даже если я простужен,
Ты - как робот Терминатор!

Не ломался, не сдавался
Даже в самый трудный час;
Когда надо - напрягался,
Заряжая всё для нас.

Сорок лет уж пролетело
C добрых Брежневских времён,
Когда корпус твой, как тело
На заводе был скреплён.

И с тех пор исправно служишь
Ты на благо всех машин,
От Союза отличаясь
Тем, что правда нерушим.

Но пришла пора меняться,
Скинуть тяжкий груз времён,
Чтобы смог ты ввысь подняться,
Чтоб как Хокинг стал умён.

Если спросит кто фальцетом
"Как же сделать это мне?" -
Не волнуйтесь, я об этом
В данной расскажу статье.

Минутка наркомании.

Приветствую вас, дорогие читатели! После почти четырёхмесячного перерыва я снова в деле и в качестве отчёта о проделанной работе считаю необходимым написать данную статью. Долго думал, с чего же начать, ну не постить же в четвёртый раз про видимость нулевую и т.д. - эта цитата и так исправно работала на меня на протяжении трёх последних статей, так что с неё хватит - пусть отправляется на заслуженный отдых! Ну а я тем временем воспользуюсь новой экспериментальной фишкой, назовём её "минуткой наркомании" - такой весёлой и непринуждённой минуткой "с приветом", плавно наводящей на основную мысль статьи. 🙄

Итак, как уже было озвучено в "минутке", сегодня я расскажу вам о том, как я превратил старинное зарядное устройство начала семидесятых в новое, современное, с управлением от микроконтроллера. Мысль такая пришла мне оттого, что мой друг позвал меня к себе на пиво в момент, когда у меня заряжался аккумулятор. Я бы и рад был пойти, но вот незадача - зарядное-то нужно было постоянно контролировать! Бегать к нему раз в полчаса, а то и чаще, чтобы проверить напряжение на аккумуляторе, и если бы оно превысило максимум - уменьшать мощность соответствующим переключателем на передней панели. Согласитесь, неудобно: ты постоянно прикован к заряжающемуся аккумулятору и не можешь никуда отойти, а если вдруг проворонишь нужный момент - аккумулятор тебе спасибо не скажет. С другой стороны, он и так его не скажет: он же памятник говорить не умеет))))

Шутки - шутками, а мне давно хотелось сделать что-то серьёзное на Arduino, с которым я познакомился ещё в ноябре, забрав заветную посылку от китайцев из Aliexpress с микроконтроллером, шилдом и другими ништяками на почте. И вот она, отличная возможность - бери, да делай! Так что я взял и начал, непосредственно, делать!

Схема зарядного устройства

В начале приведу вам весьма кликабельную схему готового устройства:

Список основных компонентов

  • 8 конденсаторов: 2 по 22 пФ , 1 на 100пФ , пару штук по 100 мФ , и для питания - один большой на 6.3 вольта и два больших на 16, например на , и 1500 мФ соответственно (можно и все на 16 вольт или больше, без разницы).
  • Программируемый микроконтроллер Atmega328 с кварцем на 16 МГц и желательно шилд для него (листать несколько страниц до первого шилда, это будет самый дешевый вариант), чтобы было удобно прошивать.
  • По той же причине - зажимные сокеты для вышеназванной микросхемы. Хотя можно, в качестве эконом-варианта обойтись и обычными . Ну или припаять провода к МК и прошивать по ним другой ардуиной или прошивальщиком - как вам удобно.
  • 9 транзисторов КТ315 и 1 КТ815 (или аналоги) - выпаять из любой старой советской техники.
  • 8 белых рассеивающих светодиодов и 1 зелёный .
  • 9 релюх с катушками на 12 вольт: одна на 220 V, четыре под 12 V 16 A и четыре поменьше под 12 V 12 A . Последние 8 нужны как можно меньшего размера.
  • 40 резисторов: 15 по 560 Ом , 12 килоомных , 8 по , 2 по 10k и по одному экземпляру 3k3 , 4k7 и 30k .
  • Парочка диодов под 12 вольт: один на полампера, второй минимум на ампер, запас не помешает. Выпаивается откуда угодно, например из дохлых БП.
  • Какая-нибудь лампочка, можно светодиод с резистором, горящие от 220 вольт. Вообще неонка бы там круто смотрелась!
  • Шестнадцатисегментный экранчик из старого системника для вывода на него текущего напряжения. Ну или три семисегментных . Или вообще забить болт на отображение текущего напряжения: это, всё-таки, автоматическое устройство, напряжение оно контролирует само, вам его знать не обязательно, в крайнем случае тестером померяете. Вместо экранчика можно просто парочку светодиодов поставить, чтобы ардуина ими перемигивала, мол, не зависла я, работаю, всё под контролем! (Нет, я ни разу не видел зависшей Ардуины, но тем не менее надо быть готовым ко всему.) 🙄
  • 3 сдвиговых регистра 74HC595
  • Ну и что-нибудь типо половинки вот такой монтажной платы (я купил на ебэе 10 штук за стакан компота):

Хочу заметить, что практически все компоненты, используемые в данном проекте, не имеют точных номиналов и могут быть заменены на аналогичные или похожие либо с минимальной адаптацией схемы и прошивки, либо вообще без каких-либо изменений. Я старался использовать те детали, которые буквально валялись у меня под рукой: например, подавляющее большинство используемых тут резисторов и транзисторов я недавно выпаял из допотопного магнитофона Vilma, останки которого после распаивания благополучно отправились на свалку. Так что потраченная сумма на покупку деталей для этого устройства не превышает $15, и то, большая часть бюджета ушла на релюхи.

Исходная версия зарядного

К сожалению, у меня не нашлось фотографии этого зарядного в исходном состоянии, поэтому всё, что я могу вам предложить на данном этапе - фото с уже снятой крышкой, открученной механической частью переключателя мощности (слева) и ручки этого переключателя (справа). Электрическая же его часть торчит сверху устройства. Также из своего родного отверстия вынут тумблер переключения напряжений (6 или 12 вольт):

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

Принцип работы исходного устройства

Само зарядное устройство построено по простому принципу - на первичную обмотку трансформатора подаётся 220 вольт, соответственно на вторичной также появляется переменное напряжение. Мощностью можно управлять благодаря тому, что со вторичной обмотки есть несколько выводов (всего 9). Это означает, что между первым и каждым из последующих восьми выводов получается всё большее количество витков, а чем больше витков, как известно, - тем выше напряжение (то есть ток или мощность - как вам будет угодно). Эти 8 выводов приходят на тот самый переключатель, с помощью которого вы и выбираете текущую мощность заряда аккумулятора.

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

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

Выбор способа коммутации вторичных обмоток

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

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

Ах, да! Чуть не забыл! На самом деле со вторичной обмотки было не 9 а 10 выводов, первых два были один для шести вольт, другой для двенадцати, оба шли к тумблеру, а уж потом к диодному мостику:

Но так как я не планировал заряжать аккумуляторы на 6V - от этой функции я отказался, поэтому выкинул тумблер (из конструкции, а не вообще) и заизолировал провод для шести вольт, а двенадцативольтовый пустил с трансформатора напрямую на диодный мост.

Так как же всё-таки коммутировать? Тут уже либо транзисторами, либо тиристорами, либо с помощью реле. И я выбрал последний вариант, ведь релюхи меньше транзисторов / тиристоров и, в отличие от них, совсем не греются, если взять их с запасом по току. Так я и сделал - купил 8 небольших релюшек с катушками на 12 вольт, 4 штуки на 16 ампер и 4 на 12. По размеру они как раз умещались в свободное пространство внутри корпуса зарядного:

Алгоритм работы устройства

И вот тут, окончательно определившись со способом коммутации выводов вторичной обмотки, я считаю нужным сделать некоторое "лірычнае адступленне" и поговорить об алгоритме функционирования устройства. Первоначально для его составления я просто проанализировал свои действия во время зарядки аккумулятора этой шайтан машиной и на основе этого начал набрасывать первые штрихи нового скетча, который вы можете забрать . Я частенько буду цитировать некоторые его кусочки, чтобы вы понимали, что там к чему, так что, на вашем месте, я бы открыл его прямо сейчас и изучал бы по ходу этого повествования.

Для начала введём 3 важнейших параметра:

// Максимальное напряжение * 10
byte maxVoltageX10 = 148;

// Напряжение * 10, при котором уже нельзя увеличивать мощность
byte powerUpMaxTreshold = 142;

// Напряжение * 10, при котором мощность повысится принудительно
byte powerUpMinTreshold = 136;

Умножены на 10 они во-первых потому, что при их вычислении удобнее пользоваться целыми числами - никаких округлений и т.д., во-вторых потому, что на экран, фактически, и выводятся такие числа, а запятая - она как-бы виртуальная, поэтому незачем делать в коде никому не нужные вычисления, и так понятно, что это 14.8, 14.2 и 13.6 вольт соответственно.

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

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

Третий параметр введён специально для случаев, когда заряжаться будет подключённый к машине аккумулятор. Например, кто-то включил радио -> напряжение просело ниже этого значения -> поднимаем мощность. Но что, если нагрузка, просаживающая напряжение до этого уровня, является кратковременной (включение фар или прикуривателя), либо периодической, с определённой частотой (например от ударов сабвуфера), и будет выходить так, что как только мозги повысят мощность - её нужно будет сразу снижать, потом сразу опять повышать и т.д.? Получится замкнутый круг, релюхи будут постоянно щёлкать, изнашиваясь, да и для аккумулятора, возможно, это будет не очень полезно... Специально для этого можно сделать нашу систему как-бы самообучающейся, введя дополнительный параметр:

// Если между повышением мощности по powerUpMinTreshold и её понижением прошло менее, чем столько миллисекунд, то powerUpMinTreshold снизится на 1
unsigned int powerUpMinTresholdTimeout = 60000;

Как видно из комментария, благодаря этому параметру powerUpMinTreshold будет снижаться на одну десятую вольта каждый раз, как мозги будут понижать мощность менее чем через powerUpMinTresholdTimeout миллисекунд после её повышения. Всё, проблема решена: пощёлкают релюхи один раз, пощёлкают второй, а на третий они уже 10 раз подумают перед тем, как щёлкнуть. Ха-ха-ха, не с теми связались!

Ну вот, с основой алгоритма вроде более-менее разобрались, теперь переходим к подробностям и нюансам.

Я сразу запланировал, что питание всей системы будет осуществляться от самого аккумулятора, а 220 вольт - подключены через реле, управляемое мозгами (то есть Ардуиной), благодаря чему у нас будет возможность отключить подачу питания на устройство в случае аварийной ситуации или по завершению зарядки аккумулятора. Более того, от реле будет меньше искрения, чем от засовывания вилки в розетку, так что этот вариант ещё и надёжнее. Про её подключение будет, естественно, написано ниже, ведь пока мы обсуждаем лишь теоретические вопросы.

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

// Задержка в миллисекундах перед включением зарядки
unsigned int powerOnDelay = 2000;

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

if (powerLevel == 1) {
delay(powerOnDelay);

}

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

Кстати, в коде есть весьма интересный параметр:

// Уровень мощости (начальный)
byte powerLevel = 0;

Он, как вы уже догадались, устанавливает начальный уровень мощности и был введён на очень ранней стадии разработки прошивки и на данный момент используется там просто как текущий уровень. Любопытно то, что если сейчас его увеличить, то условие, описанное в предыдущем пункте, никогда не сработает, то есть 220 вольт на первичную обмотку трансформатора так и не попадут, а значит устройство заряжать аккумулятор не будет. Пичалька.

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

// Время, через которое можно повышать мощность на один уровень, в миллисекундах
int powerUpTime = 5000;

То есть между двумя повышениями мощности должно будет пройти как минимум 5000 миллисекунд, за которые напряжение уже может подняться выше powerUpMaxTreshold и тогда повышать мощность будет уже не нужно.

Что касается понижения мощности, то тут вообще всё просто: программа периодически проверяет, а не превышает ли текущее напряжение максимально допустимый уровень, и если превышает - мощность надо снижать:

// Понижение мощности
if (voltageX10 > maxVoltageX10) {

Но при выполнении этого условия должны быть два варианта развития событий. Первый, это когда текущий уровень мощности больше единицы:

В этом случае нам нужно выставить мощность на уровень ниже и дальше продолжать зарядку. В противном же случае, когда уровень мощности уже и так стоял самый низкий - просто выключаем питание и моргаем экранчиком. Улыбаемся и машем, короче говоря, аккумулятор полностью заряжен!

Вообще, как показала практика, те аккумуляторы, которые заряжал я, ещё на втором уровне мощности можно было спокойно снимать с зарядки, ведь ток при этом уже опускается ниже 500 мА. Тем не менее не стоит пренебрегать функцией автоотключения - аккумуляторы же разные бывают...

Также для понижения мощности есть свой параметр задержки, схожий с параметром powerUpTime для повышения:

//Пауза после понижения мощности, в миллисекундах
int powerDownPause = 500;

Правда, реализован он проще, через обычный delay() после непосредственного снижения. Я посчитал, что полсекунды - это не настолько большой промежуток, чтобы использовать его как дополнительное условие в операторе выбора, но каждому своё, так что если кому-то из вас будет нечем заняться - в первую очередь можно было бы доработать этот кусок кода по принципу powerUpTime.

Удивительно, как это я столько уже написал и не сказал, откуда же я беру, собственно, само текущее напряжение. Исправляемся:

void loop() {
ct=millis();

Получается, что в начале каждой итерации loop"а, который, как известно, просто бесконечно повторяется после запуска системы, мы делаем две вещи. Сначала записываем в переменную ct текущее время с момента запуска микросхемы, в миллисекундах, а далее мы как раз вычисляем текущее напряжение с помощью процедуры analogRead(), используя заданный в начале скетча номер аналогового входа мониторинга:

// Аналоговый вход для мониторинга напряжения
byte voltageInput = 5;

А также 2 коэффициента, о которых я подробно расскажу позже:

// Коэффициент вычисления напряжения (на него делится)
float voltageX10Coefficient = 5.11;

// Сдвиг вычисления напряжения (он прибавляется)
int voltageX10Shift = 35;

Но всё было бы слишком просто, если бы всё было так просто. Поэтому для усложнения алгоритма в код были введены ещё 2 переменные:

boolean goingUp = true, isUpAfter = false;

Первая переменная сообщает нам, в каком состоянии находится сейчас процесс зарядки. Её значение истинно до тех пор, пока мощность не снизится в первый раз. То есть goingUp = true говорит нам о том, что мы не так давно включили зарядное и оно ещё заряжает аккумулятор максимально возможным током, ни разу не снизив его для защиты от перенапряжения.

Со второй ваще всё сложно - она нам говорит о том, происходило ли повышение мощности после того, как goingUp стал равен false и устанавливается следующим простым кусочком кода в конце процедуры повышения мощности:

if (goingUp == false) {isUpAfter = true;}

Вы щас, наверное, думаете, а нахрена всё это нужно? Щас обьясню!

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

if ((powerLevel <8) && (ct > powerTime + powerUpTime) && ((goingUp == true && voltageX10 < powerUpMaxTreshold) || (goingUp == false && voltageX10 < powerUpMinTreshold))) {

Как видим, в первой фазе зарядки мы повышаем мощность, если текущее напряжение меньше powerUpMaxTreshold, а во второй фазе - если оно меньше powerUpMinTreshold: это те самые параметры, о которых я говорил в начале.

Если условный оператор, написанный выше, всё же выполняется, а этот самый goingUp равен false, то в дело вступает запатентованная система дополнительной проверки напряжения:

boolean stillLow = true;
if (goingUp == false) {
for (int x=0; x <= upCycles; x++){
voltageX10analogRead(voltageInput)+voltageX10Shift)/voltageX10Coefficient;
if (voltageX10 > powerUpMinTreshold) {stillLow=false; break;}
delay(1);
}
}
if (stillLow == true) {

В которой на сцену выходит новое действующее лицо:

//Количество миллисекундных итераций проверки напряжения перед поднятием мощности
int upCycles = 5000;

Дело в том, что при сигнале на повышение мощности после того, как goingUp стала false, мы скорее всего имеем дело с какой-то непостоянной нагрузкой - тот же сабвуфер, как я уже предполагал, или ещё какая-нибудь неведомая фигня. А раз так, то почему бы нам вместо того, чтобы тупо поднимать мощность, лишний раз щёлкая нашими драгоценными релюхами и рискуя получить на мгновение напряжение на аккумуляторе выше максимально заданного, не устроить простую проверку: 5 тысяч раз (upCycles) с интервалом в одну миллисекунду проверить текущее напряжение, и если оно хоть раз, слышите, хоть один раз превысит powerUpMinTreshold - всё, хана, никакого повышения не будет, сворачивайте удочки! Простая, но действенная проверка.

isUpAfter, в свою очередь, помогает нам реализовать функцию уменьшения powerUpMinTreshold (я говорил о ней в начале), вот, как она выглядит:

if ((isUpAfter == true) && (powerTime > ct - powerUpMinTresholdTimeout)) {powerUpMinTreshold = powerUpMinTreshold - 1;}

Здесь powerTime - это время последнего повышения мощности на текущий момент.

Дело в том, что, кроме условия упомянутого выше powerUpMinTresholdTimeout, уменьшать его нам нужно лишь тогда, когда мы опускаем мощность после того, как предварительно её подняли после того, как уже начали опускать. Я ж говорил, что с этим isUpAfter всё сложно!

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

Подготовка блока реле

Итак, разобравшись с тем, какие контакты релюшек за что отвечают и определившись с их размещением друг относительно друга, я приступил к склеиванию:

Для этого я использовал валявшийся неподалёку "Момент - Кристалл". Не буду говорить, что это какой-то там супер-пупер клей, но по своим свойствам он меня устраивает. Лучше, конечно, использовать Хайгировский "Склею Насмерть", он сохнет быстрее и вообще затвердевает в конце, но его в тюбике в 2-3 раза меньше, а стоит он раза в полтора дороже Момента, поэтому, как говорил герой одного хорошего советского мультика, "И так сойдёт!".

По склейке всё просто и написано на тюбике - нанести на обе поверхности, подождать 5-10 минут и сильно сжать (ага, так сильно, чтобы зажатый между релюшками уголёк превратился в алмаз 😆):

Вот и всё, релюшки сжаты. Как видите, центральные контакты я разместил рядом друг с другом, их всё равно надо будет соединять между собой:

Точно так же я поступил и с большими релюхами, а потом склеил эти 2 получившихся блока вместе друг с другом, после чего начал припаивать к контактам провода. Толстый жёлтый провод подключён по очереди ко всем релюхам - это выходная шина, которая дальше пойдёт на диодный мост, красные провода - на 4 первых вывода со вторичной обмотки трансформатора, а маленький жёлтый проводок, идущий по очереди через все релюшки - это постоянные +12 вольт катушек. А минусы катушек, как вы уже догадались - это коричневые и бело-какие-то-там проводки, к ним мы в скором времени ещё вернёмся.

Та же конструкция, но уже с другой стороны, с новыми припаянными проводками для подсоединения выводов вторичной обмотки. Причём с больших релюх на 1 вывод приходится по 2 проводка - так уж сделана эта модель реле, для более равномерного распределения нагрузки и, как следствие, меньшему тепловыделению:

Так как ток, который жрут катушки в таких релюхах (~100 мА), намного превышает максимальный ток, который можно брать с выходов Arduino (~40 mA) или сдвигового регистра 74HC595 (~25 mA), для включения катушек реле нужно использовать транзисторы. И старые добрые оранжевые КТ315 будто созданы для этого!

Это n-p-n транзисторы, поэтому в схеме, если объяснять по-простому, ток должен идти от плюса к катушке, потом из неё на коллектор транзистора и дальше из эмиттера транзистора в минус. Открывается же этот транзистор током из базы в эмиттер, но ток там нужен совсем небольшой, поэтому базы транзисторов мы подключаем через резисторы в 1 кОм (1000 Ом):

Теперь осталось припаять к резисторам недлинные проводки, не забывая всё тщательно изолировать, и можно закреплять - лично я решил приклеить транзисторы к релюхам сбоку, чтобы они не путались и ничего не оторвалось:

Как видно на фото, транзисторы отлично расположились с двух сторон блока реле, также я залил клеем остальные контакты, чтобы быть уверенным, что ничего нигде не закоротит и не сгорит:

Транзисторы приклеены и блок почти готов:

Теперь перед нами встаёт вопрос - к чему же подключить транзисторы? К Arduino? Нет, тогда не хватит выходов для других компонентов, и вот в таких ситуациях в дело вступает спасительная микросхема - сдвиговый регистр 74HC595. Про него и так много написано в интернете, поэтому я не буду расписывать тут 3 абзаца, скажу лишь, что благодаря таким вот микросхемам можно увеличить количество выходов Arduino, пожертовав для этого лишь тремя. Причём их можно соединять последовательно в цепочку. Есть разные варианты подобных микросхем, например на 16 выходов или на 8, в разных корпусах. В данном проекте я решил использовать вариант на 8 выходов в маленьком корпусе SO-16. Работа хоть и ювелирная, зато всё это занимает мало места, которого и так не хватает в компактном корпусе устройства, не рассчитанного на подобные доработки:

Для индикации текущей мощности устройства я решил использовать 8 светодиодов, по одному на каждую пару транзистор / реле, для этого я использовал восьмижильный шлейф, подпаяв каждую жилу к соответствующему каналу управления, но не сразу к регистру, а к резисторам, электрически разницы нет, но механически так надёжнее, я считаю. Микросхему я, после тщательной проверки (о ней будет ниже), залил тем же самым клеем и ещё раз прошёлся им по всем транзисторам - теперь эта система стала ещё более "цельной" и крепкой:

Система индикации напряжения

Настала пора теоретических испытаний системы индикации. Для вывода текущего напряжения аккумулятора я использовал экранчик от старого системника времён первых пентиумов. С ним нет никаких премудростей, каждый сегмент - это простой зелёный светодиод, работающий от 2-2,1 вольт. Исключение составляет лишь единица - в ней 2 сегмента запараллелены и выведены на одну ножку. Всего у экранчика 16 ног: 1 плюс и 15 минусов. То есть на плюс всегда подаётся питание, а подача земли на определённую ножку зажигает нужный нам сегмент - всё предельно просто, но как это реализовать? Для этого опять же используем сдвиговые регистры, на этот раз 2 штуки. Для прототипирования на макетной плате я использовал такие же 74HC595, но уже в корпусе DIP-16, ведь с ними работать намного удобнее. На следующей картинке, как вы видите, система уже собрана и работает:

Но данная система сильно отличается от того, что вошло в конечное устройство. Начнём с того, что изначально для питания экранчика я решил использовать стабилизатор, хотя в итоге я от него отказался и каждую ногу экрана подключил через резистор в 560 Ом, во вторых на этой схеме питание светодиодов идёт через ещё один стабилизатор, более того, он питает и сам сдвиговый регистр. Но в итоге стабилизатор в моём зарядном остался только один - сделанный ещё в СССР КРЕН5В, как вы уже догадались, на 5 вольт.

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

// Шаблоны для экрана
char* dozens={"10000001","10111011","01100001","00101001","00011011","00001101","00000101","10101011","00000001","00001001", "10000000","10111010","01100000","00101000","00011010","00001100","00000100","10101010","00000000","00001000"};
char* ones={"10000010","10111110","10001001","10011000","10110100","11010000","11000000","10111010","10000000","10010000"};

Также, порядок подключения регистров в процессе дальнейшей работы поменялся - первой в цепочке будет стоять блок реле, а уже потом экранчик, релюшки же всё таки важнее, правда, на данный момент это не столь существенно, ведь порядок не имеет особого значения - просто в прошивке, в процедуре вывода, нужно поменять пару строчек местами и все дела.

Когда система заработала - к ней вместо третьего сдвигового регистра я подключил готовый блок реле. А чтобы релюхи ещё и щёлкали - мне понадобился двенадцативольтовый блок питания (не от китайского свитча, а стабилизированный, с плавным выбором напряжения). Если хотите использовать нестабилизированный - используйте девятивольтовый, или даже 7,5 - на них как раз без нагрузки вольт 12 будет. Главное - не попутайте постоянку с перемнкой! На следующей фотке видно, как 12 вольт подведены на соплях двумя штекерами с проводами в правом верхнем углу 🙄

Вот уже и экранчик работает! Написал скетч, который на экран поочерёдно выводит числа от нуля до 199, а на светодиоды справа - их двоичное представление. Ну весело же!

Работа со сдвиговыми регистрами, как я уже говорил, осуществляется по трём проводам. Номера их контактов задаются в самом начале моего скетча:

// Контакт, который подключён к ST_CP входу 74HC595
int latchPin = 8, voltageX10,voltageGuard,ons,dz,
// Контакт, который подключён к SH_CP входу 74HC595
clockPin = 12,
// Контакт, который подключён к DS входу 74HC595
dataPin = 11;

При запуске системы режим работы этих контактов, как и остальных, используемых нами, устанавливается как OUTPUT:

void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(relay220Pin, OUTPUT);
pinMode(fanPin, OUTPUT);

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

digitalWrite(latchPin, LOW);



Причём изначально shiftOut() принимает на вход переменную типа byte, а так как нам намного нагляднее записывать в регистры напрямую единицы и нули - в коде используется специальная функция bitseq(), которая преобразует вышеприведённые шаблоны как раз в то, что от нас хочет shiftOut():

byte bitseq (char s){
byte ab=0;
for (byte ba=0; ba<8; ba++){
if (s == "0") {bitWrite(ab,ba,0);} else {bitWrite(ab,ba,1);}
}
return ab;
}

К тому времени мой рабочий стол выглядел примерно так, как на следующей фотке. Не ломайте голову, задаваясь вопросом, что на монторе - это Скорая Помощь. Классный сериал, второй раз уже пересматриваю. 🙄 Кстати, для соединения не силовых цепей в своём устройстве я использовал витую пару, ту самую, которая категории 5е, у меня её просто уйма - старые кабели с крыши я не выбрасываю, а распускаю. Но для таких вещей хороши не любые проводки. Те, что я использовал - внутри не цельные, а многожильные, благодаря чему они очень эластичные и не ломкие, также у них качественная изоляция. А вот обычную витую пару с цельными жилами я бы не использовал - она очень туго гнётся (ну, относительно), и припаивать её к маленьким микросхемам в корпусе SO-16 было бы вообще неразумно. Что, скажете, мол, надо было ДИПовские микрухи использовать? Ха, вы ещё не видели, какой мазохизм начнётся прямо сейчас, так что не будем тянуть кота за рога (ага) - поехали!

На самом деле это не такая уж и плохая идея - разместить маленькие микросхемки внутри индикатора. Ведь места в старом корпусе и так нет, переднюю панель пришлось ставить на небольшие проставки, а если бы я использовал регистры в ДИПовских корпусах - уууууу, я не знаю, как бы всё туда залезло!

Как я уже говорил, в финальном варианте сегменты подключены через резисторы, а не напрямую, но, тем не менее, первый вариант я решил тоже показать: может быть, кому-то так больше понравится. Так как сам этот экранчик с обратной стороны чем-то залит (какая гадость эти ваши заливные экранчики), а поверхность этой заливки ко всему прочему ещё и вогнута внутрь, я вырезал из пластиковой карточки оплаты угадайте какого белорусского монополиста в области электросвязи маленькую плоскую пластинку, которую приклеил прямо к экранчику и уже на неё потом приклеил сами регистры, предварительно пометив на обратной стороне каждого из них первую ножку (потому что "Смотры не перапутай, Кутузау!").

После припаивания всех проводов и, опять же, проверки, показавшей, что всё работает - я залил всё клеем. Потому что одно неверное движение и проводок отломается от контакта, что-нибудь закоротит и будет большая-пребольшая пичалька. А с клеем такого не произойдёт, с клеем всё хорошо. Клей, короче, рулит. До тех пор, пока его не придётся отдирать 😆 👿 Но не будем о грустном, вот, что получилось после этих манипуляций:

Вот я уже даже соединил эти два блока вместе (правда, временно) чтобы ещё раз насладиться мигающими цыферками и щёлкающими релюшками:

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

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

Измерение напряжения с помощью Arduino

Ардуино - вещь хорошая, в ней изначально есть аналоговые входы, на которых можно в реальном времени мониторить напряжение. Загвоздка состоит лишь в том, что диапазон измерения этих входов простирается от нуля лишь до пяти вольт, а у нас напряжения будут почти до 15, так что эту проблему надо как-то решать. И тут нам на помощь приходит простейший делитель напряжения на двух резисторах. Например, за абсолютный максимум мы возьмём 20 вольт (ну, на всякий случай, чтобы ничего, если что, не сгорело), а потолок у нас - 5, то есть четвёртая часть от максимума, значит делить напряжение нам надо именно на 4. Для этого возьмём 2 резистора таких номиналов, чтобы номинал первого составлял 1/4, а номинал второго - 3/4 от суммы их номиналов. Например, 10 и 30 кОм. Или 5 и 15 кОм, или 2,5 и 7,5, ну вы поняли. Меньше брать не стоит, потому что ток там небольшой. Ну и подключаете по схеме: 10 между аналоговым входом и землёй, а 30 между аналоговым входом и выходом зарядки на аккумулятор.

Но не всё так просто - процедура analogRead() выдаст вам значение от 0 до 1024, где ноль это ноль, а 1024 - это 5 вольт для неё или 20 вольт для нас. Поэтому для пересчёта этого значения нам нужно ввести определённый коэффициент, который мы будем задавать как константу в шапке прошивки (float voltageX10Coefficient = 5.11;). Забегая немного вперёд скажу, что в последствии напряжение, которое видит Arduino, при большом токе начинало прыгать с разбросом до полувольта, поэтому пришлось наш импровизированный датчик подключить через диод, после которого я поставил конденсатор 16V 1000 мФ, и туда же я подключил реле на 220 В, но об этом в конце. Почему я говорю об этом сейчас? Потому что диод, как известно, слегка понижает напряжение, поэтому я ввёл и второй коэффициент, компенсирующий наличие этого диода (int voltageX10Shift = 35;), то есть сначала к выходному значению прибавляется второй коэффициент, а потом то, что получилось, делится на первый.

В итоге мониторинг напряжения выдался на славу - сравните показания с тестером (это не аккумулятор подключен к устройству, а тот самый самодельный стабилизированный блок питания):

Передняя панель зарядного устройства

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

Вот уже и светодиоды поставлены на свои места, и экранчик вставлен на новое место, и даже остальным отверстиям нашлось применение: в дырке от регулятора тока будет лампочка, подключённая к первичной обмотке трансформатора - она будет гореть, когда идёт зарядка, то есть когда на трансформатор подаётся 220 вольт. А если зарядка вроде и заряжает, а лампочка не горит - значит проверяйте, не забыли ли вставить вилку в розетку! В остверстии же от переключателя 6-12 вольт вставлена пластмассовая окантовка для светодиода, который через резистор без стабилизатора будет подключен напрямую к аккумулятору и по яркости его свечения будет видно, насколько заряжен аккумулятор. Это полезно, если аккум будет вообще дохлый и даже пяти вольт на нём не будет для питания мозгов - тогда диод будет тускло светиться и не возникнет вопросов, мол, может устройство сломалось. Хотя, конечно, я оправдываюсь: не было бы дырки - я бы и не думал о том, чтобы туда что-нибудь вставить. У мужиков так обычно всегда и бывает, если вы понимаете о чём я

Кстати, вот вы скажете, мол, где ты, Андрюша, видел разряженные до 5ти вольт автомобильные аккумуляторы? Ну, на тот момент я их нигде не видел, а вот после окончания работ над этой зарядкой мне один такой принесли. 3 вольта. И я даже зарядил его, и он даже живой, хоть, как я полагаю, и засульфатирован вусмерть. Был и второй в похожем состоянии, но его уже ничего не спасло 😆

Вот так вот выглядела на тот момент морда с обратной стороны:

А на следующей фотке я потихоньку обдираю клей и заменяю проводки на резисторы. Стабилизатор в левом нижнем углу фотки я, конечно же, тоже ампутировал за ненадобностью. И. кстати, резисторы припаивать гораздо проще, чем проводки - если бы я сейчас делал всё этого заново - делал бы сразу так, с резисторами и этими маленькими микросхемами.

Также на этой фотке в левом верхнем углу вы можете подсмотреть, как я подключил светодиоды. Минус у них общий, идёт по внутреннему радиусу и подключён к общему минусу устройства через резистор в 3.3 кОм - это я такой подобрал, чтобы и ярко было, и не слепили они. Вроде как в самый раз получилось. Почему резистор один? Потому что в любой момент времени, за исключением момента переключения нагрузки между релюхами, на табло будет гореть лишь один светодиод.

Почему за исключением момента переключения? Потому что если одна релюха будет выключаться, а вторая потом включаться - в момент выключения первой и в момент включения второй на их контактах будет появляться искра, от этих искр будет образовываться нагар на контактах, из-за которого они выйдут из строя со временем - он увеличит их сопротивление, они начнут греться, и всё, мементо море! Так что правильно сначала включать вторую релюху, и как только она включится - выключать первую, тогда мы избавляемся от искр и релюхи будут жить долго и счастливо! Кстати, на родном переключателе всё именно так и сделано, так что нет, это не я придумал, апплодисменты и цветы в машину направляются в данном случае конструкторам оригинального устройства, а не вашему покорному слуге. Ну что ж, не всё коту масленица. 🙄

Кстати, задержка переключения между релюхами задаётся вот этим параметром:

// Длительность перехода между релюхами в миллисекундах
byte relayTransition = 80;

Но что будет, если каким-то волшебным образом две или больше релюх окажутся одновременно включёнными на время, большее, чем отведённое на переключение, вследствие какого-то глюка? А будет очень плохо: вы, считайте, закоротите участок вторичной обмотки. Провода начнут плавится, с трансформатора пойдёт дым и вообще случится армагеддон. Тот самый, который Майкл Бэй снимал.

Так вот, дорогие господа, дамы и ван-даммы, специально для этого я придумал систему защиты от подобного армагедца. К плюсу каждого светодиода подключён резистор на 220 Ом. Почему именно 220? Во-первых потому что в тот день Луна была в Сатурне, а во-вторых потому что перед Новым Годом мне довелось распаять пару магнитофонов отечественных, а также не менее отечественное электронное пианино (или фортепиано, я хз, но не рояль короче), так вот оттуда я выпаял целый коробок этих резисторов на 220 Ом, надо ж их куда-то сувать - так вот, отличное применение!

С другой же стороны все эти резисторы соединены и притянуты к земле через 4к7 резистор (это значит 4,7 кОм, пора уже называть вещи своими именами!), которых у меня тоже дохрена и больше. Так вот мы меряем в этой точке G, куда сходятся все эти 9 резисторов, напряжение, то есть подключаем эту точку к очередному аналоговому входу Ардуины, который задаётся следующим параметром:

// Аналоговый вход для мониторинга количества включённых релюх
byte guardInput = 4;

И по этому напряжению мы сразу видим - сколько в данный момент горит там светоиодов, а так, как они подключены напрямую к транзисторам, то это то же самое, что мы видим, сколько в данный момент включено релюх, а это именно то, что нам и надо в данной ситуации! То есть мы задаём порог напряжения, при превышении которого мы во-первых сразу обрубаем 220 вольт с помощью соответствующей релюхи, а во-вторых пытаемся исправить ситуацию с релюхами, и как только она исправлена - включаем опять 220 и продолжаем работать как ни в чём не бывало. Всё просто и надёжно, я проверял!

Этот порог задаётся здесь:

// Максимально допустимое значение guardInput
byte guardTreshold = 160;

А сама процедура вышеописанной проверки выполняется каждый цикл loop`а и выглядит следующим образом:

// Проверка на количество включенных релюх и автоматическое отключение - восстановление - включение
if (voltageGuard > guardTreshold) {
digitalWrite(relay220Pin, LOW);
while (voltageGuard > guardTreshold) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(ones));
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(dozens));
shiftOut(dataPin, clockPin, MSBFIRST, bitseq(relays));
digitalWrite(latchPin, HIGH);
voltageGuard=analogRead(guardInput);
}
digitalWrite(relay220Pin, HIGH);
}

А теперь я всё-таки покажу обещанную 9 абзацев назад фотку, хотя бы просто для приличия:

А снятая крышка показывает нам напряжение. Милота!

Реле подключения к сети переменного тока

Тем не менее нам нужно двигаться дальше. Как видите, зарядное постепенно собирается, провода постепенно удлиняются и на сцену выходят два новых персонажа - та самая релюха на 220 вольт и небольшой двенадцативольтовый кулер - восьмидесятка от компа:

Релюха это обычная, ничем не отличающаяся от других. Тянет 220 вольт при, вроде 10 амперах. Но нам такого не надо, у нас и предохранитель-то на 1 ампер стоит. Но запас в таких вещах - это хорошо, это надёжность. Катушка у этой релюхи работает от 12 вольт, но есть такие же и на 5. Я купил сразу 25 штук таких на Али, по дешёвке. Почему я взял на 12, а не на 5? Вот смотрите, куда бы я её не включал - всё равно бы нужен был транзистор, правильно? Даже если б она на 5 вольт была. Только вот если она на 5 - её надо через стаб подключать, через который и так все мозги запитываются, он бы от этого ещё больше грелся - нахрена это надо? Можно напрямую тыркнуть в 12, да хоть 15 там будет - ей пофигу, она работает. Причём, начиная вольт с восьми. Светодиод я к ней подключил просто для индикации на время тестирования, типо если светодиод загорелся - значит она работает и виртуально на трансформатор пошло 220 вольт. Подключена она напрямую к выходу ардуины, через тот же самый КТ315, точно так же, как и остальные релюхи в том самом блоке. И да, резюк тоже на 1кОм, хотя там, наверное, и 2 прокатит, можете ставить те, которых больше, но учтите, что чем меньше номинал резюка - тем больший ток будет уходить вникуда через транзистор. Для общей энергоэффективности эти +- пару миллиампер пофигу, а вот для слаботочных выходов ардуины и регистров - не совсем, так что вот.

Включение этой релюхи, как вы и так, наверное, поняли, происходит с помощью

digitalWrite(relay220Pin, HIGH);

А отключение с помощью

digitalWrite(relay220Pin, LOW);

Подключение кулера для охлаждения зарядного

Но вот кулер жрёт вроде как 140 миллиампер, судя по наклейке на нём, так что КТ315 тут уже не прокатят, они по спецификации только до сотни, поэтому я взял КТ815А. Они идут до полутора тыщ миллиампер и его хватит с головой. Есть и другие варианты, я просто всегда стараюсь использовать то, чего у меня много, может у вас, например, будет для кулера какой-нибудь другой транзистор, если он потянет до 20 вольт и до 150 миллиампер - ставьте, если n-p-n, то просто по ногам смотрите распиновку, а если p-n-p - то надо немного схему изменить, но в данном случае это всё несущественно. Только вот тут есть ещё один нюанс...

Вы когда-нибудь слышали, как пищит кулер? Нет не от вращения, просто пищит? Я тоже не слышал, но вот тут посчастливилось. А всё потому, что Arduino промежуточные значения выходных напряжений (больше нуля, но меньше пяти) формирует с помощью ШИМ, то есть это быстрые-быстрые колебания напряжения, сам широтно-импульсный модулятор работает на определённой частоте, а транзисторы, как известно, тоже умеют работать на оперелённых частотах, поэтому эти импульсы через транзистор передаются на кулер и он, в силу своей архитектуры, начинает пищать. Не буду вдаваться в подробности, поскольку сам их не знаю, но лечится всё это втыканием кондёра на 100 мФ плюсом на базу и минусов на эмиттер этого транзистора. Напряжения там до 5ти вольт, соответственно кондёр можно хоть на 6.3 вольта ставить. Всё, писк пропадёт и будет вообще лепота!

Номер ШИМ-контакта, по которому происходит управление кулером, задаётся следующим параметром:

// Выход на управление вентилятором
byte fanPin = 6;

Его скорости от нуля (0V) до 255 (5V) с привязкой к уровням мощности задаются следующим массивом:

// Настройки скорости вращения вентилятора
byte fanSpeeds={0,0,80,90,100,110,120,180,255};

А само задание этих скоростей прописано в процедурах повышения и понижения мощности:

analogWrite(fanPin,fanSpeeds);

Вот, кстати, релюха с кулером поближе:

Дальнейшая работа над лицевой панелью

Но идём дальше. Тут я уже примерил на своё место предохранитель в новом корпусе - на старом было типо несколько напряжений, хотя по факту использовалось только одно, и от него был отколот кусок, а этот как новенький, на 220 вольт, из отцовских запасов. Ну и тот самый нижний светодиодик поставил и вклеил на тот же самый клей.

Наконец, пришло время собирать и ставить на место лицевую панель! Как видите, все провода уже припаяны, даже пятивольтовая КРЕНка торчит внизу кадра, в корпус вкручены проставки, чтобы немного отодвинуть панель (я уже говорил об этом), ведь раньше она крепилась вплотную к корпусу. Как видите, провода во многих местах я просунул в кембрики, чтобы нигде ничего не перетёрлось и не коротнуло. 12 вольт на КРЕНку приходят напрямую с диодного моста, проводом классом выше, чем простая витая пара. Минус подключен к общему минусу напрямую, а вот плюс - через диод, а то Вася Пупкин перепутает полярность при подключении аккумулятора и всё, финита ля комедия, перепаивайте половину сгоревших компонентов! А так можно быть спокойным.

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

Монтаж контроллера Atmega328P c обвязкой и другими элементами

К этому времени на половинке одной из тех самых монтажных платок я уже смонтировал львиную долю оставшихся компонентов - сокету для микросхемы, кварц, кондёры, транзистор для кулера и т.д. и т.п.:

Саму плату пришлось с одной стороны обрезать - она была слишком большая и не влазила. Нижнюю часть, а потом и всю полностью я замотал бумажным скотчем, чтобы она в процессе работы ни на что не закоротила.

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

Финальная настройка параметров устройства

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

После включения было обнаружено, что при большом токе, когда ажно амперметр зашкаливает - зарядное устройство видит напряжение на 0.5-0.8 вольта больше, чем реально на аккумуляторе есть в данный момент. Проверка показала, что целых полвольта теряется на проводах, поэтому я их заменил на более качественные, с большим сечением и припаял к клёвой вилке, очень подходящей к общему дизайну устройства. Это решило проблему, но не 100 процентов - при больших токах некоторая разница всё равно осталась. Но я посчитал, что это не бага, а фича, ведь нечего такими большими токами заряжать аккумулятор - пусть это работает как некоторый ограничивающий фактор!

Тут, между прочим, зарядка папиного аккумулятора идёт полным ходом, это видно по амперметру. Правда, лампочка на 220 вольт оказалась достаточно тусклой и на фотографиях почти не видно, что она горит. Но она горит, верьте мне!

Зарядное устройство готово!

Вот вам вид устройства снизу. Изначально я планировал заделать всю эту щель между корпусом и панелью, но потом передумал - лучше пусть вентилируется!

Вид с левого борта. Ну или с правого - это смотря, как смотреть, извините за каламбур.

Ну а это сверху. Тут видно, что я приклеил панель к выступающей части амперметра - получилась большая третья точка опоры, а то панель сидела как-то неуверенно. А так всё зашибись, надёжно и красиво! Вот, кстати, представьте, если бы вместо Кристалла я использовал обычный Момент, и через щель было бы видно всю это светло-жёлтую хрень. Фууууууу! 😳

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

Кстати, после сборки и тестирования устройства мне пришлось его опять разбирать, чтобы смазать этот долбанный кулер, почему только я его сразу не смазал, была же такая мысль???

Вот такой вот у меня получился первый проект на программируемом микроконтроллере. Потратил я на него почти месяц работы по вечерам. делал даже перерыв недельный, потому что надоедало, работа эта такая, нудноватая что-ли. Но я доволен. Доволен полученным опытом, доволен, что я смог довести это дело до конца, доволен, что у меня теперь есть отличное автоматическое зарядное устройство класса "включил и забыл". И я доволен тем, что когда мои друзья или знакомые будут спрашивать, нет ли у меня зарядного для их аккумулятора, я буду протягивать его им и с гордостью говорить, что эту крутую штуку сделал именно я!

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

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

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

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

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

Ультразвуковой датчик

Для измерения расстояния до препятствия были протестированы два устройства:
  • Arduino-совместимый ультразвуковой модуль HC-SR04
  • Автомобильный парктроник HO 3800
Оба устройства работают по схожему принципу. Отличия заключаются в диаграмме направленности датчиков, максимальной дальности определения препятствий и конструктивном исполнении.
Сравнение параметров датчиков:

В ходе испытаний выяснилось, что модули HC-SR04 обладают несколько худшей способностью обнаруживать препятствия и работать в сложных климатических условиях (холод).

Оба датчика, несмотря на их различия, можно использовать в ультразвуковой насадке на трость в качестве средства измерения расстояния до препятствия, поэтому основным параметром при выборе датчика для нас стала цена. Мы остановились на более дешёвом датчике HC-SR04.

Плата управления

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

Элементы питания

Для обеспечения устройства питанием целесообразно использовать литий-ионные (Li-ion) или никель-металл-гидридные (Ni-Mh) аккумуляторные элементы.

При эксплуатации в нормальных климатических условиях имеет смысл применить Li-ion аккумуляторы, имеющие по сравнению с Ni-Mh следующие преимущества:

  • простота реализации схемы зарядки
  • наличие готовых модулей заряда
  • большее выходное напряжение
  • многообразие габаритных размеров и ёмкостей
При низких температурах предпочтительнее использовать Ni-Mh аккумуляторы.

Напряжения на выходе одного Ni-Mh аккумулятора (1,0 -1,4 В) недостаточно для работы устройства. Для получения напряжения 5 В (необходимого для работы как Arduino, так и паркторника) кроме аккумуляторов будем использовать повышающий DC-DC преобразователь.

Для работы выбранных нами DC-DC преобразователей необходимо обеспечить входное напряжение 0,9-6,0 В. Для получения требуемого выходного напряжения можно было бы воспользоваться одним Ni-Mh элементом напряжением 1,2 вольт. Однако с уменьшением входного напряжения уменьшается и нагрузочная способность преобразователя, поэтому для стабильной работы устройства желательно подавать на вход преобразователя не менее 2 В (два Ni-Mh элемента по 1,2 В или один Li-ion элемент напряжением 3,7 В). Отметим, что существуют DC-DC преобразователи, для работы которых недостаточно входного напряжения 1,2 В.

Зарядка аккумуляторов

Для Li-ion аккумуляторов существует множество готовых недорогих модулей с индикацией окончания заряда.

В случае с Ni-Mh аккумуляторами всё сложнее. Готовых встраиваемых решений на рынке в данный момент мы не нашли. Для зарядки Ni-Mh аккумуляторов можно использовать специализированные внешние зарядные устройства или же создать собственную схему зарядки.

Один из способов зарядить Ni-Mh элемент – последовательное соединение c аккумулятором двух линейных стабилизаторов LM317 (или аналогичных): первый – в режиме ограничения тока, второй – в режиме ограничения напряжения.

Входное напряжение такой схемы составляет 7,0-7,5 В. При отсутствии охлаждения стабилизаторов превышать это напряжение не рекомендуется. Напряжение на каждом Ni-Mh аккумуляторе во время зарядки должно быть около 1, 45 В (напряжение полностью заряженного Ni-Mh элемента). Во избежание перегрева и выхода из строя микросхем, ток зарядки аккумуляторов не должен превышать 100 мА и может быть увеличен до 200 мА при использовании соответствующих радиаторов.

Преимущество такой схемы зарядки заключается в отсутствии необходимости контролировать состояние зарядки: при достижении нужного напряжения на элементе ток автоматически упадёт до безопасного минимума.

Сигнализатор

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

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

Корпус

Нам не удалось подобрать удобный корпус для ультразвуковой насадки на трость среди массово выпускаемых корпусов. Для проведения испытаний устройства мы использовали напечатанный на 3D-принтере корпус из ABS-пластика. Для печати корпуса на 3D-принтере нами была разработана следующая 3D-модель:

Результат испытаний опытных образцов

В процессе разработки было собрано более 12 вариантов изделия. Каждое новое изделие устраняло недостатки предыдущих: в процессе разработки мы уменьшили габариты и вес изделия, подобрали ультразвуковой датчик, удовлетворяющий нас как по цене, так и по техническим характеристикам, отказались от использования аудио канала и оптимизировали алгоритм работы устройств. Совместно с незрячими (Бортников П.В., Шалинцев В. А.) были проведены испытания всех собранных изделий. В результате нами был получен конечный образец.

Ниже приведены принципиальная электрическая схема разработанного устройства:

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

Все использованные при сборке компоненты, кроме распечатанного на 3D-принтере корпуса для насадки на трость, были куплены через AliExpress:

  1. Ультразвуковой датчик HC-SR04.
  2. Плата управления Adruino Pro Mini.
  3. Аккумуляторная батарея 3.7 V 300 mAh.
  4. Преобразователь напряжения 0.9V ~ 5V to 5V 600 mA.
  5. Модуль зарядки AC/DC 220V to 5 V 1 A.
  6. Зарядное устройство LA-520W.
  7. Сигнализатор: вибро-моторчик для мобильного телефона 4x10mm DC 3V.
  8. Кнопка PB-22E60.
  9. Корпус Gainta G1906 (для брелока).
  10. Транзистор: bss138/bcr108 или оптрон CPC1230N.
Внешний вид и цены (с учётом доставки из Китая) компонентов, используемых для сборки ультразвуковой насадки на трость, приведены на рисунке:

Из используемых при сборке компонентов наибольший вклад в стоимость устройства вносит корпус, напечатанный на 3D-принтере.

Внешний вид и цены (с учётом доставки из Китая) компонентов, используемых для сборки ультразвукового брелока, приведены на рисунке:

В дальнейшем можно разработать крепление к корпусу Gainta G1906 и использовать устройство с таким корпусом в качестве насадки на трость.

Одним из способов снижения себестоимости устройств является экономия на оплате труда и стоимости доставки компонентов устройств в Россию за счёт развёртывания производства непосредственно в Китае.

Разработанные нами устройства имеет следующие характеристики:

После проведения предварительных испытаний устройств, мы были вынуждены ограничить дальность обнаружения препятствий до 1,5 метров, для того чтобы не было лишних срабатываний при использовании устройств в потоке людей. При непрерывном изменении уровня вибрации сложнее определить приближение препятствия, поэтому по результатам предварительных испытаний мы остановились на трёх уровнях вибрации.
Внешний вид ультразвуковой насадки на трость:

Внешний вид брелока на шею:

3D-модель ультразвуковой насадки на трость и исходный код прошивки для Adruino доступны для загрузки по

Arduino PWM контроллер солнечной зарядки
Как сделать очень маленький, простой и дешевый ШИМ - контроллер солнечной зарядки с Arduino Pro Mini для 12V вне сетки установок. Размер печатной платы совпадает с размером Pro миниплаты, так что они могут быть зажаты вместе. PCB планы для универсального прототипа борту.

Подключение и использование этого Arduino контроллера солнечного заряда очень просто - есть 2 входных провода от панели солнечных батарей (+ и -) и 2 выхода приводит идти к свинцово-кислотной батарее. Основание панели солнечных батарей и батареи соединены вместе. Любой груз должен быть подключен непосредственно на клеммах аккумулятора и контроллера заряда будет автоматически обрабатывать остальное.

Arduino регулярно измеряет напряжение батареи свинца и кислоты в соответствии с определенным значением, переключает на МОП-транзистор для зарядки аккумулятора от солнечной панели и переключатели МОП-транзистор выключается, когда батарея полностью заряжена. Когда нагрузка тянет энергию от батареи, контроллер обнаруживает падение напряжения и сразу же начинает снова зарядить аккумулятор. В течение ночи, когда солнечная панель перестанет производить, контроллер ждет, пока панель снова не начнет выводить.


Положительный провод к панели солнечных батарей необходим защитный диод Шоттки, устанавливаемую непосредственно на кабеле (завернутое в термоусадочной трубки). Это не входит в основную печатную плату, как это делает его легче заменить его и остыть в то же время. Вы можете легко сделать борту немного дольше, чтобы поместиться в другой тип диода.

Схема и функции Описание:

Функция основана на N-канальный МОП - транзистор IRF3205 в высокой стороне цепи. Это требует напряжения затвора выше, чем 12 В, чтобы открыть МОП - транзистор правильно. Для того, чтобы исключить необходимость внешнего драйвера MOSFET, он приводится в движение заряда насоса, созданного с диодами, 2 конденсаторов и двух выходных выводов Arduino ШИМ (3 и 11). Pin A1 измеряет напряжение аккумуляторной батареи и пин - код 9 управляет MOSFET ON / OFF цикла. Arduino Pro Mini интегрированные светодиодные подключен к контакту 13 используется, чтобы показать текущий цикл ШИМ - сигнала.

Регулятор напряжения и все конденсаторы вокруг (C6, C5 и C4) могли бы быть исключены, поскольку есть регулятор включен в Arduino Pro Mini. Тем не менее, потому что я использовал дешевый клон доска, я не хочу, чтобы рассчитывать на его способности поддерживать более высокие напряжения, чем 12В в течение более длительных периодов времени. LP2950 очень дешево и эффективно до 30 вольт, так что стоит иметь его на борту в любом случае.


Список деталей: Регулятор напряжения с низким энергопотреблением LP2950ACZ-5.0 Транзисторы 2N3904 2N3906 х 2 N-канальный МОП-транзистор IRF3205 Резисторы 82K (1%) 20K (1%) 220K x3 (0,4W достаточно) 4K7 (0,4W достаточно) Диоды 1N4148 х 5 P6KE33CA 90SQ035 (или любой подобный диод Шоттки 35V минимальной 9А) Конденсаторы 47N / 50V x2 керамические 220P / 100V керамические 1M / 50V (1000nF) керамические 4M7 / 10V тантал 1M / 35V тантал х 2

Схема и код этого контроллера заряда является Джулиан Илетт, он является вдохновителем этой умной вещью. Все это лишь утонченный документация и подходящая дизайн печатной платы, чтобы идеально соответствовать Arduino Pro Mini доска. Он разделяет видео более эффективного регулятора заряда Arduino MPPT, но его строительство гораздо сложнее, и проект еще не завершен. Если вы можете, улучшить код или конструкцию в любом случае, пожалуйста, поделитесь своими улучшениями в комментариях.



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


Не менее важными элементами будут катушки индуктивности, которые можно сделать своими руками. Эти простые катушки наматываются из медных проводов и называются катушками с воздушным сердечником. Создание такой обмотки для нашей цели является очень простым занятием. Найдите круглый цилиндр диаметром примерно 5 сантиметров, и намотайте провод на него так, чтобы каждый виток не накладывался на другой виток, но в то же время был как можно ближе к другому витку. Круглым цилиндром может выступать, например, трубка из ПВХ. Возможно, вам понадобится использовать клейкую ленту или скотч в 2-3 местах, чтобы сохранить стабильность конструкции.


Помимо Arduino и катушек индуктивности нам понадобятся: один NPN-транзистор типа 2N3055, один диодный мост 1А (диодная сборка, у них четыре вывода), один светодиод, один 100-омный резистор, два конденсатора емкостью 47 нФ, батарейка 9 В для питания Arduino, а также желательно две платы для прототипирования. Схема подключения компонентов для создания устройства беспроводной передачи данных показана на рисунке ниже.



Схему можно протестировать с помощью простого кода для Arduino, приведенного далее.


void setup() { pinMode(13,OUTPUT); } void loop() { digitalWrite(13,HIGH); delay(0.5); digitalWrite(13,LOW); delay(0.5); }

Тем не менее, простое устройство беспроводной передачи энергии можно сделать и без Arduino. В принципе, мы можем использовать только один транзистор 2N2222. Подключите его вывод базы к первому концу катушки, а коллектор к другому концу катушки. Вывод эмиттера подключается к батарейке. В итоге такая простая конструкция может выглядеть следующим образом:




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

Arduino и добавленная к ней схема заряда могут быть использованы для мониторинга и управления зарядкой никель-металл-гидридных аккумуляторов, например, так:

Законченное устройство

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

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

Комплектующие

Список комплектующих слева направо:

  • мощный резистор 10 Ом (минимум 5 ватт);
  • резистор 1 МОм;
  • конденсатор 1 мкФ;
  • MOSFET транзистор IRF510;
  • датчик температуры TMP36;
  • источник питания 5 вольт;

Как заряжать NiMH AA аккумуляторы

Увеличение скорости заряда увеличивает риск повреждения аккумулятора.

Существует много способов зарядки NiMH аккумуляторов. Выбор используемого вами метода главным образом зависит от того, как быстро вы хотите зарядить аккумулятор. Скорость заряда измеряется по отношению к емкости батареи. Если ваша батарея обладает емкостью 2500 мАч, и вы заряжаете ее током 2500 мА, то вы заряжаете ее со скоростью 1C. Если вы заряжаете этот же аккумулятор током 250 мА, то вы заряжаете его со скоростью C/10.

Во время быстрой зарядки аккумулятора (со скоростью выше C/10), вам необходимо тщательно контролировать напряжение на батарее и ее температуру, чтобы не перезарядить ее. Это может серьезно повредить аккумулятор. Тем не менее, когда вы заряжаете аккумулятор медленно (со скоростью ниже C/10), у вас гораздо меньше шансов повредить батарею, если случайно перезарядите ее. Поэтому медленные методы зарядки, как правило, считаются более безопасными и помогут вам увеличить срок службы батареи. Поэтому в нашем самодельном зарядном устройстве мы будем использовать скорость заряда C/10.

Цепь заряда

Для данного зарядного устройства основой является схема для управления источником питания с помощью Arduino. Схема питается от источника напряжения 5 вольт, например, от адаптера переменного тока или компьютерного блока питания. Большинство USB портов не подходит для данного проекта из-за ограничений по току. Источник 5В заряжает батарею через мощный резистор 10 Ом и мощный MOSFET транзистор. MOSFET транзистор устанавливает величину тока, протекающего через батарею. Резистор добавлен как простой способ контроля тока. Контроль величины тока выполняется подключением каждого вывода резистора к аналоговым входным выводам Arduino и измерением напряжения с каждой стороны. MOSFET транзистор управляется выходным ШИМ выводом Arduino. Импульсы сигнала широтно-импульсной модуляции сглаживаются до постоянного напряжения фильтром на резисторе 1 МОм и конденсаторе 1 мкФ. Данная схема позволяет Arduino отслеживать и управлять током, протекающим через батарею.


Датчик температуры

Датчик температуры служит для предотвращения перезаряда батареи и обеспечения безопасности.

В качестве дополнительной меры предосторожности в зарядное устройство добавлен датчик температуры TMP36 для контроля температуры батареи. Данный датчик выдает напряжение, которое линейно зависит от температуры. Поэтому он, в отличие от термисторов, не требует калибровки или балансировки. Датчик устанавливается в просверленном отверстии в корпусе держателя батареи и приклеивается в отверстии так, чтобы он прижимался к батарее, когда та будет установлена в держатель. Выводы датчика подключаются к шине 5В, к корпусу и к аналоговому входному выводу Arduino.

Держатель AA батареи перед и после установки на макетную плату

Код


Код для данного проекта довольно прост. Переменные в начале исходного кода позволяют настроить зарядное устройство путем ввода значений емкости батареи и точного сопротивления мощного резистора. Также добавлены и переменные безопасных порогов. Максимально допустимое напряжение на батарее устанавливается в значение 1,6 вольта. Максимальная температура батареи установлена на 35 градусов по Цельсию. Максимальное время заряда установлено на 13 часов. Если какой-либо из этих порогов безопасности будет превышен, зарядное устройство выключается.

В теле программы вы можете увидеть, что система постоянно измеряет напряжения на выводах мощного резистора. Это используется для расчета значений напряжения на батарее и протекающего через нее тока. Ток сравнивается с целевым значением, которое составляет C/10. Если рассчитанный ток отличается от целевого значения более, чем на 10 мА, система автоматически подстраивает выходное значение, чтобы подкорректировать его.

Arduino использует последовательный интерфейс для отображения всех текущих данных. Если вы хотите проконтролировать работу вашего зарядного устройства, то можете подключить Arduino к USB порту компьютера, но это необязательно, так как Arduino питается от источника напряжения 5В зарядного устройства.

Int batteryCapacity = 2500; // значение емкости батареи в мАч float resistance = 10.0; // измеренное сопротивление мощного резистора int cutoffVoltage = 1600; // максимальное напряжение на батарее (в мВ), которое не должно быть превышено float cutoffTemperatureC = 35; // максимальная температура батареи, которая не должна быть превышена (в градусах C) //float cutoffTemperatureF = 95; // максимальная температура батареи, которая не должна быть превышена (в градусах F) long cutoffTime = 46800000; // максимальное время заряда в 13 часов, которое не должно быть превышено int outputPin = 9; // провод выходного сигнала подключен к цифровому выводу 9 int outputValue = 150; // значение выходного ШИМ сигнала int analogPinOne = 0; // первый датчик напряжения подключен к аналоговому выводу 0 float valueProbeOne = 0; // переменная для хранения значения на analogPinOne float voltageProbeOne = 0; // рассчитанное напряжение на analogPinOne int analogPinTwo = 1; // второй датчик напряжения подключен к аналоговому выводу 1 float valueProbeTwo = 0; // переменная для хранения значения на analogPinTwo float voltageProbeTwo = 0; // рассчитанное напряжение на analogPinTwo int analogPinThree = 2; // третий датчик напряжения подключен к аналоговому выводу 2 float valueProbeThree = 0; // переменная для хранения значения на analogPinThree float tmp36Voltage = 0; // рассчитанное напряжение на analogPinThree float temperatureC = 0; // рассчитанная температура датчика в градусах C //float temperatureF = 0; // рассчитанная температура датчика в градусах F float voltageDifference = 0; // разница между напряжениями на analogPinOne и analogPinTwo float batteryVoltage = 0; // рассчитанное напряжение на батарее float current = 0; // рассчитанный ток, протекающий через нагрузку в (мА) float targetCurrent = batteryCapacity / 10; // целевой выходной ток (в мА) устанавливается в значение // C/10 или 1/10 от емкости батареи float currentError = 0; // разница между целевым и фактическим токами (в мА) void setup() { Serial.begin(9600); // настройка последовательного интерфейса pinMode(outputPin, OUTPUT); // установить вывод, как выход } void loop() { analogWrite(outputPin, outputValue); // записать выходное значение в выходной вывод Serial.print("Output: "); // показать выходные значения для контроля на компьютере Serial.println(outputValue); valueProbeOne = analogRead(analogPinOne); // считать входное значение на первом пробнике voltageProbeOne = (valueProbeOne*5000)/1023; // рассчитать напряжение на первом пробнике в милливольтах Serial.print("Voltage Probe One (mV): "); // показать напряжение на первом пробнике Serial.println(voltageProbeOne); valueProbeTwo = analogRead(analogPinTwo); // считать входное значение на втором пробнике voltageProbeTwo = (valueProbeTwo*5000)/1023; // рассчитать напряжение на втором пробнике в милливольтах Serial.print("Voltage Probe Two (mV): "); // показать напряжение на втором пробнике Serial.println(voltageProbeTwo); batteryVoltage = 5000 - voltageProbeTwo; // рассчитать напряжение на батарее Serial.print("Battery Voltage (mV): "); // показать напряжение на батарее Serial.println(batteryVoltage); current = (voltageProbeTwo - voltageProbeOne) / resistance; // рассчитать ток заряда Serial.print("Target Current (mA): "); // показать целевой ток Serial.println(targetCurrent); Serial.print("Battery Current (mA): "); // показать фактический ток Serial.println(current); currentError = targetCurrent - current; // разница между целевым и измеренным токами Serial.print("Current Error (mA): "); // показать ошибку установки тока Serial.println(currentError); valueProbeThree = analogRead(analogPinThree); // считать входное значение третьего пробника, tmp36Voltage = valueProbeThree * 5.0; // преобразуя его в напряжение tmp36Voltage /= 1024.0; temperatureC = (tmp36Voltage - 0.5) * 100 ; // преобразование, исходя из зависимости в 10 мВ на градус со сдвиком в 500 мВ // ((напряжение - 500 мВ) умножить на 100) Serial.print("Temperature (degrees C) "); // показать температуру в градусах Цельсия Serial.println(temperatureC); /* temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; //преобразовать в градусы Фаренгейта Serial.print("Temperature (degrees F) "); Serial.println(temperatureF); */ Serial.println(); // дополнительные пустые строки, чтобы облегчить чтение данных при отладке Serial.println(); if(abs(currentError) > 10) // если ошибка установки тока достаточно велика, то подстроить выходное напряжение { outputValue = outputValue + currentError / 10; if(outputValue < 1) // выходное значение никогда не может быть ниже 0 { outputValue = 0; } if(outputValue > 254) // выходное значение никогда не может быть выше 255 { outputValue = 255; } analogWrite(outputPin, outputValue); // записать новое выходное значение } if(temperatureC > cutoffTemperatureC) // остановить зарядку, если температура батареи превысила безопасный порог { outputValue = 0; Serial.print("Max Temperature Exceeded"); } /* if(temperatureF > cutoffTemperatureF) // остановить зарядку, если температура батареи превысила безопасный порог { outputValue = 0; } */ if(batteryVoltage > cutoffVoltage) // остановить зарядку, если напряжение на батарее превысило безопасный порог { outputValue = 0; Serial.print("Max Voltage Exceeded"); } if(millis() > cutoffTime) // остановить зарядку, если время заряда превысило порог { outputValue = 0; Serial.print("Max Charge Time Exceeded"); } delay(10000); // задержка в 10 секунд перед следующей итерацией цикла }

Скачиваемую версию исходного кода вы можете найти по ссылке, приведенной ниже.