Showing posts with label DHT-22. Show all posts
Showing posts with label DHT-22. Show all posts

Monday, April 28, 2014

Домашний климат под контролем 2 (Arduino + CO2)

Just another meteostation, co2meter

Получив в руки игрушку под названием Arduino первое что приходит в голову - поморгать светодиодами, второе - собрать метеостанцию.
Следующим после уровня влажности  и температуры меня интересовал уровень загрязнения воздуха. А самое главное - уровень CO2. Этот показатель основа для определения качества воздуха. Если этот показатель в норме, то и с остальными газами скорее всего нет проблем. Это показатель проветриваемости помещения. Основной источник CO2 в помещении это мы сами. Минимальный уровень CO2 это обычно свежий уличный воздух - 300-400 ppm. Уровень приемлемый в жилом помещении 500-800 ppm.  Высокий уровень CO2 вызывает головные боли, тошноту, слабость, в общем симптомы отравления вплоть до несовместимости с жизнью.
Сенсоров CO2 дешевых не встречал. Китайцы не захламили ebay вариантами "все по 10 долларов", так что искать нужно у приличных производителей. При выборе смотреть нужно на уровень определения газа, для наших бытовых случаев достаточно будет от 0-400 ppm до 2000-10000 ppm. Ниже 400 у нас не будет показаний, а выше 2000 это уже очень серьезный повод покинуть помещение. Из всего что просмотрел мне приглянулся K30 от co2meter.com. Есть скетчи для arduino, есть различные варианты подключения (аналог, UART, I2C), есть система автокалибровки и все это за 65 баксов без учета доставки. Правда в РФ по сложившейся традиции не доставляют, так что ищем посредников.

По моему опыту от девайса требуется:

  • возможность посмотреть данные мониторинга на самом девайсе (глупо идти за смартфоном чтобы узнать влажность в комнате когда датчик на расстоянии вытянцтой руки). Экран в таких устройствах очень желателен.
  • возможность смотреть данные (графики) онлайн. Скидываем куда нибудь вроде narodmon.ru .
  • возможность изменять настройки устройства через веб интерфейс (к сожалению на маломощных UNO и Ethernet с 32kb FLASH и 2 SVRAM веб интерфейс это из мира фантастики).
Приведенная здесь простенькая инструкция по сборке DIY устройства мониторинга качества воздуха в помещении может вам помочь в оздоровлении окружающей вас среды.

Элементы:

Arduino (Uno + Ethernet shield, Ethernet, Ethernet with PoE)
DHT22 (dht11, AM2302)
K30
LCD 1602 (LCM1602 IIC V2)

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

co2 k30 pinout

LCD для экономии задействованных контактов был выбран с нашлепкой в виде PCF8574T, а сенсор AM2302 уже шел в DHT22 с резистором. Рекомендую почитать таки datasheet от K30.

Скетч для ардуино:



/*

Library LCD.
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
1602 with PCF8574T  LCM1602 IIC V1


K_Series.h -Library for interfacing with a K-series sensor
Created by Jason Berger
for CO2METER.com
OCT-12-2012
http://www.co2meters.com/Documentation/AppNotes/AN126-K3x-sensor-arduino-uart.zip

FILE: dht.h
VERSION: 0.1.05
PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
URL: http://playground.arduino.cc/Main/DHTLib
HISTORY:
see dht.cpp file


MemoryFree library based on code posted here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720/15
Extended by Matthew Murdoch to include walking of the free list.

 */



#include <SPI.h>
#include <Ethernet.h>
#include "kSeries.h"
#include <dht.h>
#include <MemoryFree.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

dht DHT;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);



EthernetClient client; //

char CurTemp[5]={
}
,CurHum[5]={
}
,ppm[5]={
};

kSeries K_30(6,8);

// CHANGE MAC ADDRESS TO ANY OTHER!!! (use http://www.miniwebtool.com/mac-address-generator/ for example)
byte mac[] = {
  0x90, 0xA2, 0x7C, 0x5E, 0xA7, 0xB9       }; // default mac address of ethernet shield

boolean DHCP = true,NMService=true,DHT22=true,DL=false,K30=true;

IPAddress IP=(192,168,1,121),GW=(192,168,1,1),DNS=(192,168,1,1),NMIP=(94,19,113,221);
IPAddress server(94,19,113,221);
int DHT_P=(7),DL_P=int (5);


const unsigned long postingInterval = 400000;  // интервал между отправками данных в миллисекундах (5 минут)
unsigned long lastConnectionTime = postingInterval;           // время последней передачи данных
boolean lastConnected = false;                  // состояние подключения
int HighByte, LowByte, TReading, SignBit, Tc_100;
char replyBuffer[106],macch[14];


void setup() {
  delay(200);
  Serial.begin (115200);
  if (DHCP) {
    if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed  DHCP");
      // doing nothing
      for(;;)
        ;
    }
  }
  else {
    Ethernet.begin(mac, IP);

  };
  delay(500);  // Couple of seconds just to warm up Ethernet.
  Serial.println();
  Serial.print("IP ");
  Serial.println(Ethernet.localIP());
  genmacchar();

  lcd.backlight ();

  lcd.begin(16,2);               // initialize the lcd

  lcd.home ();                   // go home
  lcd.print ("IP ");
  lcd.print(Ethernet.localIP());
  lcd.setCursor ( 0, 1 );        // go to the next line
  lcd.print ("MAC ");    
  lcd.print (macch);

  Serial.println();
  Serial.print("IP Address is ");
  Serial.println(Ethernet.localIP());


  Serial.print ("MAC ");
  Serial.println (macch);
  delay (2500);
  lcd.clear ();
  lcd.home ();
  lcd.print ("   ");
  lcd.print((char)223);
  lcd.print ("C");
  lcd.setCursor ( 0, 1 );
  lcd.print ("   ");

  lcd.print ("%     ppm");




}

void loop() {
  delay (500);

  lcd.home ();
  if (DHT22) DHTRead();
  if (K30)  co2();

  delay (3000);
  Serial.print("frmem()=");
  Serial.println(freeMemory());
  //debug
  if (client.connected()) Serial.println ("client connected");


  Serial.println ("client stopped");

  Serial.print ("lastConnectionTime= ");
  Serial.println (lastConnectionTime);
  Serial.print ("postingInterval= ");
  Serial.println (postingInterval);
  Serial.print ("millis= ");
  Serial.println (millis());
  Serial.print ("CurTemp=");
  Serial.println (CurTemp);
  Serial.print ("CurHum=");
  Serial.println (CurHum);
  Serial.print("frmem()=");
  Serial.println(freeMemory());

  //debug
  if (client.connected() && lastConnected) {
    client.stop();
  }
  if(!client.connected() && ((millis() - lastConnectionTime )> postingInterval))   {
    formingPOST ();

  }
  lastConnected = client.connected();

  delay (1000);



}



void co2 (){ //reading data from CO2 sensor
  itoa (K_30.getCO2('p'),ppm,10);
  //Print the value on Serial
  Serial.print("Co2 =");
  Serial.println(ppm);
  lcd.setCursor (9,0);
  lcd.print ("     ");
  lcd.setCursor (9,0);
  lcd.print (ppm);

}


void formingPOST (){

  Serial.println ("forming POST");

  //формирование HTTP-запроса. Preparing http request.
  memset(replyBuffer, 0, sizeof(replyBuffer));
  strcpy(replyBuffer,"ID=");
  strcat(replyBuffer,macch);
  //Конвертируем MAC-адрес. Converting mac address.

  //конвертируем адрес термодатчика. Converting first sensor address.
  Serial.print ("Here is our replyBuffer");
  Serial.println (replyBuffer);
  strcat(replyBuffer,"&");
  strcat(replyBuffer,macch);
  strcat(replyBuffer,"01");
  Serial.print ("Here is our replyBuffer");
  Serial.println (replyBuffer);
  //конвертируем адрес датчика влажности. Converting secong sensor address.
  strcat(replyBuffer,"=");
  if (SignBit)
  {
    strcat(replyBuffer,"-");
    Serial.println (" Beware of Minus !!! ");
  }

  strcat(replyBuffer,CurTemp);
  strcat(replyBuffer,"&");
  strcat(replyBuffer,macch);
  strcat(replyBuffer,"02");
  strcat(replyBuffer,"=");
  strcat(replyBuffer,CurHum);
  strcat(replyBuffer,"&");
  strcat(replyBuffer,macch);
  strcat(replyBuffer,"03");
  strcat(replyBuffer,"=");
  Serial.print ("Here is our ppm");
  Serial.println (ppm);
  strcat(replyBuffer,ppm);
  Serial.print ("Here is our replyBuffer");
  Serial.println (replyBuffer);
  httpRequest();



}

void httpRequest() {
  Serial.print ("staring to POST request");

  if (client.connect(server, 80)) {

    // send the HTTP POST request:
    client.println("POST http://narodmon.ru/post.php HTTP/1.0");
    Serial.println("POST http://narodmon.ru/post.php HTTP/1.0");
    client.println("Host: narodmon.ru");
    Serial.println("Host: narodmon.ru");
    //client.println("User-Agent: arduino-ethernet");
    //client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded");
    Serial.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(strlen(replyBuffer));
    Serial.print("Content-Length: ");
    Serial.println(strlen(replyBuffer));
    client.println();
    Serial.println();
    client.println(replyBuffer);
    Serial.println(replyBuffer);
    client.println();

    delay(1000);
  }
  else {
    Serial.print("http request failed - client not connected");
    client.stop();
  }
  lastConnectionTime = millis();
}

void DHTRead (){

  int chk = DHT.read22(DHT_P);
  Serial.print(chk);
  switch (chk)
  {
  case DHTLIB_OK:
    Serial.println("DHT OK,\t");
    delay (1000);
    dtostrf(DHT.temperature, 3, 0, CurTemp);
    Serial.print("temp and hum");
    Serial.print (CurTemp);

    Serial.print(",\t");
    delay (1000);
    dtostrf(DHT.humidity, 3, 0, CurHum);
    Serial.println (CurHum);
    lcd.setCursor(0,0);
    lcd.print ("   ");
    lcd.setCursor (0,1);
    lcd.print ("   ");
    lcd.setCursor(0,0);
    lcd.print (CurTemp);
    lcd.setCursor (0,1);
    lcd.print (CurHum);

    break;
  case DHTLIB_ERROR_CHECKSUM:
    Serial.print("Checksum er,\t");
    break;
  case DHTLIB_ERROR_TIMEOUT:
    Serial.print("Time out er,\t");
    break;
  default:
    Serial.print("Unknown er,\t");
    break;

  }


}

void genmacchar() {
  for (int k=0; k<6; k++)
  {
    int b1=mac[k]/16;
    int b2=mac[k]%16;
    char c1[2],c2[2];

    if (b1>9) c1[0]=(char)(b1-10)+'A';
    else c1[0] = (char)(b1) + '0';
    if (b2>9) c2[0]=(char)(b2-10)+'A';
    else c2[0] = (char)(b2) + '0';

    c1[1]='\0';
    c2[1]='\0';

    strcat(macch,c1);
    strcat(macch,c2);
  }
}



Выглядит непрезентабельно, комментариев мало, если будет возможность - переделаю.
ОБЯЗАТЕЛЬНО меняем mac адрес в скетче на свой или на генерируемый.

Вставляем все в корпус и запускаем. Приятной сборки.





Friday, June 14, 2013

Контроль влажности и температуры дома и не только DIY.

Детский кашель двигатель прогресса.

После очередной бессонной ночи и утреннего просмотра лекций д-ра Комаровского стало ясно что влажность, на которую я внимания никогда не обращал, имеет значение для здоровья моего маленького ребенка. Детский кашель очень тесно связан с уровнем влажности (humidity) воздуха, и желательно этот самый уровень отслеживать и им управлять. Собственно для управления уровнем влажности был включен уже давно валявшийся увлажнитель sharp kc-6500e. Но хотелось еще чего нибудь smart, да и увлажнитель один, а комнат много, надо решать где он больше востребован. Температурные показатели легко ощутить без дополнительных приборов. Холодно или тепло в комнате обычно определяешь без градусников, а вот влажность физически ощутить сложнее. Поэтому было принято решение купить/собрать (нужное подчеркнуть) датчики для мониторинга уровня влажности в комнатах.
Побродив по магазинам и просторам сети я понял что не могу купить просто метеостанцию в каком нибудь *Mart, т.к. предлагающиеся устройства никак не вписываются в современность. Ну не буду я бегать каждый час по всем комнатам и записывать показания с экранов метеостанций, хочу чтобы мне эти данные отправлялись куда нибудь, а я потом их проанализирую. На правильную мысль навела статья на Habrhabr. Короче нужно устройство с разъемом Ethernet или wifi или zigbee... Проводные сети я всегда считал более надежными, да и сеть дома проложена с запасом.

Arduino, PoE, DHT11/21/22, narodmon.ru


Постепенно выработались некие требования к решению:

  • сбор данных и передача их в какие либо сервисы (собственные или сторонние)
  • физический интерфейс RJ45 (ethernet) 
  • работа без батареек
  • приглядный внешний вид, отсутствие мотков с проводами вокруг.
  • возможность перетащить в другой дом (с другой сетью и провайдером) без доп настроек.
  • измерение уровня влажности и температуры. При необходимости добавление сенсоров.
  • если собирать самому, то без особых заморочек. Я не дружу с паяльником и программатором.


Исходя из требований к снижению количества проводов и работы без батареек я решил что лучшим решением будет использование PoE (Power over ethernet) для датчика. К тому же незадолго перед этим был заказан коммутатор с PoE под нужды видео-наблюдения. При необходимости, можно подключить и с помощью обычного блока питания.

На данный момент на рынке нашел чешский HWg-STE PoE, отечественный netping, оба вроде отвечают требованиям.

Сервис narodmon.ru предлагает кучу вариантов датчиков и неплохой сервис по отслеживанию их состояния. Средняя стоимость датчиков составляет в среднем 3000 руб., что в общем то меня уже не пугало так сильно как детский кашель. И все бы хорошо, но PoE ни у кого нет. Всем подавай отдельные блоки питания, а это куча лишних проводов, занятая розетка и вообще не интересно.
Самое простое решение которое пришло в голову - взять за основу решение на Arduino и чуть чуть его изменить под свои нужды. Если три платы заменить на одну, и добавить PoE, то получим то что нужно.

Для датчика были заказаны:


  1. Arduino Ethernet Rev3 WITH PoE (A000074)  = €54.90 + доставка  €9 (arduino.cc) В сумме на 2600 руб.
  2. DHT22 2302 Digital Temperature and Humidity Sensor Module = 11$ или 340 руб. (При заказе из Китая их лучше комплектовать с товарами погабаритнее чтобы по почте быстрее шло. Меньше посылка - дольше идет. В моем случае 60 дней).
  3. Как потом оказалось нужен еще USB 2 Serial Converter (A000059) для программирования Arduino, поскольку в этой модели нет USB разъема, его место занял Ethernet. Включать еще €10 в стоимость устройства или нет непонятно, т.к. он нужен только при программировании. В общем плюс еще 400 руб.
Итого требуется электроники на 3340 руб. Если закупать не Made in Italy, а клоны, то будет дешевле, но надо еще найти клоны с PoE модулем. При покупке всего этого добра в России увеличиваем бюджет до 4500 руб. Все элементы доставлялись почтой России, часть дошла за 30 дней, а часть до сих пор в пути, вместо DHT 22 пока установил DHT 11 - они дешевле, но менее точные. Пожалуйста не используйте DHT 11.
С сенсорами вообще вышла какая то неувязка. По идее это должны быть цифровые сенсоры, и распиновка по всем datashit с незадействованным третьим пином.

Но мне с Amperka.ru пришли сенсоры уже с резисторами, с разъемом и работали как аналоговые. При этом судя по пайке в этом варианте не использовался 4й пин (как на картинке справа).



Реализация на DHT 11/21/22 (пожалуйста не покупайте DHT11 - используйте DHT22)

Аналоговое подключение сенсоров.

Скетч который у меня заработал в итоге с аналоговым вариантом DHT11 с библиотекой от амперки (не забываем менять MAC адрес устройства на свой, большая часть кода взята отсюда, отсюда и отсюда ):





У этого решения множество багов:
1. DHT11 в таком исполнении всегда врал. Возможно бракованные сенсоры попались, но врали они безбожно. Влажность почти всегда на одном уровне 33%.
2. Результаты иногда странным образом задваивались, то есть вместо 33% влажности получалось 66%. В код  нужно добавлять контроль результата измерения в сравнении с последними данными.
3. Часть позволяющая устройству работать в качестве веб сервера закоментированна, поскольку я её после отладки не использовал, может надо кому.

Цифровое подключение сенсоров

Схема соединения и код который заработал с цифровым подключением DHT22. Сенсор который был у меня уже имел необходимую обвязку (подтягивающий резистор).

 
Библиотека для DHT здесь  и теперь он поддерживает и DHT21.
Код:


Внимание апдейт - я пересмотрел свое отношение к коду - оказалось что датчик корректно отображал показания только при первом включении. Дальше показания не менялись до следующей перезагрузки. Поэтому исходный код я изменил, и новый вставил в статью на место старого. Кроме того, обращаю внимание - для работы скетча необходимо установить соответствующую библиотеку. Библиотека для DHT не входит в стандартный набор устанавливаемый вместе с IDE Adruino. Библиотеку я использовал не с Amperka.ru. 

готовое устройство:

В качестве корпуса использовал корпуса от FDD и CD.
метеостанция Arduino +DHT22

датчик Arduino + DHT22 в сборе

DHT22 с обвязкой

Кстати, есть новая версия скетча и инструкций.