устройства умный дом
Как использовать обычные клавишные выключатели с произвольным дизайном как проходные и с параллельным управлением из микроконтроллера, да еще и с обратной связью и так чтобы работало одновременно и из контроллера, и с выключателя? Это вообще законно? 🙂
Как? Обо всем по порядку!
Общий принцип следующий:
Для коммутации нагрузки (лампы) будет использоваться обычное импульсное реле (еще его иногда называют бистабильное импульсное реле).
Для создания импульсов на наше импульсное реле будут использоваться механические кнопочные (пружинные) выключатели и коммутируемое реле на 220V с 3-5 вольтовой логикой управления.
Кнопочных выключателей может быть произвольное количество, все они подключаются параллельно и монтируются куда необходимо. Для примера мы воспользуемся одним выключателем.
К микроконтроллеру (в нашем случае Raspberry pi) подключается одно коммутируемое реле на 220V c 3-5 вольтовой логикой управления.
Параллельно к нагрузке (лампе) подключается опторазвязка или произвольный датчик контроля наличия 220V, который сообщает текущее состояние на линии в наш контроллер.
Теперь раскроем каждый пункт чуть подробнее.
Импульсное реле
Импульсное реле коммутирует реальную нагрузку, то есть нашу лампу (люстру и тд). Как работает импульсное реле? Это, как правило, электромеханическое реле, которое может иметь два состояния (отсюда название «бистабильное»). Состояние реле изменяется только при приходящем импульсе. Пришел импульс — реле замкнулось и напряжение пошло, пришел еще импульс — реле разомкнулось и электрическая цепь разорвана. И так далее, по кругу, импульс за импульсом. Существуют различные импульсные реле, отличающиеся количеством фаз и вольтажом входного импульса. Обычно входные импульсы — это 12 или 24 вольт кратковременного постоянного тока или 220 вольт переменного. Данные входные импульсы приходят по сигнальным линиям от кнопочных выключателей или программного реле — генератора импульсов контроллера.
В нашем примере я буду использовать простейшее однофазное импульсное реле Finder 20-ой серии, если конкретно — Finder 20.21.8. для установки на DIN рейку. Данное реле управляется импульсами от сети 220v.
Плюсы: не нужно строить отдельную сигнальную линию другого вольтажа и согласовывать входящие уровни во всех управляющих элементах.
Минусы: сигнальный провод — это провод на 220 вольт. Cтоимость такого будет несколько выше, чем провода, подходящего для 24V. К тому же, нужно будет всегда помнить о технике безопасности — вы будете работать с 220 вольт!
Какой импульсник взять — не принципиально. Главное — правильно подбирайте номиналы для вашей реальной нагрузки.
Клавишный выключатель
Подойдет любой. Выбирайте на ваш вкус, можно хоть сенсорный. Главное, чтобы выключатель автоматически возвращался в исходное состояние (например, внутренней пружиной), тем самым кратковременно замыкал цепь в момент нажатия и размыкал, когда вы его отпустите. В этом вся прелесть: вы не зависите от производителя и кнопка на стене у вас будет красивой.
Реле
Для программной генерации импульса можно использовать как электромагнитное, так и твердотельное реле на 220V c сигналом управления 3-5V от нашего Raspberry pi.
Ампераж такого реле может быть существенно ниже, чем на ипульсном, так как нагрузки на таком реле не предвидится, оно просто будет создавать кратковременные импульсы в сети.
В данном примере я буду использовать электромагнитное реле на 16 ампер. Взял первое, какое лежало под рукой 🙂
Более подробно о таких реле и способах их подключения можно почитать тут.
Внимание! На схеме реле имеются участки и контакты, при соприкосновении с которыми произойдет поражение электрическим током! Для штатной работы используйте диэлектрический корпус.
Опторазвязка
Как говорилось выше, можно воспользоваться готовым датчиком определения наличия 220V. Но мне было проще и дешевле собрать такой самому (да и интереснее). Суммарная стоимость компонентов не дороже 100 рублей.
В нашем случае у нас будет простейшая оптопара TLP621(GB), один диод 1N4007 и 2 резистора номиналами 130Ком и 4,7Ком. Вот и вся схема.
Принцип схемы таков, что когда напряжение 220V в сети есть — диод внутри оптопары загорается, транзистор открывается и ток от Raspberry pi, поданный на контакт питания, протекает на сигнальный контакт. При этом у нас присутствует гальваническая развязка между сетью 220v и 5-и вольтовым Raspberry pi. На малине нет встроенного АЦП, но это не критично, данной схемы вполне хватит, чтобы программно ловить текущее состояние по входящему сигналу на любом контроллере.
Внимание! На схеме имеются участки и контакты, при соприкосновении с которыми произойдет поражение электрическим током! Для штатной работы используйте диэлектрический корпус.
Общая схема подключения всего нашего хозяйства
импульсное реле + электромагнитное реле + выключатель + raspberry:
Еще раз напомню, что данная схема — лишь лабораторный вариант! Для конечного решения используйте диэлектрические корпуса!
Так же будьте аккуратны при определении фазы. Важно, чтобы все реле коммутировали именно фазу, а не ноль!
Завершающий этап — скрипты контроля и управления
Сначала напишем питоновский скрипт для управления электромагнитным реле. Мы должны будем генерировать импульсы электромагнитным реле для нашего импульсного реле.
Для этого достаточно просто ненадолго подавать на сигнальный провод 26 GPIO pin логическую единицу.
1
|
root@raspberrypi:~# vim /home/pi/pulse_to_relay.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
import ConfigParser
config = ConfigParser.RawConfigParser()
config.read(«/home/pi/global_config.conf»)
pin_number = config.getint(«relay_pins», «pulse1»)
#print «use pin:»+str(pin_number) #можно раскомментить.
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(pin_number, GPIO.OUT)
GPIO.output(pin_number, GPIO.HIGH)
time.sleep(0.9)
GPIO.output(pin_number, GPIO.LOW)
|
В сценарии я пользуюсь конфигом пинов, чего и вам крайне советую.
Содержание конфига /home/pi/global_config.conf:
1
2
3
4
5
|
[relay_pins]
pulse1 = 26
[optron_pins]
optron1 = 17
|
Секций и строк в нем может быть гораздо больше в зависимости от линий нагрузок и прочих ваших проектов. Данный файл удобен тем, что в нем можно хранить соответствия номеров пинов и переменных для ваших программ. Небольшие идентичные программки могут быть раскиданы по всей системе или различным проектам; единственное, что в них иногда приходится править, это на какие пины их завязать. Для этого удобнее пользоваться единым файлом конфигурации, отвечающим за этот момент.
Не забываем сделать сценарий исполняемым, и можем попробовать погенерировать импульсы:
1
|
root@raspberrypi:~# chmod +x /home/pi/pulse_to_relay.py
|
1
2
|
root@raspberrypi:~# /home/pi/pulse_to_relay.py
root@raspberrypi:~# /home/pi/pulse_to_relay.py
|
Ваше электромагнитное реле должно будет загораться примерно на секунду после каждого исполнения скрипта.
После каждого включения на импульсник будет приходить импульс и реле будет менять состояние. Лампа должна загораться и гаснуть после каждого переключения. Тот же самый эффект должен происходить и при механическом нажатии на выключатель. Не важно откуда вы будете генерировать импульс — при каждом следующем импульсе импульсное реле будет щелкать.
Чтож, половина дела сделана. Осталось получить обратную связь. Мы всегда должны знать программным способом, включена сейчас лампа или нет. Не важно, включили ли вы свой raspberry pi только что, перезагрузились или он работает уже несколько месяцев — мы должны получить от него актуальное состояние о лампе с нашей опторазвязки.
С точки зрения программы, мы будем получать на 17 GPIO pin входящую последовательность нулей и единиц, если свет включен и ничего не будем получать, если свет выключен.
Запустим несколько классов: один для постоянного контроля входящей последовательности, второй для информативности и записи в файловую систему текущего состояния света.
Что-то очень похожее на proc, если вы понимаете, о чем я 🙂
Есть единица в директории, отвечающей за нашу опторазвязку, значит свет горит.
Нет единички в директории — на опторазвязке тишина, света не должно быть.
Все это дело удобно для множества программ, которым потребуется узнавать, как дела у нашей опторазвязки. Не будем дергать ее из разных мест множественными одновременными запусками.
Создадим сразу все необходимые директории:
1
2
|
root@raspberrypi:~# mkdir /home/pi/optrons
root@raspberrypi:~# mkdir /home/pi/optrons/optron1
|
Считывание и определение сигнала из опторазвязки:
1
|
root@raspberrypi:~# vim /home/pi/optron_read.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO, time, os
import threading
from datetime import datetime
import subprocess
import ConfigParser
#читаем необходимый входящий пин из конфига пинов
config = ConfigParser.RawConfigParser()
config.read(«/home/pi/global_config.conf»)
pin = config.getint(«optron_pins», «optron1»)
#id_f — айдишник запуска программы.
#0 — только стартанули,
#1 — свет сейчас горит,
#2 — стартанули с выключенным светом.
#3 — свет погашен не в первый раз.
global id_f
id_f=0
#айдишник работы входящей последовательности.
#1 — свет горит. 0-выключен
global id_do
id_do=0
#file — сотояние света для остальных скриптов и сценариев — это файл в ФС.
#в директории присутствует 1 — свет горит,
#еденички нет в директории — не горит.
file=‘/home/pi/optrons/optron1/1’
#Класс для постоянного считывания входящей последовательности сигналов.
#Если сигналы валят — свет включен, если ожидание прерывания — выключен.
class check_optron(threading.Thread):
def run ( self ):
def RCtime (RCpin):
global t_run
global id_f
global id_do
GPIO.setmode(GPIO.BCM)
GPIO.setup(RCpin, GPIO.IN)
GPIO.wait_for_edge(RCpin,GPIO.BOTH) #валят нули и еденицы если свет горит
signal = GPIO.input(RCpin)
#print signal #можно раскомментить и посмотреть сырой сигнал
t_run = datetime.now() #время изменения последнего состояния в во входящих сигналах.
id_f=1
id_do=1
while True:
RCtime(pin)
time.sleep(0.1)
check_optron().start()
#класс для корректного вывода на экран инфы о состоянии света.
#Куча айдишников — для того чтобы не флудить при включенном и выключенном свете инфой,
#а выводить только изменения и первичную инфу.
#Запись состояния света без насилования ФС. Зафись только при изменении состояния или первом запуске программы;
class state_inf(threading.Thread):
def run ( self ):
global t_run
global id_f
global id_do
id_print=0
while id_f <= 0:
t_run = datetime.now() #если стартанули и свет выключен, нужно указать какое то время, подходящее для выключенного состояния
time.sleep(1)
id_f=2
while True:
t_now = datetime.now()
td = t_now—t_run
#если время последнего элемента последовательности меньше 0,4 сек — считаем, свет горит.
#если последовательность не приходит на вход больше 0,4 сек — считаем что свет выключен.
if td.total_seconds() <= 0.4:
if id_print==0:
print «Свет сейчас горит»
if os.path.exists(file):
next=1
else:
#создаем файл состояния в файловой системе — на случайобесточивания и перезагрузок
subprocess.call(«touch %s» %file, shell=True)
id_print=1
else:
next=1
time.sleep(0.2)
else:
if id_f == 2:
id_f=3
print «Свет погашен. Програма запущена только что.»
if os.path.exists(file):
subprocess.call(«rm -f %s» %file, shell=True) #удаляем файл состояния
else:
next=1
elif id_do==1:
print «Свет погашен.»
if os.path.exists(file):
subprocess.call(«rm -f %s» %file, shell=True) #удаляем файл состояния
else:
next=1
time.sleep(1)
id_do=0
id_print=0
id_f=3
time.sleep(1)
else:
next=1
time.sleep(0.2)
state_inf().start()
|
Разрешаем исполнение.
1
|
root@raspberrypi:~# chmod +x /home/pi/optron_read.py
|
Последний штрих после всех проверок: добавим программку для обратной связи в автозагрузку, чтобы не запускать его каждый раз руками.
1
|
root@raspberrypi:~# vim /etc/rc.local
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will «exit 0» on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname —I) || true
if [ «$_IP» ]; then
printf «My IP address is %sn» «$_IP»
fi
#запуск сценария
/home/pi/optron_read.py &
exit 0
|
ГОТОВО. Можно перезагружаться. После перезагрузки убедитесь, что в файловой системе присутствует ваша единичка, если свет горит или она удалена, если свет выключен.
Успехов в проектах, подписывайтесь на блог и да прибудет с вами терпение!
умный дом скачать