Современный одноплатный компьютер вроде Raspberry Pi, Orange Pi -- устройство довольно прожорливое (что бы там не говорили про энергоэффективность). Мало того -- питание ему требуется весьма и весьма стабильное. Не даром китайцы явно завышают требования к блокам питания -- так, Orange Pi 4 комплектуется БП не менее 3-4А.
Вопрос -- нужно ли им столько оставим за кадром. Практика показывает, что нужно, ибо пользователя хлебом не корми -- дай что-нибудь в USB подключить.
Одноплатники имеют свойство прирастать. Так, в прошлой статье я уже рассказывал о безумии в виде Kubernetes на них.
Всю эту гору нужно как-то питать. Есть несколько путей:
- Закупить проверенных источников и удлинителей 220в типа "Pilot" в нужном количестве.
- Закупить хороший большой БП на 5 вольт ватт на 100 и сделать кучу разветвлений. Они бывают дешевыми (для светодиодных лент) с "грязным" питанием и дорогими и качественными -- типа Meanwell.
- Сделать многоканальное устройство управления питанием с возможностью управления каждым каналом
Первые два пути слишком простые :). Поэтому сразу их выкинем. Остается третий. Для начала подумаем, что мы хотели бы от "идеального управленца электропитанием".
Какую проблему решаем
Решать будем сразу несколько проблем
- Хотим управлять N каналами питания постоянного тока и питать N устройств.
- Не хотим бегать и дергать питание зависшего Orange Pi, тем более если у нас их больше 5 или даже 10. Хотим комфортно дать команду "выключи канал X/включи канал X".
- Хотим, по возможности использовать ATX блоки питания. Серьёзно -- их огромное количество новых, ещё больше на вторичке -- на любой вкус и кошелёк. Более старые хорошо сбалансированы пол линии 5в, более новые -- по 12в. Почти каждый радиовредитель либо их использовал в поделках, либо использует по сей день.
Зумеры могут попробовать замкнуть зеленый и черный провод на коннекторе ATX БП. Случится чудо.
- Хотим, чтобы устройство подключалось к дешёвым одноплатным ПК каким-то распространенным способом -- будь то UART и/или i2c.
- Если мы используем ATX, то неплохо было бы знать о "здоровье" БП. Нет, не то, чтобы прям полный мониторинг -- но у ATX есть контакт "power good", который выставляет уровень логической "1", если все хорошо. Этим можно воспользоваться.
Ну достаточно "хотелок", они наверняка отрастут еще в процессе разработки, а тут важно соблюсти баланс, дабы задача была решаемой.
Инструментарий
Arduino
Да, это Arduino-клон. Самопальный, плата сделана по технологии ЛУТ (лазерно-утюжная технология).
Во-первых его не жалко, во-вторых он работает на ATMega8, а в дальнейшем эту микросхему можно внедрить прямо в плату без посредников.
У ATMega8 есть и внутренний кварц, на целых 8 Мгц, что позволит ещё больше упростить схему.
Мосфеты
Управлять питанием будет мощный полевой транзистор.
В нашем случае это IRL520NPBF, характеристики которого более чем подходят для наших целей.
Транзистор управляет землей. То есть, с него можно снимать либо 0 вольт, ибо на обоих "ножках" будет одинаковое напряжение разность потенциалов будет 0, либо нужное напряжение, если одна из ног выдает 0 вольт.
Россыпь резисторов и светодиодов
Ну, собственно, тут добавить нечего. Найдутся в любой банке с радиодеталями.
Понадобится для обвязки мосфета, индикации питания, короче для всяких вспомогательных штук.
Сдвиговые регистры
Ой, да. В первой версии они использовались, ибо был риск, что на Arduino не хватит ножек.
С помощью этой микросхемы можно размножить количество выходов Arduino. Прекрасная статья на эту тему есть в старом блоге Ильи Данилова.
Первый прототип
Наша задача -- научиться управлять ATX блоком питания. То есть, включать его, выключать и отслеживать состояние канала "Power Good".
Обычные Arduino работают с уровнями сигнала 5в, если не указано иное, АТХ БП имеет такие же уровни управляющих сигналов.
Короче, не буду грузить долго. Нам нужно выделить ножку Arduino, которая бы выставляла 0 на канале PS_ON в ATX, и вторую ножку, которая бы могла считывать состояние сигнала Power Good.
Вот тут исчерпывающее описание, как и что мы делаем, правда использована плата ARCAdaptor, но на ней та же ATMega8.
Дальше -- больше. Нам потребуется изобразить из себя устройство либо подключаемое по UART, либо по I2C (а лучше и так и так), чтобы принимать команды снаружи и включать и отключать каналы.
На БП ATX есть так называемое "дежурное питание 5в", от него мы запитаем как наш Arduino, так и головной одноплатник, к которому будет подключена "ардуинка". На него мы будем заходить и отдавать команды.
Да,да очередной одноплатник для руления другими одноплатниками. На самом деле Arduino можно приколхозить к ПК через UART или USB-i2c адаптер за копейки.
Схемы и диаграммы
Вот, что получилось после некоторых раздумий
Тут, внезапно, отросли еще и PWM каналы. Они есть у ATMega8/Arduino, так почему бы не заставить еще и их работать. Пусть крутят вентиляторами, например.
Вот простой транзисторный ключ, который будет управляться ножкой Arduino/ATMega:
На выходе получаем либо разность потенциалов в 5в, либо в 0в, то есть включаем и выключаем устройство.
Вот тут -- узел для PWM:
Первый вариант платы
Плата была literally выпилена на фрезерном станке, и, надо сказать -- вполне рабочий вариант.
Дальнейшее развитие
Идея продолжала развиваться.
Появилась следующая версия платы, в которой были выкинуты сдвиговые регистры, да и отдельный Arduino был заменен на микросхему ATMega8.
Ножек вполне хватило на 12 каналов, управление как через I2C, так и через UART. Причем через последний реализация была в виде старых добрых AT команд.
Убедившись в работоспособности я заказал партию в Китае. Сейчас вот лежат, как молчаливое напоминание.
Заказ на черном текстолите -- это хоть и стильно, но абсолютно непрактично. А именно -- не видно косяков изготовления.
Но и это ещё не конец.
Внезапно выяснилось, что современные ATX блоки "оптимизированы-сбалансированы" для 12в. Поэтому было принято решение половину выходов отдать под линии 12в.
То есть, плата имела 6 выходов для управление 5в питанием и 6 под 12в.
Если 5в нужно больше, чем 6 -- преполагалось использовать крошечный DC-DC преобразователь. Зато блок мог вполне работать с современными БП, да и питать можно было уже не одноплатники, а ещё и оборудование, которое "просит" 12в.
Плата была переведена на SMD компоненты, что удешевило её сборку (в плане цены на компоненты, конечно же).
IRL520 были заменены на IRLML6344TRPBF, причем они же стали использоваться и в PWM узле для универсальности.
Получилось довольно внятная конструкция, вполне управляемая и повторяемая. Документация заботливо сохранена :)
SDP -- "Software Defined Power". Думал у себя на домене сделать страничку про них (это к вопросу о надписи на плате).
Младшие братья
ATX это прекрасно, но в какой-то момент удалось приобрести как 100ваттный 5в источник от Meanwell, так и парочку просто мощных источников 5в, достаточных для питания, скажем, 4х плат.
Захотелось менее сложных конструкций.
Вариант на ATTiny44/88
Эта плата у меня работает до сих пор и обслуживает прокси-ферму о 9ти модемах.
Зачем мне прокси-ферма -- это отдельная история, скажу только, что она круче и технологичнее тех, что можно найти на Авито.
Питание 5 в подается на плату и на управляющий узел. Плата и узел коммутируют питание на остальные 9 узлов.
Подключение только через i2c. Сама ATTiny44/88 работает от 3.3в, что позволяет коммутировать ее с одноплатным ПК без использования преобразователя уровней. Используется внутренний кварц, а это освобождает нам целых две ножки для полезной нагрузки.
В принципе, можно было сделать и PWM-enabled версию, но руки не дошли, да и вроде и не надо.
В качестве мосфетов использовались IRLML6344TRPBF для поверхностного монтажа.
Вариант на ATTiny85
Фото ниже -- из предыдущей статьи.
Если читали пассаж про Kubernetes, то фотку узнаете сразу.
А вот её портрет в несобранном виде.
Ножек у ATTiny85 катастрофически мало, так что пришлось отключать Reset. Тут нужно было не облажаться в прошивке (благо, она была уже отлажена), иначе пришлось бы где-то искать AVR Fuse Doctor и восстанавливать ATTiny.
Полевики те же, что и в предыдущем варианте.
Плата работает через UART на 9600 бод, и тут очень важно не облажаться с настройками внутреннего кварца, ибо скорость UART зависит от частоты.
И конечно же, я облажался. Второй раз я уже прошить не смог (функциональность reset переопределена), так что пользовался UART'ом на 2400. Ну хоть завелась.
Да, джампер стоит на коннекторе UART, замыкает резистор или размыкает. Некоторые устройства (например прошитые роутеры на OpenWRT отказываются без него работать).
Эта плата работала в том самом Kubernetes кластере из прошлой заметки, причем годами и успешно. А до этого -- в ферме о 4х одноплатниках вообще в другом городе и управлялась полностью удаленно.
Тупиковые ветки
Я довольно сильно увлекся этим процессом. Хотелось собрать 2U стоечный сервер, а плату управления втыкать в слот (точнее вешать на держалку для платы над слотом) -- слоты все равно пустуют в большинстве случаев.
Было две платы -- одна коммутирует питание исключительно 12в, а на вторую запаиваются DC-DC преобразователи в количестве, если надо получить 5в на каком-то из каналов.
Сбоку есть место для крепления держалки PCI-платы. А 12в подается через коннектор видеокарты.
Была идея сделать хостинг на одноплатных ПК (ну серьезно, за небольшую сумму по факту получаете bare metal, пусть на ARM, но зато весь ваш). У меня даже домен до сих пор висит -- rent-a-pi.ru
Идею пришлось притормозить из-за непродуманности, хотя кое-что из нее я взял на вооружение для производства кластера в дальнейшем.
Однако, один экземпляр даже сохранился
Этот экземпляр использовался в кластере из одноплатников из 12 узлов. В до-кубернетесную эпоху.
Я поставил преобразователь питания с 5в на 3.3 для питания ATMega8, а саму плату запитал от 5в. Так что без лишних приседаний оно подключалось к I2C головного одноплатника и тихо разадавало 5в от мощного источника.
Как делались платы
Изготовление было заказано в Китае на одном из известных сайтов по производству.
Отличные ребята, даже ни с кем не пришлось общаться. Загрузил gerber файл, выбрал параметры, оплатил -- сиди и жди.
Трассировка платы была заказана здесь и отдана на откуп частному специалисту.
Надо сказать, что всё было сделано на уровне, косяки решались быстро, перезаказывать не пришлось.
Увы, исходники в Sprint Layout, так что придется хранить антикварную копию этого "программного обеспечения". Успешно запускается в Wine, если что.
Часть плат собирал я сам, часть отдал на сборку, трезво рассудив, что вечер можно потратить ещё на что-то.
Вообще, мой первый опыт общения с отечественными производителями плат был так себе:
- 80 USD по курсу для подготовки плат из формата какого-то CAD в гербер и настройки производства
- Еще около 20 USD за партию плат, отдельно доставка и прочее.
У китайцев -- типа 30 за всё, причем часть плат сделают бонусом бесплатно, купоны-шмупоны, прочие завлекухи.
Для разового заказа -- условия отличные. Выбор очевиден. Возможно, они не пройдут сертификацию, какие-нибудь тесты на вибростенде -- но волнует ли это обычного радиогубителя ?
Как писались прошивки
В Arduino IDE. Его многие недооценивают, однако, обмазав его нужными библиотеками -- получается вполне годный к работе инструмент, если речь идет о работе с микроконтроллерами.
Вот пара полезных библиотек:
- MiniCore -- ориентированная для работы с bare metal микросхемами, поддерживает популярные AVR-микроконтроллеры.
- ATTinyCore -- аналогичная библиотека, но заточена под серию ATTiny
Помимо, как и в любой другой деятельности, вы должны (реально должны) понимать, что происходит внутри микросхемы, и ни в коем случае не отдаваться на милость "готовых решений".
Например, для реализации AT-команд пришлось отказаться от стандартной ардуинной библиотеки для работы со строками и "как встарь" использовать эти ваши char*, и прочее.
А вот для реализации PWM пришлось подбирать частоты и перенастраивать оный. Иначе он работал на частотах, которые были слышны человеческому уху... И вентиляторы начинали "петь". Забавно, но крайне неприятно при работе в реальной жизни.
Совсем честно -- пришлось перелопатить кучу материала и найти нужную комбинацию настроек где-то в глубинах форума радиовредителей, и да, оно финально сработало.
Я уже писал, что платы работали либо по UART, либо по I2C (либо поддерживали оба способа).
В этой секции, исключительно для иллюстрации приведу список реализованных команд.
I2C
Система команд достаточно проста. Само устройство является I2C Slave с адресом 0x29. Команды трехбайтовые.
{00 01 00} -- Включить ATX
{00 00 00} -- Выключить ATX
{00 0xFF 00} -- Получить статус ATX. После посылки этой команды можно считать 3 байта по шине I2C. Первый байт ответа - 00, второй - статус линии PowerOK (должен быть 01 при включенном ATX), третий - 01, если ATX включен, 00 если выключен. То есть если ATX включен, и работает в штатном режиме - должно вернуться {00 01 01}. Если ATX выключен -- {00 00 00}. Если ATX включен, но нет сигнала PowerOK, есть неполадка в БП.
{01 N M} -- Включить (N=1) или выключить (N=0) канал M (M=0..11).
{01 0xFF M} -- Получить статус канала. После посылки этой команды можно считать 3 байта по шине I2C. Первый байт ответа - 01, второй - номер канала (0..11), третий - статус канала (1 - включен, 0 - выключен).
{02 N M} -- Установить напряжение регулируемого канала N (0..2) в значение M (0..255), где 0 - выключено, а 255 соотвествует 12 вольтам.
{02 0xFF N} -- Получить значение регулируемого канала. После посылки этой команды можно считать 3 байта по шине I2C. Первый байт ответа - 02, второй - номер канала (0..2), третий - значение.
{03 0|1 N} -- Сохранить (0) или восстановить (1) состояние регулируемого канала в/из EEPROM (N=0..2).
{04 0|1 0xFF} -- Сохранить(0)/восстановить(1) состояние всех 12 каналов питания в/из EEPROM
UART
Управление через UART фактически дублирует I2C-команды, хотя имеется несколько расширенных команд.
Команды текстовые, имеют AT-префикс. Скорость UART -- 9600.
Каждая команда либо возвращает "OK", либо "ERROR". Так же возможен дополнительный вывод, например при опросе состояния.
Некоторые команды возвращают ошибку, если ATX выключен.
AT -- привлечение внимания. Возвращает OK всегда.
ATI -- опрос состояния.
ATZ -- сброс в исходное. Внимание! ATX будет выключен, значения всех каналов выставлены в OFF/0.
AT+RESET -- "аппаратный" сброс МК. Сопровождается выдачей информации о версии платы и микропрограммы.
AT+ATX,ON|OFF -- включить/выключить ATX
AT+C,ON|OFF,N -- включить/выключить канал, где N -- номер канала. Вернёт ошибку, если не включен ATX.
AT+С,W|R -- сохранить/считать состояния каналов в EEPROM. Вернёт ошибку, если ATX не включен.
AT+P,S,N,M -- выставить уровень на канале N в значение M (0..255). Если ATX выключен, задан неверный номер канала, уровень превышает 255 -- вернётся ошибка.
AT+P,W|R,N -- сохранить/считать значение регулируемого канала N в EEPROM. Вернёт ошибку, если не включен ATX.
Как писались утилиты для работы с платой
На Python. И не потому, что этот всратый кусок дерьма, так распиаренный зумерам прям прекрасен. Нет, вовсе нет.
Готовые библиотеки для работы с Serial Port, внятные, старые, написанные нормальными людьми
- Готовые библиотеки для работы с I2C, относительно живые. Правда, всё равно пришлось писать свой кусок, что бесило.
Из плюсов -- оно заработало даже на MIPS роутере с установленным OpenWRT. Причем успешно, хоть и не быстро.
Был велик соблазн переписать оное на Go или Rust в образовательных целях. Но сили покинули меня, поэтому оставим пока так. Все-таки battle tested на разных окружениях
Lessons learned
Было ли это всё зря ? Не думаю.
Во-первых, одна из разработанных плат работает до сих пор уже несколько лет и приносит неиллюзорный профит.
Во-вторых что касается ATX-плат -- я до сих пор вынашиваю идею перевести всю "слаботочку" типа свитчей, роутеров, одноплатников (оставшихся) на централизованное питание.
Плюсы -- управляемость.
Минусы -- централизация. В случае любого emergency я просто подмахну "вылетевший" БП, а в случае кончины централизованного блока я вообще останусь без инфраструктуры. Тут еще 10 раз подумаешь, что лучше.
Имеет ли смысл использовать моднейшие ESP8266/ESP32/Raspberry Pi Pico ? Есть ощущение, что нет. Есть ощущение, что эти микроконтроллеры будут исполнять ещё что-то кроме вашего кода. Про надёжность уже и речи наверное нет, время такое.
Спасибо, что дочитали до этого места. Надеюсь, было интересно.
Следующие статьи будут менее замороченным, а для кого-то более интересными. Надеюсь на это :)
Вопросы можно задать в комментариях, ну или поделиться собственным мнением там же.