Основа для умной комнаты, или как Arduino в общежитии живёт
И вновь привет, Хаброжители! Ежедневно читая Хабр, я не раз наталкивался на статьи об Arduino и DIY проектах на его основе. Стоит заметить, что с электроникой я дел не имел, а весь мой опыт заключался в посещении радиокружка на базе подросткового клуба «Огонёк» (г. Петрозаводск). Однажды я собрался и решил сделать на Arduino браслет с сенсорами (температура, давление, пульс) для смартфона (связь по BT) Но сделав ошибку при заказе, я получил лишь сам Arduino и датчик давления. Чтобы протестировать плату я отправился в ближайший магазин радиодеталей за светодиодами, и там на глаза мне попался магнитный датчик закрытия двери. Он натолкнул меня на мысль, что можно было бы немного усовершенствовать жизнь в комнате (не путать с квартирой). Не тратя время, я оформил на Ali заказ с кучей сенсоров и Arduino Mega.
После заказа джентльменского набора сенсоров (температура, влажность, реле, StarterKit, BT, часы, дальнометр, IR датчик) я решил поискать как другие представляют умный дом. Большинство ограничивалось: управлением люстрами и тёплыми полами, хотя были и реально крутые статьи. Часть функций, обыденных для квартир, в комнате были просто лишними: например, датчик утечки газа или протечки. Я решил сам составить функционал, необходимый в умной комнате:
- Управление светом
- Контроль температуры
- Управление множеством способов
- Управление дверью
- Мониторинг температуры
- Мониторинг погоды
Оказалось, что все необходимые сенсоры уже заказаны и остаётся только ждать. И вот все сенсоры пришли!
Первый шаг
Когда ты уже помигал светодиодами и решил собрать умный дом, логичным шагом было бы помигать светом в комнате, но ранняя жара заставила заняться контролем температуры. Для начала я просто попытался подключить dht11 из StarterKita. Что может быть проще, если в интернете полно инструкций? Как оказалось, для подключения dht11 есть множество библиотек и не все они совместимы с последними версиями IDE, но спустя пару часов я любовался температурой выведенной в консоль, а ещё через пару минут светодиодом, мигающим в зависимости от неё. (Отключить датчик, положить в холодильник, достать из холодильника, подключить...)
Первой же проблемой стала низкая точность выбранного dht11: он врал на 2-3 градуса в обе стороны — пришлось его заменить (после этого я стараюсь заказывать датчики в нескольких вариантах).
Затем я отправился в LeroyMerlin и приобрёл там самый простой вентилятор. После нескольких минут возни с проводами и вилкой вентилятор был собран. Вместе с соседом сняли форточку и установили его (вентилятор, не соседа) на освободившееся место. Мы воткнули вилку в розетку и… Вентилятор начал вращаться. Медленно. Очень медленно.
Стоит ли говорить, что мы неправильно установили вилку, а вентилятор вращался от ветра?
Конечно, доступно ручное отключение тока. Но как же лучше управлять вентилятором через реле? Подключить напрямую к вентилятору? Я решил подключить вентилятор к реле через розетку: это придаёт гибкость системе (можно заменить вентилятор на что-либо другое).
Тестирование вентиляции
И вот код переписан со светодиода на реле. Прошивка загружена, я мониторю температуру в ожидании необходимой для старта — и вот он тот момент! Реле щёлкает, а COM-порт пропадает. Видимо, в момент переключения нагрузка на USB увеличивается и идёт помеха данным. Сначала я думал, что это из-за помех от 220В проводов, но они находятся на достаточном расстоянии от платы. В последствии это доставило мне немало проблем: при попытки залить новый скетч, Arduino уходит в ребут, переключает реле и тем самым выносит COM-порт, а, значит, и процесс обновления. Я так и не смог побороть эту проблему.
Управление с пульта
Конечно, постоянная работа вентилятора вскоре наскучила, а выключать его через выключатель было не круто! Поэтому я достал Starter Kit и пульт ДУ оттуда. Собственно с этого момента и начались проблемы: я понятия не имел, как выглядит приёмник. Но несколько минут гугления помогли мне найти его, а ещё через час я уже весело управлял вентилятором с пульта.
Сначала это был сложный алгоритм с несколькими флагами, но в итоге я пришёл к небольшому
алгоритму с таймером
Если (пришёл сигнал){
время_ручного_управления = 1800;
режим_вентилятора =! режим_вентилятора;
}
Если (время_ручного_управления != 0){
время_ручного_управления--;
}иначе{
Если(температура < 26){
режим_вентилятора = false;
}иначе{
режим_вентилятора = true;
}
}
время_ручного_управления = 1800;
режим_вентилятора =! режим_вентилятора;
}
Если (время_ручного_управления != 0){
время_ручного_управления--;
}иначе{
Если(температура < 26){
режим_вентилятора = false;
}иначе{
режим_вентилятора = true;
}
}
Но и тут без проблем не обошлось: обновляя провода, я подал 5V на DATA и очень быстро лишился приёмника. Это и подтолкнуло меня к следующему шагу…
Управление через BT модуль
Вскоре я подключил BT модуль HC-06, перенаправил вывод туда и добавил считывание команд. Думал, что будет намного сложнее, но спасибо статье с robocraft.
Получилось
Сосед и вентилятор
Я думал, что научив соседа управлять системой со смартфона, я решу проблему «Эй, мне холодно», но… Если отключение питания вентилятора через выключатель я мог стерпеть, но закрытие форточки меня просто выводило из себя. Почему? Вентилятор дул в стекло на расстоянии нескольких сантиметров и жутко гудел. К счастью, у меня завалялись магнитные датчики, которые и побудили меня на создание системы. Замкнутый датчик сигнализирует Arduino о том, что вентилятор нельзя включать. Увы, иногда шли помехи, поэтому пришлось сделать простейшую проверку: если сигнал о закрытии приходит несколько раз подряд — форточка действительно закрыта.
Управление светом
Теперь можно было взяться за управление светом. После вентилятора уже ничего сложного: короб, пара клеммников — и свет уже управляется через Arduino (конечно, с возможностью отключения через старый выключатель). Единственное, что волнует это то, что реле являются не лучшим способом для управления лампочками.
Проблемы со звуком
Ну какое же управление светом без хлопков? Мной был заказан микрофон. Так я думал… Помните про неопытность? На самом деле я заказал детектор звука с ручной настройкой порога. Вроде бы годится для моей цели? Но появилась пара «но»:
- Маленький радиус действия: хлопки обрабатываются только с десятка сантиметров
- Малая длительность подачи сигнала: при большом времени исполнении кода сигнал с датчика просто не успевал зафиксироваться Arduino
Возвращение пульта
Небольшое гугление, поход в магазин — и вместо сгоревшего VS1838B я приобрёл более надёжный TSOP1836. В этот раз установка прошла успешно и всё заработало сразу.
Выход на улицу
С окном разобрался, но что за ним? Вооружившись паяльником, я припаял к пятиметровому VGA кабелю датчик дождя и ещё один dht11. Немного U-образных крепежей, чёрной изоленты, мха и система выходит на боевое дежурство.
А ещё я узнал, что можно выводить русский текст.
Стало
Немного удобства
Кажется, что смартфон всегда под рукой, но пока найдёшь, пока подключишь… Иногда быстрее отключить свет или вентилятор через выключатель, но это лишает возможность управления через Arduino (импульсные реле слишком дороги), поэтому я добавил две обыкновенные кнопки.
Немного безопасности
Куда без пожарной сигнализации в общаге технарей? По неопытности, я приобрёл датчик огня, а не дыма. Определение горящей спички на расстоянии до 30 см — это, конечно, круто, но недостаточно. Поэтому пока обошёлся без этого.
К слову о пожарной сигнализации в общежитии...
- Динамик, из которого иногда раздаётся сирена или хрип мертвеца
- Локальный датчик дыма
- Сетевой датчик дыма (подключён к пульту охраны)
Общий вид
У размещения на корпусе компьютера есть огромный недостаток: возможность вызвать короткое замыкание. Поэтому вскоре плата переедет на личную полку, а вместо картонки будет самодельный корпус из кейса для HDD.
Код скетча
Текущее состояние
#include <IRremote.h>
#include <IRremoteInt.h>
#include <DS1302.h>
#include <DHT.h>
#define DHT_PIN 2 //пин градусника…
#define DHT2_PIN 52 //пин уличного градусника…
#define RAIN_PIN 53 //пин датчика дождя
#define RECV_PIN 3 //пин подключения IR приёмника
#define FAN_PIN 4 //пин подключения реле
#define LAMP_PIN 5 //пин подключения реле
#define SOUND_PIN A0 //пин подключения микрофона
#define WINDOW_PIN A1 //пин окна
#define LAMP_BUT_PIN 50 //пин подключения микрофона
#define FAN_BUT_PIN 51 //пин окна
#define DHTTYPE DHT11
#define TIMER_FAN 0
#define TIMER_WINDOW 1
IRrecv irrecv(RECV_PIN);
decode_results results;
int timers[2];
bool FAN_FLAG = false;
bool LAMP_FLAG = true;
int WINDOW_VAL = 0;
bool WINDOW_OPEN = false;
bool WINDOW_FLAG = false;
bool RAIN_FLAG = false;
char incomingByte;
DHT dht(DHT_PIN, DHTTYPE);
DHT dht2(DHT2_PIN, DHTTYPE);
DS1302 rtc(49, 46, 48);
void setup() {
Serial1.begin(9600);
rtc.halt(false);
rtc.writeProtect(false);
//rtc.setDOW(SUNDAY); // Set Day-of-Week to FRIDAY
//rtc.setTime(0, 37, 40); // Set the time to 0:37:00 (24hr format)
//rtc.setDate(25, 5, 2014); // Set the date to 25 мая
timers[TIMER_FAN] = 0;
timers[TIMER_WINDOW] = 0;
pinMode(RAIN_PIN, INPUT);
pinMode(LAMP_BUT_PIN, INPUT);
pinMode(FAN_BUT_PIN, INPUT);
pinMode(FAN_PIN,OUTPUT);
pinMode(LAMP_PIN,OUTPUT);
digitalWrite(FAN_PIN,LOW);
irrecv.enableIRIn(); // Включаем ресивер
dht.begin();
dht2.begin();
}
int volume;
void loop() {
WINDOW_VAL = analogRead(WINDOW_PIN); //магнитный датчик
if(WINDOW_VAL > 950){
if(WINDOW_FLAG){
timers[TIMER_WINDOW]++;
if(timers[TIMER_WINDOW]>10){
WINDOW_OPEN = false;
}
}else{
WINDOW_FLAG=true;
}
}else{
WINDOW_OPEN = true;
WINDOW_FLAG = false;
timers[TIMER_WINDOW]=0;
}
if(digitalRead(RAIN_PIN)==HIGH){
RAIN_FLAG=true;
}else{
RAIN_FLAG=false;
}
volume = analogRead(SOUND_PIN);
if(volume<40){
LAMP_FLAG = !LAMP_FLAG;
}
if(digitalRead(LAMP_BUT_PIN)==HIGH){
input_signal(1);
}
if(digitalRead(FAN_BUT_PIN)==HIGH){
input_signal(0);
}
if (irrecv.decode(&results))
{
if (results.value == 16750695) //Код кнопки
{
input_signal(0);
}
if (results.value == 16756815) //Код кнопки
{
input_signal(1);
}
irrecv.resume(); // Получаем следующее значение
}
//Serial.println(rtc.getTime().hour);
//Serial.println(rtc.getTime().min);
Serial1.print(rtc.getDOWStr());
Serial1.print(" ");
Serial1.print(rtc.getDateStr());
Serial1.print(" — ");
Serial1.println(rtc.getTimeStr());
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
if(incomingByte == '0') {
Serial1.println(«Ручной режим деактивирован»);
input_signal(0);
}else if(incomingByte == '1') {
Serial1.println(«Ручной режим активирован»);
input_signal(0);
}else if(incomingByte == '2') {
input_signal(1);
}
}
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial1.println(«Ошибка чтения с внутреннего термометра»);
} else {
if(timers[TIMER_FAN]<=0){
if (t<26){
FAN_FLAG = false;
}else if (t>26){
FAN_FLAG = true;
}
}else{
timers[TIMER_FAN]--;
}
Serial1.print(«Влажность: „);
Serial1.print(h);
Serial1.println(“ %\t»);
Serial1.print(«Температура: „);
Serial1.print(t);
Serial1.println(“ *C»);
}
if(timers[TIMER_FAN]>0){
Serial1.print(«Ручному режиму осталось работать: „);
Serial1.print(timers[TIMER_FAN]);
Serial1.println(“ сек.»);
}else{
Serial1.println(«Ручной режим выключен»);
}
if (FAN_FLAG && WINDOW_OPEN){
digitalWrite(FAN_PIN,HIGH);
Serial1.println(«Вентилятор включён»);
}else{
digitalWrite(FAN_PIN,LOW);
Serial1.println(«Вентилятор выключен»);
}
if(WINDOW_OPEN){
Serial1.println(«Окно открыто»);
}else{
Serial1.println(«Окно закрыто»);
}
if(LAMP_FLAG){
digitalWrite(LAMP_PIN,HIGH);
}else{
digitalWrite(LAMP_PIN,LOW);
}
h = dht2.readHumidity();
t = dht2.readTemperature();
Serial1.println(«За окном:»);
if (isnan(t) || isnan(h)) {
Serial1.println(«Ошибка чтения с уличного термометра»);
} else {
Serial1.print(«Влажность: „);
Serial1.print(h);
Serial1.println(“ %\t»);
Serial1.print(«Температура: „);
Serial1.print(t);
Serial1.println(“ *C»);
}
if (RAIN_FLAG) {
Serial1.println(«Дождя нет»);
}else{
Serial1.println(«Дождь»);
}
Serial1.println("*****");
delay(100);
}
void input_signal(int signal){
switch(signal){
case 0:
if(rtc.getTime().hour> 1 && rtc.getTime().hour < 8){
timers[TIMER_FAN] = 1800;
}else{
timers[TIMER_FAN] = 18000;
}
FAN_FLAG = !FAN_FLAG;
Serial1.println(«Вентилятор переключён»);
break;
case 1:
LAMP_FLAG = !LAMP_FLAG;
Serial1.println(«Свет переключён»);
break;
}
}
#include <IRremoteInt.h>
#include <DS1302.h>
#include <DHT.h>
#define DHT_PIN 2 //пин градусника…
#define DHT2_PIN 52 //пин уличного градусника…
#define RAIN_PIN 53 //пин датчика дождя
#define RECV_PIN 3 //пин подключения IR приёмника
#define FAN_PIN 4 //пин подключения реле
#define LAMP_PIN 5 //пин подключения реле
#define SOUND_PIN A0 //пин подключения микрофона
#define WINDOW_PIN A1 //пин окна
#define LAMP_BUT_PIN 50 //пин подключения микрофона
#define FAN_BUT_PIN 51 //пин окна
#define DHTTYPE DHT11
#define TIMER_FAN 0
#define TIMER_WINDOW 1
IRrecv irrecv(RECV_PIN);
decode_results results;
int timers[2];
bool FAN_FLAG = false;
bool LAMP_FLAG = true;
int WINDOW_VAL = 0;
bool WINDOW_OPEN = false;
bool WINDOW_FLAG = false;
bool RAIN_FLAG = false;
char incomingByte;
DHT dht(DHT_PIN, DHTTYPE);
DHT dht2(DHT2_PIN, DHTTYPE);
DS1302 rtc(49, 46, 48);
void setup() {
Serial1.begin(9600);
rtc.halt(false);
rtc.writeProtect(false);
//rtc.setDOW(SUNDAY); // Set Day-of-Week to FRIDAY
//rtc.setTime(0, 37, 40); // Set the time to 0:37:00 (24hr format)
//rtc.setDate(25, 5, 2014); // Set the date to 25 мая
timers[TIMER_FAN] = 0;
timers[TIMER_WINDOW] = 0;
pinMode(RAIN_PIN, INPUT);
pinMode(LAMP_BUT_PIN, INPUT);
pinMode(FAN_BUT_PIN, INPUT);
pinMode(FAN_PIN,OUTPUT);
pinMode(LAMP_PIN,OUTPUT);
digitalWrite(FAN_PIN,LOW);
irrecv.enableIRIn(); // Включаем ресивер
dht.begin();
dht2.begin();
}
int volume;
void loop() {
WINDOW_VAL = analogRead(WINDOW_PIN); //магнитный датчик
if(WINDOW_VAL > 950){
if(WINDOW_FLAG){
timers[TIMER_WINDOW]++;
if(timers[TIMER_WINDOW]>10){
WINDOW_OPEN = false;
}
}else{
WINDOW_FLAG=true;
}
}else{
WINDOW_OPEN = true;
WINDOW_FLAG = false;
timers[TIMER_WINDOW]=0;
}
if(digitalRead(RAIN_PIN)==HIGH){
RAIN_FLAG=true;
}else{
RAIN_FLAG=false;
}
volume = analogRead(SOUND_PIN);
if(volume<40){
LAMP_FLAG = !LAMP_FLAG;
}
if(digitalRead(LAMP_BUT_PIN)==HIGH){
input_signal(1);
}
if(digitalRead(FAN_BUT_PIN)==HIGH){
input_signal(0);
}
if (irrecv.decode(&results))
{
if (results.value == 16750695) //Код кнопки
{
input_signal(0);
}
if (results.value == 16756815) //Код кнопки
{
input_signal(1);
}
irrecv.resume(); // Получаем следующее значение
}
//Serial.println(rtc.getTime().hour);
//Serial.println(rtc.getTime().min);
Serial1.print(rtc.getDOWStr());
Serial1.print(" ");
Serial1.print(rtc.getDateStr());
Serial1.print(" — ");
Serial1.println(rtc.getTimeStr());
if (Serial1.available() > 0) {
incomingByte = Serial1.read();
if(incomingByte == '0') {
Serial1.println(«Ручной режим деактивирован»);
input_signal(0);
}else if(incomingByte == '1') {
Serial1.println(«Ручной режим активирован»);
input_signal(0);
}else if(incomingByte == '2') {
input_signal(1);
}
}
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial1.println(«Ошибка чтения с внутреннего термометра»);
} else {
if(timers[TIMER_FAN]<=0){
if (t<26){
FAN_FLAG = false;
}else if (t>26){
FAN_FLAG = true;
}
}else{
timers[TIMER_FAN]--;
}
Serial1.print(«Влажность: „);
Serial1.print(h);
Serial1.println(“ %\t»);
Serial1.print(«Температура: „);
Serial1.print(t);
Serial1.println(“ *C»);
}
if(timers[TIMER_FAN]>0){
Serial1.print(«Ручному режиму осталось работать: „);
Serial1.print(timers[TIMER_FAN]);
Serial1.println(“ сек.»);
}else{
Serial1.println(«Ручной режим выключен»);
}
if (FAN_FLAG && WINDOW_OPEN){
digitalWrite(FAN_PIN,HIGH);
Serial1.println(«Вентилятор включён»);
}else{
digitalWrite(FAN_PIN,LOW);
Serial1.println(«Вентилятор выключен»);
}
if(WINDOW_OPEN){
Serial1.println(«Окно открыто»);
}else{
Serial1.println(«Окно закрыто»);
}
if(LAMP_FLAG){
digitalWrite(LAMP_PIN,HIGH);
}else{
digitalWrite(LAMP_PIN,LOW);
}
h = dht2.readHumidity();
t = dht2.readTemperature();
Serial1.println(«За окном:»);
if (isnan(t) || isnan(h)) {
Serial1.println(«Ошибка чтения с уличного термометра»);
} else {
Serial1.print(«Влажность: „);
Serial1.print(h);
Serial1.println(“ %\t»);
Serial1.print(«Температура: „);
Serial1.print(t);
Serial1.println(“ *C»);
}
if (RAIN_FLAG) {
Serial1.println(«Дождя нет»);
}else{
Serial1.println(«Дождь»);
}
Serial1.println("*****");
delay(100);
}
void input_signal(int signal){
switch(signal){
case 0:
if(rtc.getTime().hour> 1 && rtc.getTime().hour < 8){
timers[TIMER_FAN] = 1800;
}else{
timers[TIMER_FAN] = 18000;
}
FAN_FLAG = !FAN_FLAG;
Serial1.println(«Вентилятор переключён»);
break;
case 1:
LAMP_FLAG = !LAMP_FLAG;
Serial1.println(«Свет переключён»);
break;
}
}
А что, если в коде сбой
Я использую нормальнозамкнутое реле. То есть по умолчанию всё включено: можно отключить Arduino от сети и использовать простые выключатели.
Планы по развитию
То, что я перечислил, является лишь основой для действительно умной комнаты. Ведь всё её AI — это включение и отключение вентилятора, в зависимости от температоруы. Я планирую следующее, чтобы сделать комнату более удобной и «автономной».
Будильник
После добавления часов в систему следующий на очереди будильник. В качестве сигнала я предполагаю: пьезопищалку, моргание света и включение вентилятора. Ну и конечно, раннее пробуждение, если на улице дождь (-10 к скорости передвижения).
Добавить систему сохранения будильников на SD карточку с помощью такого модуля (на случай сбоев в питании).
Приложение на компьютер и смартфон + виджеты
Какой же умный дом без управления со смартфона или компьютера?
Предполагаю примерно такую схему:
Почему не Wi-Fi? Слишком дорого.
Вывести Arduino собственное питание
Думаю, что комментарии излишни: опасность выжечь USB и постоянные помехи для других устройств. Кроме того, хочу перенести питание с платы на специальный адаптер.
Управление роутером через розетку
Старый добрый Asus RT56U очень любит греться, особенно летом. Поэтому хочу сделать автоматическое отключение на пару часов ночью, чтобы давать ему остыть.
Добавить мониторинг присутствия
Сейчас у меня есть несколько старых добрых пироэлектрических инфракрасных датчиков и пара ультразвуковых датчика расстояния. Этого может хватить для простейшего контроля присутствия.
В комнате проживают два человека. Каждый имеет по четыре состояния:
- За компьютером
- Стоит
- Лежит на кровати
- Отсутствует
Инфракрасные датчики определяют присутствие в комнате, а ультразвуковые наличие в зонах (кровать/стол) и мониторят количество вошедших/вышедших.
Это позволит реализовать простейшие сценарии:
- Я пришёл вечером и сосед не спит: включить свет
- Все вышли: выключить свет
- Все легли и не двигаются: выключить свет
Добавить светочувствительный резистор
Классика жанра: автоматическое включение света, если в комнате кто-то в зонах «За компьютером», а в комнате темно.
Добавить электромеханический замок и доводчик
Не знаю, как вам, а мне всё время лень искать ключи, поэтому я очень хочу установить электромеханический замок вкупе со считывателем проксимити карт или датчиком отпечатков пальцев. Вход в общежитие осуществляется с помощью электронных пропусков — частота мне известна, и я могу легко заказать считыватель для Arduino, но карты очень легко клонировать (у меня у самого есть устройство для этого), поэтому, когда придёт час, скорее всего, остановлюсь на отпечатках пальцев.
Сосед часто выходит на кухню/туалет/ванну и не закрывает дверь. Я сижу напротив входа и мне не нравится, что каждый, кто проходит мимо,
Проапгрейдить форточку
Как я уже писал, если температура выше определённого предела, включается вентилятор. Но что, если в комнате никого нет, а температура уже ниже 20-ти? Хотелось бы добавить в систему открытие/закрытие форточки. Возможно, это будут простые моторчики + леска.
Известно, если охладить лампочку и включить её, с большой долей вероятности она взорвётся. Таким образом, это также побережёт нервы и лампочки.
лампочка, которая не дожила до системы контроля температуры
Заменить DHT11
Как я уже писал, я не разбираюсь в сенсорах и т.п. Поэтому я купил первые попавшиеся датчики температуры: dht11. Сейчас я хочу заменить их на dht22 для комнаты и dht21 для улицы. У dht22 меньшая погрешность, а dht21 имеет поддержку отрицательных температур и защищённый корпус, что актуально для улицы. Уличный dht11 уже иногда начал теряться.
Добавить электрический диммер
Очень хочется плавно регулировать уровень освещения в комнате. Если бы у меня не было умной комнаты, я бы купил и повесил простой диммер, но сейчас хочется диммер, который может существовать в рамках текущей системы. К моему сожалению, я не смог найти диммер для 220В, регулируемый 5В. Всё, что пока смог придумать — это простой диммер + присоединенный к нему моторчик.
Голосовое управление
К текущим способам управления хотелось бы добавить голосовое. Благо, существуют системы наподобие этой. Конечно, голосовая реакция тоже была бы в тему, но это простые динамики.
Ссылки на приобретенные сенсоры
- Инфракрасные датчики
- Ультразвуковые датчики
- dht11
- Датчик дождя и снега
- Датчик огня
- Специальный модуль для питания
- Модуль часов
- BT модуль HC-06
- Модуль реле
- Starter Kit
Послесловие
Думаю, что получится написать новую статью по завершении части планов, а пока я просто мечтаю об электромеханическом замке и готовлюсь к сессии.
Хороших наступающих выходных: проведите их с пользой!