Подключение Arduino к отечественному проекту Народного мониторинга
Хочу рассказать ещё об одном сервисе для удалённого мониторинга температуры, преимущественно за окном. На этот раз проект отечественный, что не может не радовать.


Последнее обновление: 16 июля 2014 (v1.3)
Исправлена ошибка с дробными показаниями температуры
6 октября 2013 (v1.2)
При наличии нескольких термодатчиков данные передаются на сервер одновременно со всех, а не по очереди, как было раньше.
25 февраля 2013 (v1.1)
Исправлена ошибка с округлением отрицательной температуры до десятых долей градуса.
Немного о проекте
Сервис располагается по адресу http://narodmon.ru
Проект начался с обсуждения темы «Народный мониторинг температуры (vs прогноз) в различных городах. Нужен ли?» на Хабрахабре. На тот момент целью проекта являлось лишь информирование пользователей в Интернет о реальной погоде в данный момент времени в определенном месте, где есть участники данного проекта. C дальнейшим ростом аудитории разработчиков электронных устройств для работы с данным проектом, а также пополнением базы пользователей, возникла необходимость расширить рамки проекта с целью передачи сбора показаний с датчиков различного типа с более универсальным протоколом с крайне низкими требованиями к каналу передачи данных вплоть до GPRS/EDGE/3G/UMTS.
Собираем устройство
Нам понадобятся следующие компоненты:
- Микроконтроллер Arduino или Freeduino (с ATmega328);
- Ethernet-shield;
- Цифровой термодатчик DS18B20;
- Резистор 4.7 кОм;



Все компоненты соединяются между собой также как и в предыдущей статье: Arduino: цифровой термометр с web-мониторингом. Немного повторюсь:
Термодатчик подключается по шине 1-wire по схеме с паразитным питанием. При этом, можно использовать несколько таких датчиков (все они соединяются параллельно двумя проводами) и считывать с каждого отдельную температуру. Подключать можно к любому цифровому входу микроконтроллера, кроме 10, 11, 12 и 13, которые используются для нужд Ethernet Shield.
Прошивка
Теперь заливаем в Arduino следующий скетч:
// Скетч для Arduino для отправки данных о температуре на Народный мониторинг. // Версия 1.3 (16.07.2014) // // Автор: Гладышев Дмитрий (2012-2014) // http://student-proger.ru/2012/06/podklyuchenie-arduino-k-otechestvennomu-proektu-narodnogo-monitoringa/ #include <SPI.h> #include <Ethernet.h> #include <OneWire.h> bool Debug = false; //режим отладки //**************************************************************************************** byte mac[] = { 0xDE, 0xAD, 0xBE, 0x00, 0x00, 0x00 }; //MAC-адрес Arduino OneWire ds(2); //пин подключения термодатчика const unsigned long postingInterval = 600000; // интервал между отправками данных в миллисекундах (10 минут) //**************************************************************************************** char server[] = "narodmon.ru"; EthernetClient client; unsigned long lastConnectionTime = 0; // время последней передачи данных boolean lastConnected = false; // состояние подключения int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract; char replyBuffer[160]; int CountSensors; void setup() { if (Debug) { Serial.begin(9600); } delay(1000); // Ethernet connection: if (Ethernet.begin(mac) == 0) { if (Debug) { Serial.println("Failed to configure Ethernet using DHCP"); } // ничего не делаем for(;;); } // секунда для инициализации Ethernet delay(1000); //Узнаём количество термодатчиков CountSensors = DsCount(); if (Debug) { Serial.print("Found "); Serial.print(CountSensors); Serial.println(" sensors."); } lastConnectionTime = millis()-postingInterval+15000; //первое соединение через 15 секунд после запуска } void loop() { //Если вдруг нам случайно приходят откуда-то какие-то данные, //то просто читаем их и игнорируем, чтобы очистить буфер if (client.available()) { client.read(); } if (!client.connected() && lastConnected) { if (Debug) { Serial.println(); Serial.println("disconnecting."); } client.stop(); } //если не подключены и прошло определённое время, то делаем замер, //переподключаемся и отправляем данные if (!client.connected() && (millis() - lastConnectionTime > postingInterval)) { //формирование 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); } //Сбрасываем поиск датчиков (кол-во нам уже известно) ds.reset_search(); //Теперь в цикле опрашиваем все датчики сразу for (int j=0; j<CountSensors; j++) { byte i; byte present = 0; byte data[12]; byte addr[8]; if ( !ds.search(addr)) { ds.reset_search(); return; } ds.reset(); ds.select(addr); ds.write(0x44,1); delay(1000); present = ds.reset(); ds.select(addr); ds.write(0xBE); for ( i = 0; i < 9; i++) // we need 9 bytes { data[i] = ds.read(); } LowByte = data[0]; HighByte = data[1]; TReading = (HighByte << 8) + LowByte; SignBit = TReading & 0x8000; // test most sig bit if (SignBit) // negative { TReading = (TReading ^ 0xffff) + 1; // 2's comp } Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25 Whole = Tc_100 / 100; // separate off the whole and fractional portions Fract = Tc_100 % 100; char temp[3]; itos(Whole,temp); strcat(replyBuffer,"&"); //конвертируем адрес термодатчика for (int k=7; k>=0; k--) { int b1=addr[k]/16; int b2=addr[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,"="); if (SignBit) //если температура отрицательная, добавляем знак минуса { strcat(replyBuffer,"-"); } strcat(replyBuffer,temp); strcat(replyBuffer,"."); if (Fract<10) { strcat(replyBuffer,"0"); } itos(Fract,temp); strcat(replyBuffer,temp); } strcat(replyBuffer,'\0'); if (Debug) { Serial.println(replyBuffer); Serial.print("Content-Length: "); Serial.println(len(replyBuffer)); } //отправляем запрос httpRequest(); } //храним последнее состояние подключения lastConnected = client.connected(); } void httpRequest() { if (client.connect(server, 80)) { if (Debug) { Serial.println("connecting..."); } // send the HTTP POST request: client.println("POST http://narodmon.ru/post.php HTTP/1.0"); client.println("Host: narodmon.ru"); //client.println("User-Agent: arduino-ethernet"); //client.println("Connection: close"); client.println("Content-Type: application/x-www-form-urlencoded"); client.print("Content-Length: "); client.println(len(replyBuffer)); client.println(); client.println(replyBuffer); client.println(); lastConnectionTime = millis(); } else { if (Debug) { Serial.println("connection failed"); Serial.println("disconnecting."); } client.stop(); } } //Количество термодатчиков на шине int DsCount() { int count=0; bool thatsall = false; byte addr[8]; do { if ( !ds.search(addr)) { ds.reset_search(); thatsall = true; } count++; } while(!thatsall); return (count-1); } int len(char *buf) { int i=0; do { i++; } while (buf[i]!='\0'); return i; } 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]; }
Обратите внимание на следующие строки:
//**************************************************************************************** byte mac[] = { 0xDE, 0xAD, 0xBE, 0x00, 0x00, 0x00 }; //MAC-адрес Arduino OneWire ds(2); //пин подключения термодатчика const unsigned long postingInterval = 600000; // интервал между отправками данных в миллисекундах (10 минут) //****************************************************************************************
Здесь необходимо будет придумать MAC-адрес для Arduino (рекомендую взять для этого MAC-адрес вашего компьютера), указать номер входа, к которому подключен термодатчик, а также частоту обновления информации. По MAC-адресу устройство будет идентифицироваться в проекте, поэтому он должен быть уникальным.
Теперь регистрация на сайте
Заходим на сайт, жмём кнопочку «Вход», затем «Я тут впервые». Вводим свой E-Mail и ждём пока на почту свалится письмо с паролем.

Входим в систему.

Теперь нажимаем кнопку «Мои датчики», затем «Добавить». Вводим MAC-адрес, который указан в прошивке. Теперь система должна отобразить подключенные термодатчики и температуру на них. Можно указать местоположение термометра на карте и дать подписи датчикам.


Щёлкнув по пузырьку с температурой на карте, можно просмотреть дополнительную информацию:

Также можно просмотреть график изменения параметра:

и отчёт о переданных числовых данных:

Скетч v1.2
Скетч v1.1
Библиотеки:
Ethernet
OneWire
SPI
Работа проверялась с Arduino IDE v1.0.1
