После очередной бессонной ночи и утреннего просмотра лекций д-ра Комаровского стало ясно что влажность, на которую я внимания никогда не обращал, имеет значение для здоровья моего маленького ребенка. Детский кашель очень тесно связан с уровнем влажности (humidity) воздуха, и желательно этот самый уровень отслеживать и им управлять. Собственно для управления уровнем влажности был включен уже давно валявшийся увлажнитель
. Но хотелось еще чего нибудь smart, да и увлажнитель один, а комнат много, надо решать где он больше востребован. Температурные показатели легко ощутить без дополнительных приборов. Холодно или тепло в комнате обычно определяешь без градусников, а вот влажность физически ощутить сложнее. Поэтому было принято решение купить/собрать (нужное подчеркнуть) датчики для мониторинга уровня влажности в комнатах.
Побродив по магазинам и просторам сети я понял что не могу купить просто метеостанцию в каком нибудь *Mart, т.к. предлагающиеся устройства никак не вписываются в современность. Ну не буду я бегать каждый час по всем комнатам и записывать показания с экранов метеостанций, хочу чтобы мне эти данные отправлялись куда нибудь, а я потом их проанализирую. На правильную мысль навела статья на
. Короче нужно устройство с разъемом Ethernet или wifi или zigbee... Проводные сети я всегда считал более надежными, да и сеть дома проложена с запасом.
Исходя из требований к снижению количества проводов и работы без батареек я решил что лучшим решением будет использование PoE (Power over ethernet) для датчика. К тому же незадолго перед этим был заказан коммутатор с PoE под нужды видео-наблюдения. При необходимости, можно подключить и с помощью обычного блока питания.
, оба вроде отвечают требованиям.
предлагает кучу вариантов датчиков и неплохой сервис по отслеживанию их состояния. Средняя стоимость датчиков составляет в среднем 3000 руб., что в общем то меня уже не пугало так сильно как детский кашель. И все бы хорошо, но PoE ни у кого нет. Всем подавай отдельные блоки питания, а это куча лишних проводов, занятая розетка и вообще не интересно.
и чуть чуть его изменить под свои нужды. Если три платы заменить на одну, и добавить PoE, то получим то что нужно.
Скетч который у меня заработал в итоге с аналоговым вариантом DHT11 с библиотекой от амперки (не забываем менять MAC адрес устройства на свой, большая часть кода взята
// подключаем библиотеки (для DHT аналогового -
https://github.com/amperka/dht)
#include <dht.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>
#include <SPI.h>
// создаём объект-сенсор
DHT sensor = DHT();
const unsigned long postingInterval = 600000; // интервал между отправками данных в миллисекундах (10 минут)
unsigned long lastConnectionTime = 0; // время последней передачи данных
boolean lastConnected = false; // состояние подключения
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
char replyBuffer[106];
char CurTemp[6];
// ========================Задаем данные сети======================
byte mac[] = {
0x92, 0xA2, 0xDA, 0x0D, 0xD2, 0x3A }; //mac - адрес ethernet shielda
// byte ip[] = { 192, 168, 1, 177 }; // ip адрес ethernet shielda (в случае DHCP не нужен)
// byte subnet[] = { 255, 255, 255, 0 }; //маска подсети (в случае DHCP не нужен)
// EthernetServer server(80); //порт сервера
EthernetClient client; //
int ledPin = 9; // указываем что светодиод будет управляться через 9 Pin
String readString = String(30); //string for fetching data from address
boolean LEDON = false; //изначальный статус светодиода - выключен
IPAddress server(94,19,113,221); // IP сервера
// ===============================================================
void setup()
{
delay(1000);
// Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// ничего не делаем
for(;;)
;
}
// секунда для инициализации Ethernet
delay(1000);
// секунда для инициализации Ethernet
delay(1000);
lastConnectionTime = millis()-postingInterval+15000; //первое соединение через 15 секунд после запуска
//запускаем Ethernet
// Ethernet.begin(mac);
//устанавливаем pin 9 на выход
pinMode(ledPin, OUTPUT);
//enable serial datada print
Serial.begin(9600);
Serial.println("Port Test!"); // Тестовые строки для отображения в мониторе порта
Serial.println("GO!");// Тестовые строки для отображения в мониторе порта
delay(1000);
// методом attach объявляем к какому контакту подключен
// сенсор. В нашем примере это нулевой аналоговый контакт
sensor.attach(A0);
//
// после подачи питания ждём секунду до готовности сенсора к работе
delay(2000);
// lastConnectionTime = millis()-postingInterval+15000; //первое соединение через 15 секунд после запуска
}
void loop()
{
// метод update заставляет сенсор выдать текущие измерения
delay(5000);
sensor.update();
//switch (sensor.getLastError())
//{
// case DHT_ERROR_OK:
// char msg[128];
// данные последнего измерения можно считать соответствующими
// методами
// sprintf(msg, "Temperature = %dC, Humidity = %d%%",
// sensor.getTemperatureInt(), sensor.getHumidityInt());
// Serial.println(msg);
// break;
// case DHT_ERROR_START_FAILED_1:
// Serial.println("Error: start failed (stage 1)");
// break;
// case DHT_ERROR_START_FAILED_2:
// Serial.println("Error: start failed (stage 2)");
// break;
// case DHT_ERROR_READ_TIMEOUT:
// Serial.println("Error: read timeout");
// break;
// case DHT_ERROR_CHECKSUM_FAILURE:
// Serial.println("Error: checksum error");
// break;
//}
if (client.available()) {
char c = client.read();
}
if (!client.connected() && lastConnected)
{
client.stop();
}
if(!client.connected() && (millis() - lastConnectionTime > postingInterval))
{
//отправляем запрос
int t = sensor.getTemperatureInt();
delay (2000);
int h= sensor.getHumidityInt();
delay (2000);
// EthernetClient client = server.available();
// if (client) {
// while (client.connected()) {
// if (client.available()) {
// char c = client.read();
//read char by char HTTP request
// if (readString.length() < 30) {
//store characters to string
// readString.concat( c); }
//output chars to serial port
// Serial.print( c);
//if HTTP request has ended
// if (c == '\n') {
//Проверяем включили ли светодиод?
//Level=1 - включен
//Level=0 - выключен
// if(readString.indexOf("Level=1") >=0) {
//Включаем светодиод
// digitalWrite(ledPin, HIGH); // set the LED on
// LEDON = true;
// }else{
//Выключаем светодиод
// digitalWrite(ledPin, LOW); // set the LED OFF
// LEDON = false;
// }
// =============Формируем HTML-страницу==========================
// client.println("HTTP/1.1 200 OK");
// client.println("Content-Type: text/html");
// client.println();
// client.println("<head> ");
// client.println("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' /> ");
// client.println("<title> :: Упр.Arduino:: V1.1</title>");
// client.println("</head> ");
// client.println("<body");
// client.println("<hr />");
// client.println("<h1> ::Упр.Arduino:: </h1>");
// if (LEDON){
// client.println("<form method=get name=LED><input type=radio name=Level value=1 CHECKED>Включить<input type=radio name=Level value=0>Выключить<input type=submit value=OK></form>");
// client.println("<font size=’5′>LED-статус: ");
// client.println("<font size=’5′>Вкл.");
// }else{
// client.println("<form method=get name=LED><input type=radio name=Level value=1>Включить<input type=radio name=Level value=0 CHECKED>Выключить<input type=submit value=OK></form>");
// client.println("<font size=’5′>LED-статус: ");
// client.println("<font size=’5′>Выкл");
// }
//==============Вывод значений на web-страницу======================
// client.println("<hr />");//линия=====================================
// client.println("Tемпература = "); //Температура с DHT 22
// client.println(t);
// client.println(" *C");
// client.println("<br> "); //перенос на след. строчку
// client.println("Влажность = "); //Влажность с DHT 22
// client.println(h);
// client.println(" %\t");
// client.println("<br> "); //перенос на след. строчку
// client.println("<hr />");//линия=====================================
//==============================================================
// client.println("</body></html>");
//очищаем строку для следующего считывания
//==============Останавливаем web-client===========================
// readString="";
// client.stop();
//==============================================================
// }
// }
// }
// }
char temp[3];
char hum[2];
//формирование HTTP-запроса
memset(replyBuffer, 0, sizeof(replyBuffer));
strcpy(replyBuffer,"ID=");
//Конвертируем MAC-адрес
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(replyBuffer,c1);
strcat(replyBuffer,c2);
}
strcat(replyBuffer,"&");
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(replyBuffer,c1);
strcat(replyBuffer,c2);
}
strcat(replyBuffer,"01");
//конвертируем адрес термодатчика
strcat(replyBuffer,"=");
if (SignBit)
{
strcat(replyBuffer,"-");
}
itos(t,temp);
strcat(replyBuffer,temp);
strcat(replyBuffer,".");
strcat(replyBuffer,"&");
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(replyBuffer,c1);
strcat(replyBuffer,c2);
}
strcat(replyBuffer,"02");
//конвертируем адрес датчика влажности
strcat(replyBuffer,"=");
itos(h,hum);
strcat(replyBuffer,hum);
strcat(replyBuffer,".");
// strcat(replyBuffer,"&");
strcat(CurTemp,temp);
// Serial.println(replyBuffer);
//отправляем запрос
httpRequest();
}
lastConnected = client.connected();
}
void httpRequest() {
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.println("Content-Length: 53");
Serial.println("Content-Length: 53");
client.println();
Serial.println();
client.println(replyBuffer);
Serial.println(replyBuffer);
client.println();
lastConnectionTime = millis();
delay(1000);
}
else {
client.stop();
}
}
void itos(int n, char bufp[3]) //int to string
{
char buf[3]={'0','0','\0'};
int i = 1;
while (n > 0) {
buf[i] = (n % 10)+48;
i--;
n /= 10;
}
for (i=0; i<3; i++)
bufp[i]=buf[i];
}
1. DHT11 в таком исполнении всегда врал. Возможно бракованные сенсоры попались, но врали они безбожно. Влажность почти всегда на одном уровне 33%.
2. Результаты иногда странным образом задваивались, то есть вместо 33% влажности получалось 66%. В код нужно добавлять контроль результата измерения в сравнении с последними данными.
3. Часть позволяющая устройству работать в качестве веб сервера закоментированна, поскольку я её после отладки не использовал, может надо кому.
Схема соединения и код который заработал с цифровым подключением DHT22. Сенсор который был у меня уже имел необходимую обвязку (подтягивающий резистор).
и теперь он поддерживает и DHT21.
В качестве корпуса использовал корпуса от FDD и CD.