Доброго времени суток, дорогиее. Хочу поделиться своим небольшим опытом создания домашнего климат контроля с веб информером на основе платы Arduino с использованием TSOP, IR, DHT22 и напольного кондиционера Electrolux и некоторых других компонентов.
Итак, если вам интересна моя реализация добро пожаловать под хабракат (готовый к заливке скетч там же).
Вступление.
В преддверии лета я задумался о необходимости покупки кондиционера, но так как планировка дома и квартиры не позволяет использовать сплит систему вынужден был взять напольный кондиционер. Да, я понимал что будет геморрой с выводом трубки, поэтому во вступлении я кратко расскажу о тюнинге связки кондиционера и моего окна. Всё достаточно просто, есть 2 трубки, одна затягивает воздух, вторая выводит его наружу (горячий). Холодный воздух выходит из центральной части кондиционера.
Для того, чтобы вывести трубки мне понадобилось:
• Оргстекло размером с 1 створку моего окна (стеклопакеты) плюс отверстия под трубки.
• 4 крепления для установки оргстекла
• трубка для воздухоотвода (взял фольгированную) 2 шт.
• кондиционер
Суть заключается в том, что в оргстекле есть 2 отверстия для наших трубок, которые забирают и выводят воздух. Это сделано для того чтобы не было разреженности воздуха (читал на разных форумах об этом, но сам не замечал этого, но хуже не будет, думаю). Трубку с выводом горячего воздуха я закрепил в нашем оргстекле под небольшим углом вверх и влево, трубку забора воздуха под небольшим углом вниз и вправо, дабы воздушные потоки не пересекались. Крепления для оргстекла сделал снаружи окна, идея для этого возникла глядя на установленную антимоскитную сетку в соседней секции окна (живя на нижних этажах надоедают комарьё, плюс в период цветения тополей у меня сетка стала махровой, но в квартиру пуха не попало).
На картинке выше вроде бы понятно как оно крепиться, где расположены трубки и т.д. Если будут вопросы, задавайте в комментариях. И так, теперь у нас есть кондиционер, который находится около окна, из кондиционера трубки вставлены в оргстекло и выведены на улицу (единственное неудобство — постоянно открыто окно, но оно загорожено оргстеклом, не эстетично, но сверлить несущую стену, дырки в диаметре ~20см 2 штуки на улицу желания нет). Теперь перейдём к логике нашей системы.
Логическая часть
В моём случае используется кондиционер Electrolux EACM-14EZ/N3, у которого есть несколько режимов + IR пульт. Первый и основной — это, конечно, охлаждение (привет, Кэп). Вторая, но не менее полезная — осушение воздуха (не увлажнение, а именно осушение). Второе бывает очень полезно, особенно в жару, ведь жару легче переносить в более сухом воздухе (в прочем как и холод), а совсем недавно в квартире у меня была влажность под 75-80% (по крайней мере мне так сказал подаренный на работе гигрометр). Для увлажнения воздуха я использую дешёвый увлажнитель, который просто нагревает воду до температуры кипения и всё, описание подключения пока нет, так как ещё не доделал его, но обязательно опубликую, дело в том что у него нет никаких интерфейсов типа IR и т.д., поэтому его необходимо разобрать, припаять свой контроллер с релешкой, но вернёмся к основной теме. Для меня и жены тепература в комнате в идеале 22-24 градуса (ну на крайний случай 25 но при достаточно низкой влажности).
Поэтому мы выделим следующую логику:
• Включаем систему охлаждения в случае t > 25 градусов
• Отключаем систему охлаждения при t < 22 градуса
• Включаем режим осушения при h > 60%
• Выключаем режим осушения при h < 40%
• Если 22 < t < 25 и 40 < h < 60 — включаем автоматический режим (кондей попеременно включает осушение и охлаждение сам, либо мы через контроллер управляем сменой, допустим по 5 минут каждого типа)
Итого у нас есть 4 IR команды:
• Включить кондей на максимальное охлаждение (вентилятор на максимум, температура 16 или 18 градусов в зависимости от модели)
• Вкючить кондей на максимальное осушение (вентилятор на максимум)
• Включить кондей в автоматическом режиме
• Выключить кондей
Тут вроде бы понятно. Лично я для себя выбрал вариант именно с 4 командами, когда в случае пересечении правил включается просто автоматический режим (можно конечно написать и свою систему попеременного включения, но пока этого мне хватает).
Начало реализации
Запишем команды пульта кондиционера. Для этого я использовал готовую библиотеку для ардуино, подключенный к нему ТСОП ну и сам пульт от кондея. Качаем библиотеку с гитхаба (кстати в последней версии решили проблему с длинной пакета, она увеличена до 100, до этого некоторые команды не влезали, т.к. было ограничение в 50, и часто встречал много гневных отзывов, хотя фиксится за 2 секунды). Плюс этой библиотеки в том, что там есть в демо достаточно удобный логгер пришедших сигналов на наш ТСОП и вывод это в Serial.
Выводится как raw данные (т.е. не обработанные) так и готовые отпарсенные пакеты по типам (например NEC, RC5 и тд) если они определились, которые можно прямо из библиотеки в коротком виде отправлять. Мой же кондиционер не имеет общепринятого стандарта пакетов (кстати как и телевизор, зато приставка от онлайма по протоколу NEC работает), поэтому будем использовать так называемые raw данные. Сначала подключим наш ТСОП датчик как показано на картинке ниже (на светодиод не обращайте внимания) и зальём нашу прошивку парсера из демо библиотеки на ардуино (IRrecvDump).
В первый раз у меня возникла бага: пакеты шли сами по себе. Делал это в комнате и предположил, что может что-то фонить. Вышел с ноутбуком на балкон — фон продолжился. Честно говоря так и не понял в чём была проблема, но я пошёл в ближайший магазин электроники и купил 2 новых тсопа (первый, глючный, был прислан из китая), подключив которые такого глюка небыло и пакеты отображались только при нажатии кнопки на пульте. Чтобы записать сигнал подключаем ардуино к компьютеру, предварительно всё подключив по картинке выше, открываем монитор порта, указав нужный ком порт. Поднесём пульт и нажмём кнопку с нужной командой. В мониторе отобразится вся необходимая информация. Прошивку я использовал кастомную, чтобы сразу генерировать код, который копипастом удобнее будет вставлять в скетч, ничего сложного, но т.к. форматировал хард, забыл сохранить этот скетч. Демо от библиотеки более чем достаточно и не сильно отличается.
В результате мы получили пакеты для отправки, например включить кондиционер на максимум у меня:
Raw periods:
+2650 -2650 +750 -2000 +750 -700 +700 -700 +700 -700 +750 -700 +700 -700 +750 -650 +750 -700 +750 -700 +700 -700 +700 -700 +750 -700 +700 -700 +750 -650 +750 -700 +700 -700 +750 -700 +700 -700 +750 -700 +700 -700 +750 -650 +800 -700 +700 -750 +700 -650 +750 -700 +700 -700 +750 -650 +800 -650 +750 -700 +700 -2000 +750 -1950 +750 -2000 +750
Готовый код для ардуино:
unsigned int TurnColdOn[68] = {2650,2650,750,2000,750,700,700,700,700,700,750,700,700,700,750,650,750,700,750,700,700,700,700,700,750,700,700,700,750,650,750,700,700,700,750,700,700,700,750,700,700,700,750,650,800,700,700,750,700,650,750,700,700,700,750,650,800,650,750,700,700,2000,750,1950,750,2000,750};
irsend.sendRaw(TurnColdOn,68,38);
По поводу Raw periods — там где "+" там мы горим указанное количество мкс, там где "-" мы не горим указанное количество мкс. Для тех кто будет например использовать AVR контроллеры типа тинек, там есть функция по задержке с указанием микросекунд. Используется приблизительно так:
#include <util/delay.h>
_delay_us(время в мкс);
Таким образом собираем все необходимые команды. Теперь мы подключим наш DHT22 к ардуино, IR светодиод и напишем наш скетч несущий основную логику. В данной версии я, к сожалению, использую полностью проводную систему передачи данных, я заказал NF24L01 датчики, но сколько они ещё будут идти из любимой чайны неизвестно, подробнее смотрите список того что планируется доработать в последней части статьи в разделе TODO. Так же для реализации проекта использовался Ethernet Shield (аналог из поднебесной в районе 9-15 долларов (я взял за 9) ).
Основная реализация (код)
Наш DHT22 подключен к 5 аналоговому пину, ИК светодиод к 3 (тот что с pwm).
#include <dht.h>
#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
dht DHT;
//Настройки для нашего интернета. Тут используется сначала DHCP, если не получилось то тогда ручная установка конфига.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte gateway[] = { 192, 168, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };
IPAddress ip(192, 168, 1, 200);
//Настройки данных по температуре и влажности
float MAX_TEMP = 25.0;
float MIN_TEMP = 22.0;
int MAX_HUMID = 60;
int MIN_HUMID = 40;
int last_condey_status = 0;
//Сигналы пульта для кондея
unsigned int TurnCondeyOff[68] = {2700,2600,750,700,700,700,700,700,750,700,750,700,750,650,750,700,700,700,750,700,750,650,750,700,700,700,750,700,700,700,700,700,750,700,700,700,750,650,750,700,750,700,700,700,750,650,750,700,700,700,750,650,750,700,750,700,750,700,700,2000,750,2000,750,1950,750,2000,750};
unsigned int TurnCondeyMaxOn[68] = {2650,2650,750,2000,750,700,700,700,700,700,750,700,700,700,750,650,750,700,750,700,700,700,700,700,750,700,700,700,750,650,750,700,700,700,750,700,700,700,750,700,700,700,750,650,800,700,700,750,700,650,750,700,700,700,750,650,800,650,750,700,700,2000,750,1950,750,2000,750};
unsigned int TurnCondeyWaterOn[68] = {2650,2650,750,1000,700,700,700,700,700,700,750,700,700,700,750,650,750,700,750,700,700,700,700,700,750,700,700,700,750,650,750,700,700,700,750,700,700,700,750,700,700,700,750,650,800,700,700,750,700,650,750,700,700,700,750,650,800,650,750,700,700,2000,750,1950,750,2000,750};
unsigned int TurnCondeyAuto[68] = {2650,2650,750,1500,750,750,700,700,700,700,750,700,700,700,750,650,750,700,750,700,700,700,700,700,750,700,700,700,750,650,750,700,700,700,750,700,700,700,750,700,700,700,750,650,800,700,700,750,700,650,750,700,700,700,750,650,800,650,750,700,700,2000,750,1950,750,2000,750};
IRsend irsend;
int dht_status = 0;
char serverName[] = "myserver.ru"; // здесь я указал какой сервер мне нужен, так как дома у меня используется свой сервер с несколькими сайтами, на этом домене есть скрипт, который логирует входящий гет запрос с данными с дхт22 и статусом кондея
byte server[] = { 192, 168, 1, 5 };
EthernetClient client;
void setup()
{
Serial.begin(115200);
Serial.print("LIBRARY VERSION: ");
Serial.println(DHT_LIB_VERSION);
delay(1000);
Serial.println("Try to configure Ethernet using DHCP...");
// start the Ethernet connection:
if(Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP. Using manual config.");
Ethernet.begin(mac, ip, gateway);
}
PrintIPtoSerial();
}
void loop()
{
Serial.println("status,tHumidity (%),tTemperature (C)");
// READ DATA
int chk = DHT.read22(DHT22_PIN);
switch (chk)
{
case DHTLIB_OK:
dht_status = 200;
Serial.print("OK,t");
break;
case DHTLIB_ERROR_CHECKSUM:
dht_status = 501;
Serial.print("Checksum error,t");
break;
case DHTLIB_ERROR_TIMEOUT:
dht_status = 504;
Serial.print("Time out error,t");
break;
default:
dht_status = 500;
Serial.print("Unknown error,t");
break;
}
// DISPLAY DATA
Serial.print(DHT.humidity, 1);
Serial.print(",t");
Serial.println(DHT.temperature, 1);
SendDataToServer(dht_status, DHT.temperature, DHT.humidity); //здесь вызывается функция для отправки данных на мой сервер, в неё мы передаём статус дхт22 датчика и данные полученные с него.
WorkWithCondey(DHT.temperature, DHT.humidity);
delay(1000);
}
boolean SendDataToServer(int d_stat, float temp, int humidity) {
if (client.connect(server, 80)) {
char buf[80];
int temp1 = (temp - (int)temp) * 100;
int humidityl = (humidity - (int)humidity) * 100;
Serial.println("Sending information to weather server");
// Make a HTTP request:
sprintf(buf, "GET /meteo.php?S=%d&T=%0d.%d&H=%0d.%d&CS=%d HTTP/1.1", (int)d_stat, (int)temp, abs(temp1), (int)humidity, abs(humidityl), last_condey_status); //meteo.php - это и есть скрипт который принимает данные. обращаю ваше внимание, в ардуино нельзя в sprintf передать сразу флоат, поэтому есть небольшое извращение
client.println(buf);
client.println("Host: myserver.ru");
client.println("Connection: close");
client.println();
client.stop();
return true;
}
else {
// kf you didn't get a connection to the server:
Serial.println("Connection to weather server failed");
client.stop();
return false;
}
}
void WorkWithCondey(float temp, int humidity) {
int status = 0;
if(temp > MAX_TEMP) {
status=1;
}
if(temp < MIN_TEMP) {
status=0;
}
if(humidity > MAX_HUMID) {
status = status+3;
}
if(humidity < MIN_HUMID) {
status = status;
}
//Проверяем, изменился ли статус по сравнению со старым, если нет, то ничего не делаем, если да, то шлём сигнал.
if(status != last_condey_status) {
last_condey_status = status;
if(status == 0) {
irsend.sendRaw(TurnCondeyOff,68,38);
}
if(status == 1) {
irsend.sendRaw(TurnCondeyMaxOn,68,38);
}
if(status == 3) {
irsend.sendRaw(TurnCondeyWaterOn,68,38);
}
if(status == 4) {
irsend.sendRaw(TurnCondeyAuto,68,38);
}
}
}
void PrintIPtoSerial() {
Serial.print("My Local IP address: ");
Serial.println(Ethernet.localIP());
}
Этот код смотрит на датчик температуры, отправляет данные на мой сервер (так же отправляет последний статус кондиционера, пока его не обрабатываю но может пригодиться), так же вызывается функция WorkWithCondey которая проверяет данные датчика и принимает решение — влючать или нет кондей и какой режим. На серверной стороне у меня простой скрипт на пхп, который принимает гет запрос с данными (только с локальных ипов из списка разрешённых). Эти данные он сохраняет в базу (пока mongodb), и пишет данные в файл, этот файл доступен в интернете, и я написал маленькую програмку на C# которая читает эти данные и выводит в режиме On Screen Display (OSD), т.е. текст поверх всех окон без фона. То что я планирую оптимизировать во всей этой схеме смотрите в разделе ТУДУ.
Итог
У нас есть ардуино, ethernet shield, ir led, tsop датчик, кондиционер — и всё это работает автоматически. Пока я его испытывал 2 дня (в выходные) было исправлено несколько багов в скетче, вроде сбоев пока нет. Если нужно будет видео, то постараюсь записать при первой возможности.
TODO!
Итак, список того что планируется реализовать:
1. Поменять файл с данными на Memcache, чтобы не мучить файловую систему. Хранить в мемкэше последние 5 записей на всякий случай
2. Поменять базу данных с MongoDB на Mysql (или что-то другое, просто смысла в монге здесь особого нет, он стоял, а других баз не было, и ставить было лень )
3. Для записи в базу данных использовать очереди (либо Apache MQ либо другие аналоги).
4. Разделить систему на 3 части: ардуино с эзернетом и RL24L01, плата с датчиком температуры (тинька 2313) и RF24L01, плата с ик светодиодом (тинька2313) и RF24L01. Это нужно чтобы уменьшить размеры, чтобы ненужно было подключать всё только к ардуине, а работать по воздуху.
5. Придумать другой воздухообмен, но пока даже мыслей нет как сделать лучше (посоветуйте в комментах, буду очень рад).
6. В связи с рождением ребёнка (ему только месяц исполнился) заказал пир датчики (ик датчик присутствия), не знаю как хорошо он сработает. При ребёнке (ну и вообще при находжении человека в помещении) нужно не включать кондей. Плюс будет отправляться соответствующий статус в скрипт что в помещении люди.
7. Доработать дешёвый увлажнитель, чтобы и его к этой системе подключить. Туда пойдёт плата с NF24L01, тинька 2313 и простенькое реле. Т.к. у этого увлажнителя всего два режима: Вкл и Выкл и то с кнопочки :)
Благодарности
Хабру — за площадку, где я могу поделиться личным опытом, и пополнить багаж знаний
DiHalt — за интересные статьи, благодаря которым я приобщился к DIY
adafruit — за библиотеку для работы с DHT датчиками
shirriff — за библиотеку для работы с ИК сигналами
Китаю — за дешёвые компоненты и датчики
Тебе, дорогой читатель, за то что дочитал до конца :)
И конечно моей жене за сына и волшебные пинки под зад для реализации этой идеи.
Файлы
Мой скетч приведённый выше (на всякий случай)
Библиотека для DHT22 (github)
Библиотека для работы с IR (github)
Надеюсь вам понравилась статья, отзывы и пожелания оставляйте в комментариях. Буду рад конструктивной критике. И соглашусь сразу, статья для новичков от новичка в этом деле. Сильно, пожалуйста, не пинайте, первая статья на харбре.
Автор: ErgoZru