Skip to content

Instantly share code, notes, and snippets.

@b4tman b4tman/fan_ctrl.py
Last active Apr 19, 2019

Embed
What would you like to do?
Включение и регулировка скорости вращения вентилятора в зависимости от температуры для Raspberry Pi с помощью программной реализации ШИМ
#!/usr/bin/env python
# coding: utf8
# скрипт мониторит температуру, и с помощью ШИМ управляет
# GPIO пином (0-3В), который должен быть подключен на базу транзистора,
# который является ключем в цепи питания вентилятора (5В).
# пример подключения вентилятора через ключ:
# https://easyeda.com/b4tman.p2p/rpi-fan-01
# параметры:
T_MIN=50000 # минимальная температура включения (в градусах С * 1000)
T_FULL=60000 # температура для включения на полную скорость
S_MIN=15 # минимальная скорость, при включении вентилятора (процент)
S_MAX=100 # максимальная скорость вентилятора
GPIO_pin=4 # номер управляющей GPIO ноги
DELAY=5 # интервал между проверками (секунд)
# ---
import time
import logging
from gpiozero import PWMOutputDevice
from gpiozero.pins.rpigpio import RPiGPIOPin
import gpiozero.devices
# генератор, бесконечно получает температуру
def get_temp():
with open('/sys/class/thermal/thermal_zone0/temp', mode='r') as f:
while(True):
f.seek(0,0)
txt = f.read()
yield int(txt.strip())
# аналог Arduino-функции map
def val_map(src_x, src_a, src_b, dst_a, dst_b):
if dst_a == dst_b:
return dst_a
src_plus = 1 if src_b >= src_a else 0
dst_plus = 1 if dst_b >= dst_a else 0
src_len = (src_b - src_a) if src_plus else (src_a - src_b)
dst_len = (dst_b - dst_a) if dst_plus else (dst_a - dst_b)
val = (float(src_x) - (src_a if src_plus else src_b))/(float(src_len) if src_len > 0 else 1)
return int((dst_a if dst_plus else dst_b) + ((1 if dst_plus else -1)* val * dst_len))
# аналог Arduino-функции constrain
def val_constrain(x, start, end):
return min(max(x, start), end)
# настройка ШИМ
gpiozero.devices.pin_factory = RPiGPIOPin
fan = PWMOutputDevice(GPIO_pin)
logging.basicConfig(format = '[%(asctime)s] %(message)s', datefmt='%H:%M:%S', level = logging.DEBUG)
t = 0
try:
for t in get_temp():
if t < T_MIN:
fan.off()
time.sleep(DELAY)
continue
t = val_constrain(t, T_MIN, T_FULL)
speed = val_map(t, T_MIN, T_FULL, S_MIN*10, S_MAX*10)
logging.debug('temp: %.3f °С, speed: %d %%', float(t)/1000, int(speed/10))
fan.value = float(speed)/1000.
time.sleep(DELAY)
except KeyboardInterrupt:
pass
finally:
fan.close()
#!/bin/sh
docker run -d \
--device /dev/gpiomem:/dev/gpiomem \
-v /sys/class/thermal/thermal_zone0/temp:/sys/class/thermal/thermal_zone0/temp:ro \
--restart=unless-stopped \
--name=rpi-fan \
b4tman/rpi-fan
FROM arm32v6/python:alpine3.7
WORKDIR /usr/src
ENV TZ=Europe/Moscow
RUN set -ex \
&& apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
alpine-conf \
tzdata \
&& /sbin/setup-timezone -z $TZ \
&& pip install --upgrade --no-cache-dir pip \
&& pip install --no-cache-dir \
RPi.GPIO \
gpiozero \
&& apk del .build-deps
COPY fan_ctrl.py /usr/src
CMD ["python", "/usr/src/fan_ctrl.py"]
@b4tman

This comment has been minimized.

Copy link
Owner Author

b4tman commented Mar 23, 2017

@blackangel666

This comment has been minimized.

Copy link

blackangel666 commented Mar 4, 2018

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

@b4tman

This comment has been minimized.

Copy link
Owner Author

b4tman commented Mar 21, 2018

@blackangel666 Привет

  1. Можно взять уже готовый образ:
    docker pull b4tman/rpi-fan
    Или собрать самостоятельно:
    docker build -t b4tman/rpi-fan -f rpi-fan.Dockerfile .

  2. Установить и запустить можно с помощью install.sh

  • Но можно и без докера запускать.
  1. Нужно просто установить python и зависимости:
    pip install RPi.GPIO gpiozero

  2. А потом запускать например через rc.local:
    python /path/to/script/fan_ctrl.py
    где /path/to/script/ - папка со скриптом

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.