Автор Тема: Подключаем вентилятор к GPIO с сервисами блекджеком и шл...  (Прочитано 1063 раз)

Оффлайн TRAHOMOTO

  • Новичок
  • *
  • Сообщений: 9
  • Лайков: 6
  • Карма: +1/-0
  • лентяй
    • Просмотр профиля
Перед тем как начну, хотчу поблагодарить одного очень умного администтратора-разработчика который всех нас тут собрал  ;) спасибо за Ваш труд и терпение с которым Вы отвечаете и ведете Ваш Реурс!
----------------------------------------------------------------------
Эта заметка для жирафов или задротов которые хотят разобраться в том как это работает.

Сегодня я хочу поделиться опытом и наработками в вопросе управления охлаждения плат Orange Pi c ОС Armbian, а именно как подключить к OPi вентилятор, чтобы она (OPi) сама им управляла.

Начнем с харды ... в смысле с железа, нам потребуется:

  • Резистор 10кОм
  • Резистор 1кОм
  • Транзистор 2n4401
  • Вентилятор (я использую KD2406PHS2 потому что у меня питание устройсва 24В)
  • Провода, коннекторы, припой ...

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

Это не самое лучшее решение, но пожалуй самое простое и дешевое :)
По сути картинки ... нам нужно подобрать достаточный для нас транзистор. Я использовал тот что был у меня в пенале 2n4401, этот "рычаг" при небольшой стоимости может управлть нагрузкой до 600мА при напряжении 40В ... т.е. для наших целей "выше крыши"
Резистор 10кОм между "базой" и "эмиттером" нужен для того, чтобы при отсутствии внешнего сигнала вентилятор был выключен. Иными словами этот резистор "подтягивает" базу к 0. Т.е. в такой схеме транзистор будет зарыт, ток через него не будет течь и вентилятор не будет крутиться. Чтобы вентилятор начал работать на "базу" транзистора нужно подать логическую "1", но не просто подать, а опять же чтобы не спалить хилый но умный процессор, через резистор в 1кОм.
Еще раз, для понимания процесса, резистор в 10кОм закрывает транзистор, а 1кОм защищает наш процессор от повреждений. На схеме есть еще один элемент - диод (нарисован пунктиром параллельно вентилятору и в обратную сторону) ... это опциональное дополнение, если Вы решите подключить вместо вентилятора какое-то реле или какой-то небольшой моторчик с щетками или еще какую-то нужную индуктивную хрень - это защитит наш транзистор.
Также на фотке можно увидеть транзистор с припаянным подтягивающим SMD резистором, просто я хотел показать как можно организовать эту схему в железе в минимальных размерах ...
 
Надеюсь я не сильно забил мозг, все что не понятно, пожалуйста, прочтите в гугле тама всё понятно рассказывают более умные преподаватели, а мы пока перейдем к софту ...
Чтобы начать пользоваться GPIO OPi нужно сначала заглянуть в /boot/script.bin ... ну не прям в него, а в его аватара script.fex ... как сварить *.fex из *.bin читаем в гугле. В *.fex нужно проверить секцию

[gpio_para]
gpio_used = 1
gpio_num = 19
gpio_pin_1 = port:PA06<1><default><default><0>
gpio_pin_2 = port:PA13<1><default><default><0>
gpio_pin_3 = port:PA14<1><default><default><0>
gpio_pin_4 = port:PA01<1><default><default><0>
gpio_pin_5 = port:PD14<1><default><default><0>
gpio_pin_6 = port:PA00<1><default><default><0>
gpio_pin_7 = port:PA03<1><default><default><0>
gpio_pin_8 = port:PC04<1><default><default><0>
gpio_pin_9 = port:PC07<1><default><default><0>
gpio_pin_10 = port:PA02<1><default><default><0>
gpio_pin_11 = port:PA21<1><default><default><0>
gpio_pin_12 = port:PA07<1><default><default><0>
gpio_pin_13 = port:PA08<1><default><default><0>
gpio_pin_14 = port:PG08<1><default><default><0>
gpio_pin_15 = port:PA09<1><default><default><0>
gpio_pin_16 = port:PA10<1><default><default><1>
gpio_pin_17 = port:PG09<1><default><default><0>
gpio_pin_18 = port:PG06<1><default><default><0>
gpio_pin_19 = port:PG07<1><default><default><0>

Т.е. следует проверить включены ли в вашей OPi GPIO.

и выполнив код смотрим есть ли доступные порты...
ls /sys/class/gpio_sw/

вы должны увидеть что-то типа

root@node0-aat:~# ls /sys/class/gpio_sw/
PA0  PA1  PA10  PA13  PA14  PA2  PA21  PA3  PA6  PA7  PA8  PA9  PC4  PC7  PD14  PG6  PG7  PG8  PG9

Если Вы увидете пустоту, то гуглим как сделать modprobe gpio_sunxi и как добавить модуль в автозагрузку, да и вообще полезно знать что такое модули :)


Я подключил свой вентилятор к PA10 потому что мне так удобнее. Т.е. к транзистору через резистор подключаем вывод PA10, а теперь вернемся к софту...
Чтобы Linuх мог выводить на вывод 1, тем самым управлять вентилятором нам нужен скрипт, например свой я назвал fanctl (fan control) и положил его в /usr/bin/

# Это содержимое файла  /usr/bin/fanctl
#!/bin/sh

readonly FAN_PIN='PA10'
readonly FAN_PATH=/sys/class/gpio_sw/${FAN_PIN}/data

readonly MSG_ON='Fan ON!'
readonly MSG_OFF='Fan OFF!'

on(){
echo 1 > $FAN_PATH
}

off(){
echo 0 > $FAN_PATH
}

old_state=$(cat $FAN_PATH)

case $1 in
  on|off) "$1" ;;
esac

cur_state=$(cat $FAN_PATH)

if [ "$old_state" != "$cur_state" ] && [ -z "$2"  ]; then
if [ "$cur_state" = 1 ]; then
echo $MSG_ON
else
echo $MSG_OFF
fi
fi
Если Вы не понимаете что тут тварится, напишите в коментах, обсудим! ;)

Итак скрипт мы создали ...теперь давайте позволим его выполнять ... для этого выполним в консоли
chmod +x /usr/bin/fanctl
Эта комманда позволит исполнять наш скрипт, как будто это программа

Теперь уже можно пользоваться нашим скриптом просто выполнив комманду
fanctl on 
можно включить вентилятор (подать "1" на вывод PA10) или

fanctl off
выключить вентилятор (подать "0")

Но все это попса ... подать на пин адиницу это может любой, не интересно ... Чтобы управлять охлаждением нам нужно знать какая температура сейчас на процессоре, ну или близко к нему :) Чтобы узнать это, можно выполнить комманду
cat /sys/class/thermal/thermal_zone0/temp
или
cat /sys/class/thermal/thermal_zone1/temp
на самом деле одинхрен оно показывает одно и то же ... пойдет! Можо написать скрипт в папке /usr/bin/, что то типа

# Это содержимое файла  /usr/bin/cputemp
#!/bin/sh

echo $(cat /sys/class/thermal/thermal_zone0/temp)
этот скрипт, выведет на консоль температуру процессора если использовать его
root@node0-aat:~# cputemp
42
НЕ ЗАБУДЬТЕ дать права на выполнение (chmod +x /bla/bla/ololo)!

Ок! Теперь у нас есть "вход" и "выход", т.е. мы можем узнать какая температура и можем управлять нагрузкой - вентилятором или реле, которое управляет системой водяного/креогенного охлаждения  ::) давайте тепрь это автоматизируем ...

Чтобы управлять нагрузкой нам нужно чтобы OPi постоянно мониторила и принимала решение! Сказано сделано! Пишем еще один скрипт в /usr/bin/autofan

# Это содержимое файла  /usr/bin/autofan
#!/bin/sh

readonly TEMP_START=45
readonly TEMP_STOP=35

STATE="idle"

get_temp() {
    echo $(cat /sys/class/thermal/thermal_zone0/temp)
}

on(){
    /usr/bin/fanctl on silent
}

off(){
    /usr/bin/fanctl off silent
}

#===  FUNCTION  ================================================
#          NAME:  cleanup
#   DESCRIPTION: 
#===============================================================
cleanup ()
{
  # wait for active children, remove empty logfile, ..., exit
  rm /var/run/autofan.pid

  exit 0
} # ----------  end of function cleanup  ----------

#===============================================================
#   TRAPS
#===============================================================
trap cleanup 15

#echo "Script '$0' / PID ${$}"
echo $$ > /var/run/autofan.pid
while :; do
    temp=$(get_temp)
    if [ "$temp" -ge $TEMP_START ] && [ "$STATE"=="idle" ]; then
STATE="cooling"
on
    else
if [ "$temp" -le $TEMP_STOP ] && [ "$STATE"=="cooling" ]; then
STATE="idle"
off
fi
fi
    sleep 10
done

#===============================================================
#   STATISTICS / CLEANUP
#===============================================================
cleanup
Я не буду учить вас написанию Shell скриптов, это уж Вы сами в гугле :). Только расскажу взагалi ...
Скрипт в бесконечном цикле производит замер температуры 1 раз в 10 секунд  (см. sleep 10) и если она больше TEMP_START начинает процесс охлаждения (включает нагрузку - вентилятор) до тех пор, пока температура процессора не опустится ниже TEMP_STOP. Когда это произошло, то охлаждение прекращается и вентилятор выклюается. Так же хочу обратить внимание на строчку
echo $$ > /var/run/autofan.pid
она создает текстовый файл в который выводится Process ID нашего autofan, чтобы мы, потом, могли "убить" его правильно с помощью скрипта
 
# Это содержимое файла  /usr/bin/autofanstop
#!/bin/sh

kill -15 $(cat /var/run/autofan.pid)

Итак теперь у нас есть почти все, осталось только заставить наш скрипт запускатья при загрузке системы. Это можно сделать разными способами, но мы пойдем по пути настоящих профи и будем like a boss! :) напишем unit для systemd.

Systemd - это система, которая запускает, мониторит и управляет всеми программами и подсистемами свежих ОС Linux таких как Debian, Ubuntu ... Armbian ... есичо читать тут

Итак Unit получился такой
# Это содержимое файла /etc/systemd/system/coolfan.service
[Unit]
Description=Controls cooling fan on GPIO

[Service]
Type=simple
ExecStart=/usr/bin/autofan
ExecStop=/usr/bin/autofanstop

Restart=always
PIDFile=/var/run/autofan.pid
OOMScoreAdjust=-100
TimeoutSec=20

[Install]
WantedBy=multi-user.target

Ок! Осталось совсем чуть чуть ... теперь у нас есть все чт о нужно. Осталось лишь активировать наш сервис коммандой
systemctl enable coolfan.service
И можно сразу же его запустить
systemctl start coolfan.service
или узнать его состояние
systemctl status coolfan.service

ВСЁ! :) если вы поняли то что я описал, и сделали все правильно то теперь у Вас в системе завеляся демон, который рулит вентилятором (релешкой, моторчиком ...) через GPIO и нахрен не нужен никакой питон, wiringPi и прочая нечесть :)

Скрипты в папках лежат в архиве внизу, Если чего не получилось, you free to ask в комментах, я бываю тут часто, но отвечать не всегда есть время ... :)

_________________________________

И раз уж этот ресурс на домене UA и ваш покорный слуга Хохол то -  СЛАВА УКРАЇНІ! :)
« Последнее редактирование: Февраль 06, 2017, 12:13:13 am от TRAHOMOTO »

Оффлайн 2kx

  • Новичок
  • *
  • Сообщений: 13
  • Лайков: 0
  • Карма: +0/-0
  • OPiPC2, OPiLite
    • Просмотр профиля
а если у меня 5 вольтовый вентилятор?
я его втыкал в 5v выход gpio но он сильно шумный становится.. Втыкал его в 3.3 разьем крутит не слышно при этом хорошо охлаждает. Но хочется всё таки чтобы он не всегда работал. Попробовал подключить его к pgio разъёму и подать на него 1 - не крутится. Чего ему не хватает?

Оффлайн AlDemin

  • Житель
  • ****
  • Сообщений: 412
  • Лайков: 110
  • Карма: +14/-1
  • OPi, OPi+, OPiOne, OPiZero, OPiPC2, BPi, RPiB.
    • Просмотр профиля
Тока ему от GPIO не хватает.
Надо подключить "+" к +3.3 вольта, а "-" на сток полевика, исток на массу, а затвор полевика на gpio. Полевик взять типа 2N7002, почти на любой дохлой материнке имеется.

Оффлайн 2kx

  • Новичок
  • *
  • Сообщений: 13
  • Лайков: 0
  • Карма: +0/-0
  • OPiPC2, OPiLite
    • Просмотр профиля
Тока ему от GPIO не хватает.
Надо подключить "+" к +3.3 вольта, а "-" на сток полевика, исток на массу, а затвор полевика на gpio. Полевик взять типа 2N7002, почти на любой дохлой материнке имеется.
подключил по этой схеме, но вентилятор крутит всё время с самого старта, на затвор не реагирует.  Что я мог сделать не так?

Оффлайн AlDemin

  • Житель
  • ****
  • Сообщений: 412
  • Лайков: 110
  • Карма: +14/-1
  • OPi, OPi+, OPiOne, OPiZero, OPiPC2, BPi, RPiB.
    • Просмотр профиля
Ну тут либо транзистор пробит, либо сток-исток перепутал.

Оффлайн 2kx

  • Новичок
  • *
  • Сообщений: 13
  • Лайков: 0
  • Карма: +0/-0
  • OPiPC2, OPiLite
    • Просмотр профиля
Ну тут либо транзистор пробит, либо сток-исток перепутал.
спасибо, всё работает, я не правильно сток-исток нашел.
всё получилось относительно компактно-аккуратно.