- PVSM.RU - https://www.pvsm.ru -
Если ты, читатель, тоже страдаешь понятием "Не баг, а фича" и желанием покапаться в железках, то этот пост для твоих "кривых ручек", как у меня.
На днях, я искал интересный корпус для Raspberry Pi 4, мне очень уж понравился набор
Mini Tower Kit от https://github.com/geeekpi/minitowercase, но вот незадачка, проект, изначально, предназначен для RPi 5, а у меня RPi 4, но хотелка меня переосилила и я решился купить его за 2300 денег.
Корпус Mini Tower Kit это интересный и прикольный проект, напечатанный на 3Д принтере, состоящий из 3х частей корпуса, кулера (Ice Tower), OLED-экрана и RGB-подсветки, на кулере (не управляемая) и на обратной стороне экрана, выглядит это чудо как уменьшенная копия геймерского ПК. Так же в комплекте блок расширения GPIO контактов.
Все бы хорошо, но вот незадачка, кулер подключается через fan-интерфейс на RPi 5, а на RPi 4 такого нет.
- Чож делать, Чож делать?
- Кустарить!
Мое приключение началось с разбора распиновки, в прочем ничего особенного, вот она:
Ну, в целом, разницы особо никакой, поэтому проблем с OLED и I2C не будет, значит надо разбираться с кулером.
Распиновка кулера представляет из себя JST-PH 2.0 мм (4 pin), у которого:
|
Цвет провода |
Назначение |
Что с ним делать |
|---|---|---|
|
🔴 Красный |
+5V питание |
5V (Pin 2 или Pin 4) |
|
⚫ Чёрный |
GND |
GND (Pin 6 / 9 / 14 и т.д.) |
|
🟡 Жёлтый |
TACH / Sense (датчик оборотов) |
Опционально, можно не подключать |
|
🔵 Синий |
PWM control (управление скоростью) |
GPIO (GPIO 13 / Pin 33) |
Ну, красный и черный - понятно и валенку, а желтый и синий - нужно разбираться.
ЖЁЛТЫЙ (RPM) - тахометр (мы его НЕ используем) - это это выход вентилятора
Что он делает:
вентилятор шлёт импульсы
обычно 2 импульса на один оборот
это open-collector выход (нужна подтяжка к 3.3V)
Используется для:
подсчёта RPM (оборотов)
мониторинга: «крутится / заклинил»
В нашей переделке нам не нужен RPM, потому что мы его регулируем по температуре CPU, которая прекрасно вычисляется самим RPi 4. Таким образом в этом корпусе малинки нет смысла использовать его, потому что придется проводить рассчеты напряжения, ставить сопротивление, потому что GPIO не любит получать чистый 3.3v на вход - ну его нафиг.
А вот СИНИЙ (PWM) - это провод на вход к кулеру, т.е. он управляет самим кулером.
Как это работает:
Вентилятор питается постоянно от 5V
Синий провод принимает логический сигнал
Частота обычно ~25 кГц (PC стандарт) (по крайней мере так пишут про подобные на просторах тырнета)
Но 5V вентиляторы терпят и 100–1000 Гц
Получается такие вертушки работают по принципу:
|
Duty Cycle |
Что происходит с сигналом |
Как крутится вентилятор |
|---|---|---|
|
0% |
всегда LOW |
не крутится |
|
10% |
1 короткий «пшик» |
еле живой |
|
25% |
четверть времени ON |
медленно |
|
50% |
половина ON / половина OFF |
средне |
|
75% |
почти всегда ON |
быстро |
|
100% |
всегда HIGH |
максимум |
Таким образом, мы подаём PWM с GPIO, и вентилятор сам регулирует обороты.
Теперь, когда мы разобрались во всех причинно-следственных связях, переделаем контактики на виртушке, под нашу архитектуру.
Я особо не запаривался, отрезал покороче JST, взял коннекторы типа "мама" с ардуиновских проводов и просто перепаял провода и насадил коннекторы
Синий, в общем-то, я не захотел изолировать или удалять, поэтому просто тоже насадил на него коннектор, а вось когда-нибудь и пригодится :D
Затем приступил к сборке, согласно распиновки из комплекта, но столкнулся с небольшой накладкой, т.к. пины OLED дисплея и кулера пересекались. Эта задачка была решена достаточно тривиально - использованием блока расширения для GPIO и простой сменой ШИМ-порта с GPIO 18 на GPIO 13 - код все поправит
Прекрасно, железо запустилось, кулер крутится, диоды на нем горят, но дисплей не воркает, потому что I2C еще не инициализирована в системе.
Так, с железом разобрались, переходим к программной части.
У меня RPi 4 с Ubuntu Server на борту, а родное ПО предполагает RPi 5 с RPi OS.
Выкачиваем репозиторий, смотрим какие библиотеки использует код. Для работы с OLED и I2C используется rpi_ws281x - не проблема, питон переварит. Для кулера же, все гораздо проще, на уровне драйверов ОС (kernel / firmware).
Ну, с дисплеем все понятно, а по поводу вентилятора придется вернуться к истокам ардуино, в принципе, тоже ничего сложного, в тырнете полно информации. Питон спасет мир, поэтому вот, я реализовал это у себя:
GPIO.setup(FAN_PIN, GPIO.OUT)
pwm = GPIO.PWM(FAN_PIN, 250) # частота
pwm.start(0)
while True:
temp = get_cpu_temp()
if temp < 45:
pwm.ChangeDutyCycle(20)
elif temp < 60:
pwm.ChangeDutyCycle(50)
else:
pwm.ChangeDutyCycle(100)
На этом моменте основной функционал отработан, тесты положительные, все воркает.
Теперь можно экспериментировать.
Оригинальный софт представлял собой один бесконечный цикл на Python, который пытался делать всё сразу. Я пошел по пути Unix-way: одна задача - один процесс.
Вся экосистема проекта была разбита на независимые демоны (Systemd Services), которые общаются друг с другом через файлы состояний и конфигурационный JSON-файл.
Файловая система организована так, чтобы отделить исполняемый код от конфигурации, доступной пользователю.
/
├── etc/
│ └── minitower/
│ └── config.json # Глобальный конфиг (пользовательские настройки)
├── usr/
│ └── local/
│ ├── minitower/
│ │ ├── fan_control.py # Логика охлаждения
│ │ ├── led_service.py # Драйвер подсветки (запущен от root)
│ │ ├── sysinfo.py # Драйвер OLED дисплея
│ │ └── led_control.py # CLI-утилита для пользователя
│ └── bin/
│ ├── led # Симлинк для удобного вызова
│ └── minitower_wrapper # Перехватчик команд reboot/shutdown
└── tmp/
└── led_status # IPC-канал для приоритетных сигналов
Такая структура позволяет обновлять скрипты, не затирая настройки пользователя, и дает возможность управлять подсветкой без прав суперпользователя.
Максимально простой и надежный скрипт. Он читает /sys/class/thermal/thermal_zone0/temp и управляет скважностью ШИМ на GPIO 13.
Тихий режим: До 45°C вентилятор полностью остановлен.
Линейный рост: С 45°C до 65°C обороты плавно растут.
Турбо: Выше 65°C вентилятор включается на 100%.
Это не просто «гирлянда», а конечный автомат (State Machine). Сервис работает с библиотекой rpi_ws281x и имеет систему приоритетов.
Приоритет 1 (Высокий): Системные события.
Скрипт мониторит наличие файла-флага в /tmp/led_status.
Если файл содержит BLINK_RED - пропал интернет, мигаем красным.
Если BLINK_ALARM - обнаружена попытка взлома, агрессивный стробоскоп (в моем случае реализовано при неправильном вводе пароля по SSH.
Если REBOOT - плавное угасание.
Приоритет 2 (Низкий): Пользовательские настройки.
Если системных событий нет, сервис читает /etc/minitower/config.json. Пользователь может выбрать статический цвет, режим «радуги», «матрицы», «дыхания» и т.п.
Хак с правами доступа: Чтобы менять цвет мог обычный пользователь командой
led greenбезsudo, файл конфигурации и папка/etc/minitowerимеют права 666/777. Демон подсветки (работающий от root) просто перечитывает файл при изменении его времени модификации.
Экран 128x64 используется на 100%. Вместо стандартных логотипов, я сделал полноценный дашборд.
Верхняя панель: Hostname и часы.
Метрики: CPU Temp, RAM Usage, Disk Usage. Если значение превышает критический порог (например, RAM > 80%), строка инвертируется (черный текст на белом фоне), привлекая внимание.
Сетевой монитор:
Скрипт пингует 8.8.8.8. Если пинга нет - на экран выводится крупное предупреждение CONNECTION LOST, и отправляется сигнал подсветке стать красной.
Если сеть есть, отображается локальный IP.
Детектор SSH: Через библиотеку psutil сканируются активные TCP-соединения на 22 порту. Если вы подключились к серверу, на дисплее появится надпись ssh connected и IP-адрес вашего клиента.
В отдельном потоке дисплейного сервиса запущен мониторинг логов journalctl.
Если скрипт видит строки Failed password или Invalid user от sshd:
Создается файл-флаг тревоги для подсветки.
OLED-экран начинает быстро мигать белым фоном.
На дисплее крупно выводится надпись INTRUDER ALERT и IP-адрес атакующего.
Это превращает сервер в наглядный индикатор того, что вас пытаются брутфорсить.
Самая интересная техническая задача - сделать красивое выключение. Если просто написать systemd-юнит с Before=shutdown.target [1], система может убить процессы экрана и подсветки раньше, чем они успеют отрисовать анимацию прощания.
Я пошел радикальным путем: Shell Wrappers.
Системные команды /usr/sbin/reboot, shutdown, poweroff и halt подменяются симлинками на мой скрипт-обертку.
Алгоритм работы обертки:
Пользователь вводит sudo reboot.
Запускается мой скрипт.
Он вызывает скрипт дисплея с аргументом reboot.
Рисуется Progress Bar остановки сервисов, подсветка плавно гаснет.
Только после завершения анимации скрипт вызывает системный бинарник перезагрузки.
Чтобы не править JSON вручную, написана утилита led. Она написана на Python, но скомпилирована в исполняемый файл (или вызвана через shebang) и доступна в $PATH.
Примеры команд:
root@AnDyPi:~$ led
Minitower LED Control v2.6
Использование:
led on / off - Включить (белый статический) или выключить
led [название_цвета] - Статичный цвет (red, orange, yellow, green, blue, indigo, violet...)
led mode [название] - Эффект (rainbow, pulse, breath, knight, strobe, sparkle, fire, matrix, party, ycle)
led auto [on/off] - Автоматическая смена режимов (гирлянда)
led brightness [0-255] - Установка яркости
led speed [1-100] - Скорость анимации (чем меньше, тем быстрее)
led set [r] [g] [b] - Установка своего RGB цвета
Весь проект упакован в Git-репозиторий - https://github.com/Reider0/PC_Pi_pack.git [2]
install.sh делает всю грязную работу по установке:
Проверяет root-права.
Ставит зависимости (python3-pip, i2c-tools, rpi.gpio).
Разносит файлы по папкам /usr/local/minitower/ и /etc/minitower/.
Создает Systemd юниты и активирует их.
Создает симлинки для перехвата команд выключения.
Вместо китайской игрушки для Raspberry Pi 5 получился полноценный, информативный домашний кампуктер на Raspberry Pi 4 с Ubuntu Server на борту.
Этот проект - отличный пример того, как с помощью Python и понимания устройства Linux можно значительно прокачать опыт даже на таком простом наборе для для Raspberry Pi, а самое главное его преимущество, что возможности ограничиваются только фантазией и количеством токенов в ChatGPT :D
Автор: Reider0
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/443222
Ссылки в тексте:
[1] shutdown.target: http://shutdown.target
[2] https://github.com/Reider0/PC_Pi_pack.git: https://github.com/Reider0/PC_Pi_pack.git
[3] Источник: https://habr.com/ru/articles/989870/?utm_source=habrahabr&utm_medium=rss&utm_campaign=989870
Нажмите здесь для печати.