Mini Tower Kit для Raspberry Pi 5: Переделываем проект под Raspberry Pi 4 с Ubuntu Server

в 8:16, , рубрики: diy-проекты, linux, python, Raspberry, Raspberry Pi, Raspberry Pi 4, rpi, RPi4, Ubuntu, умный дом

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

1. Обзор и сборка проекта

На днях, я искал интересный корпус для 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 такого нет.

fan интерфейс

fan интерфейс

- Чож делать, Чож делать?
- Кустарить!

Мое приключение началось с разбора распиновки, в прочем ничего особенного, вот она:

Распиновка RPi 5

Распиновка RPi 5
Распиновка RPi 4

Распиновка 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)

На этом моменте основной функционал отработан, тесты положительные, все воркает.

Теперь можно экспериментировать.

2. Архитектура ПО

Оригинальный софт представлял собой один бесконечный цикл на 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-канал для приоритетных сигналов

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

Логика работы сервисов

1. Сервис охлаждения (Fan Control)

Максимально простой и надежный скрипт. Он читает /sys/class/thermal/thermal_zone0/temp и управляет скважностью ШИМ на GPIO 13.

  • Тихий режим: До 45°C вентилятор полностью остановлен.

  • Линейный рост: С 45°C до 65°C обороты плавно растут.

  • Турбо: Выше 65°C вентилятор включается на 100%.

2. Сервис подсветки (Moodlight Service)

Это не просто «гирлянда», а конечный автомат (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) просто перечитывает файл при изменении его времени модификации.

3. Сервис OLED-дисплея (Sysinfo)

Экран 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-адрес вашего клиента.

4. Intruder Alert (Система безопасности)

В отдельном потоке дисплейного сервиса запущен мониторинг логов journalctl.
Если скрипт видит строки Failed password или Invalid user от sshd:

  1. Создается файл-флаг тревоги для подсветки.

  2. OLED-экран начинает быстро мигать белым фоном.

  3. На дисплее крупно выводится надпись INTRUDER ALERT и IP-адрес атакующего.

Это превращает сервер в наглядный индикатор того, что вас пытаются брутфорсить.

INTRUDER ALERT

INTRUDER ALERT

Магия выключения (Shutdown Wrappers)

Самая интересная техническая задача - сделать красивое выключение. Если просто написать systemd-юнит с Before=shutdown.target, система может убить процессы экрана и подсветки раньше, чем они успеют отрисовать анимацию прощания.

Я пошел радикальным путем: Shell Wrappers.
Системные команды /usr/sbin/reboot, shutdown, poweroff и halt подменяются симлинками на мой скрипт-обертку.

Алгоритм работы обертки:

  1. Пользователь вводит sudo reboot.

  2. Запускается мой скрипт.

  3. Он вызывает скрипт дисплея с аргументом reboot.

  4. Рисуется Progress Bar остановки сервисов, подсветка плавно гаснет.

  5. Только после завершения анимации скрипт вызывает системный бинарник перезагрузки.

Перезагрузка

Перезагрузка
Включение

Включение

CLI-интерфейс

Чтобы не править 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

install.sh делает всю грязную работу по установке:

  1. Проверяет root-права.

  2. Ставит зависимости (python3-pip, i2c-tools, rpi.gpio).

  3. Разносит файлы по папкам /usr/local/minitower/ и /etc/minitower/.

  4. Создает Systemd юниты и активирует их.

  5. Создает симлинки для перехвата команд выключения.

Итог

Вместо китайской игрушки для Raspberry Pi 5 получился полноценный, информативный домашний кампуктер на Raspberry Pi 4 с Ubuntu Server на борту.

Этот проект - отличный пример того, как с помощью Python и понимания устройства Linux можно значительно прокачать опыт даже на таком простом наборе для для Raspberry Pi, а самое главное его преимущество, что возможности ограничиваются только фантазией и количеством токенов в ChatGPT :D

Автор: Reider0

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js