Pull to refresh

Домашний мини-климат-контроль своими руками

DIY
Sandbox
Доброго времени суток, дорогие хабровчане. Хочу поделиться своим небольшим опытом создания домашнего климат контроля с веб информером на основе платы 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 командами, когда в случае пересечении правил включается просто автоматический режим (можно конечно написать и свою систему попеременного включения, но пока этого мне хватает).

Начало реализации




Наша arduino с ethernet shield в сборе.

Запишем команды пульта кондиционера. Для этого я использовал готовую библиотеку для ардуино, подключенный к нему ТСОП ну и сам пульт от кондея. Качаем библиотеку с гитхаба (кстати в последней версии решили проблему с длинной пакета, она увеличена до 100, до этого некоторые команды не влезали, т.к. было ограничение в 50, и часто встречал много гневных отзывов, хотя фиксится за 2 секунды). Плюс этой библиотеки в том, что там есть в демо достаточно удобный логгер пришедших сигналов на наш ТСОП и вывод это в Serial.


Вот сам TSOP и перед ним IR светодиод

Распиновка TSOP22 (у большинства других, на сколько я знаю, всё идентично):



Выводится как raw данные (т.е. не обработанные) так и готовые отпарсенные пакеты по типам (например NEC, RC5 и тд) если они определились, которые можно прямо из библиотеки в коротком виде отправлять. Мой же кондиционер не имеет общепринятого стандарта пакетов (кстати как и телевизор, зато приставка от онлайма по протоколу NEC работает), поэтому будем использовать так называемые raw данные. Сначала подключим наш ТСОП датчик как показано на картинке ниже (на светодиод не обращайте внимания) и зальём нашу прошивку парсера из демо библиотеки на ардуино (IRrecvDump).


Схема подключения TSOP

В первый раз у меня возникла бага: пакеты шли сами по себе. Делал это в комнате и предположил, что может что-то фонить. Вышел с ноутбуком на балкон — фон продолжился. Честно говоря так и не понял в чём была проблема, но я пошёл в ближайший магазин электроники и купил 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) ).


На фото отладка датчика температуры

В редультате сбора у нас будет такая схема:



Некоторые советуют к датчику температуры между выводами Vcc и Data разместить подтягивающий pull-up резистор номиналом 10 кОм, но у меня работает без него, и реального смысла, если честно, я не вижу, измерения нареканий не вызывают.

Основная реализация (код)




Вся система в собранном виде во время тестирования.

Наш DHT22 подключен к 2 аналоговому пину, ИК светодиод к 3 (тот что с pwm).
Код
#include <dht.h>
#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
#define DHT22_PIN 2

dht DHT;

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, 220);

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,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 TurnCondeyAuto[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 irsend;

int dht_status = 0;
char serverName[] = "myserver.ru";
byte server[] = {192, 168, 1, 5 };

EthernetClient client;

void setup()
{
  Serial.begin(9600);
  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);
  WorkWithCondey(DHT.temperature, DHT.humidity);
  Serial.println();
  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);
    client.println(buf);
    client.println("Host: myserver.ru");
    client.println("Connection: close");
    client.println();
    client.stop();
    return true;
  } 
  else {
    // if 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;
  }

  String condey_text_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);
    }
  }
  Serial.print("Condition status: ");
  Serial.println(status);
}


void PrintIPtoSerial() {
  Serial.print("My Local IP address: ");
  Serial.println(Ethernet.localIP());
}


Этот код смотрит на датчик температуры, отправляет данные на мой сервер (так же отправляет последний статус кондиционера, пока его не обрабатываю но может пригодиться), так же вызывается функция WorkWithCondey которая проверяет данные датчика и принимает решение — влючать или нет кондей и какой режим. На серверной стороне у меня простой скрипт на пхп, который принимает гет запрос с данными (только с локальных ипов из списка разрешённых). Эти данные он сохраняет в базу (пока mongodb), и пишет данные в файл, этот файл доступен в интернете, и я написал маленькую програмку на C# которая читает эти данные и выводит в режиме On Screen Display (OSD), т.е. текст поверх всех окон без фона. То что я планирую оптимизировать во всей этой схеме смотрите в разделе ТУДУ. Если будете использовать мой код, то не забудьте заменить myserver.ru на свои данные.

Информация после заливки скетча:
Binary sketch size: 22 034 bytes (of a 32 256 byte maximum) - 68% used

А вот что в выводе ком порта
LIBRARY VERSION: 0.1.05
Try to configure Ethernet using DHCP…
My Local IP address: 192.168.1.107
status, Humidity (%), Temperature ©
OK, 67.5, 26.2
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.4, 26.3
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.4, 26.3
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.4, 26.3
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.4, 26.4
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.3, 26.3
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.3, 26.4
Sending information to weather server
Condition status: 4

status, Humidity (%), Temperature ©
OK, 67.2, 26.4
Sending information to weather server
Condition status: 4

Как видно из лога у нас статус кондиционера «4». Если посмотрите исходный код, то при статусе 4 — у нас срабатывает правило автоматического режима кондиционера, оно и понятно, ведь влажность по логам 67,2% и температура 26,4 градуса. Если поднести датчик к воздушному потоку кондиционера статус меняется на 0, т.е. кондиционер отключен.

Итог



Вся система в сборе на полке, откуда оно управляет кондиционером

У нас есть ардуино, 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 и простенькое реле. Т.к. у этого увлажнителя всего два режима: Вкл и Выкл и то с кнопочки :)

NF24L01:


PIR Sensor:


Благодарности


Хабру — за площадку, где я могу поделиться личным опытом, и пополнить багаж знаний
DIHALT — за интересные статьи, благодаря которым я приобщился к DIY
arduino playground — за библиотеку для работы с DHT датчиками
shirriff — за библиотеку для работы с ИК сигналами
Китаю — за дешёвые компоненты и датчики
Тебе, дорогой читатель, за то что дочитал до конца :)
И конечно моей жене за сына и волшебные пинки под зад для реализации этой идеи.

Файлы


Мой скетч приведённый выше (на всякий случай)
Библиотека для DHT22 (сайт ардуино)
Даташит на DHT22
Даташит на TSOP31256 который я использую
Библиотека для работы с IR (github)

Upd. Добавил фоток, добавил и обновил схемы подключения. Добавил даташит. Обновил код скетча (небольший фикс). Поправил ссылку на библиотеку DHT22&DHT11.
Upd. 2 — Обновил финальную схему подключения ардуино. (Добавлены резисторы, спасибо за подсказку Siorinex)

Надеюсь вам понравилась статья, отзывы и пожелания оставляйте в комментариях. Буду рад конструктивной критике. И соглашусь сразу, статья для новичков от новичка в этом деле. В выходные сниму видео как это всё работает с полным описанием и демонстрацией.
Tags:
Hubs:
Total votes 11: ↑8 and ↓3 +5
Views 57K
Comments Comments 27