Доброе утро всем! Очень нужна помощь знатоков в завершении одного скетча под arduino uno+ethernet shield w5100+rf433. Задача очень простая: 1. По радиоканалу получить данные с датчика температуру и влажность 2. По езернет каналу отобразить их в локальной сети. Так вот. Скетч готов на 99.99%. Проблема только одна: при получении данных с датчика они запоминаются ардуиной и если вдруг беспроводной датчик отвалится, то данные так и будут висеть в памяти ардуинки. По логике понимаю, что необходимо каждому параметру по таймеру и его сбрасывать при приеме данных, как лимит таймера превысил к примеру 30 минут, то пишем ошибку или скидываем данные в 0. Подскажите как это реализовать? Вот мой код: Код (C++): #include <SPI.h> #include <Ethernet.h> #include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); float tempout1=0,Hr1=0,tempout2=0,Hr2=0; #define key1 11000 // датчик температуры 1 #define key2 12000 // датчик влажность 1 #define key3 21000 // датчик температуры 2 #define key4 22000 // датчик влажность 2 #define REQ_BUF_SZ 20 char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string char req_index = 0; // index into HTTP_req buffer byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192, 168, 1, 20); EthernetServer server(80); void setup() { Ethernet.begin(mac, ip); mySwitch.enableReceive(0); server.begin(); } void loop() { if (mySwitch.available()) { unsigned long receivedCode= mySwitch.getReceivedValue(); if (receivedCode == 0) { // обработка:не верный формат данных } else { if (key1<=receivedCode && key1+999>receivedCode) tempout1=(float)(receivedCode-key1-500)/10; else if (key2<=receivedCode && key2+999>receivedCode) Hr1=(float)(receivedCode-key2)/10; else if (key3<=receivedCode && key3+999>receivedCode) tempout2=(float)(receivedCode-key3-500)/10; else if (key4<=receivedCode && key4+999>receivedCode) Hr2=(float)(receivedCode-key4)/10; } mySwitch.resetAvailable(); // сброс данных. } // listen for incoming clients EthernetClient client = server.available(); if (client) { // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // save HTTP request character req_index++; } if (c == '\n' && currentLineIsBlank) { if (StrContains(HTTP_req, "GET / ")) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Connection: close"); client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<link rel='shortcut icon' href='favicon.ico' type='image/x-icon'>"); client.println("<meta http-equiv='refresh' content='10'/>"); client.println("<meta http-equiv='content-type' content='text/html; charset=UTF-8'>"); client.println("<title>Данные с датчиков</title>"); client.print("Температура1 = "); client.print(tempout1); client.print(" °C<br/>"); client.print("Влажность1 = "); client.print(Hr1); client.print(" %<br/>"); client.print("Температура2 = "); client.print(tempout2); client.print(" °C<br/>"); client.print("Влажность2 = "); client.print(Hr2); client.print(" %<br/>"); client.println("</html>"); } req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); } } void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } } char StrContains(char *str, char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; }
Тут дело не в показаниях. Датчик беспроводной по радиоканалу представляет из себя тиньку 13+ds18b20+STX882. Запитано это все от батарейки, точнее двух ААА. И вот если вдруг батарейка сдохла, то на принимающей ардуинке так и будут висеть последние принятые данные.
как я понимаю в это вместо Код (C++): if (mySwitch.available()) { unsigned long receivedCode= mySwitch.getReceivedValue(); if (receivedCode == 0) { // обработка:не верный формат данных } else { if (key1<=receivedCode && key1+999>receivedCode) tempout1=(float)(receivedCode-key1-500)/10; else if (key2<=receivedCode && key2+999>receivedCode) Hr1=(float)(receivedCode-key2)/10; else if (key3<=receivedCode && key3+999>receivedCode) tempout2=(float)(receivedCode-key3-500)/10; else if (key4<=receivedCode && key4+999>receivedCode) Hr2=(float)(receivedCode-key4)/10; } mySwitch.resetAvailable(); // сброс данных. } необходимо вставить таймер. при получении пакета засечь таймер и если прошло больше 35 минут, то значения key1-key4 сбрасывать в 0 Осталось только программно это реализовать.
Ну я бы предположил, что проверку таймера нужно впихнуть перед сбросом данных, но здравый смысл возражает против такого решения. Из этого вопрос - в каком месте останавливается ваша программа?
Можно организовать счетчик с помощью millis() типа : time = millis()/60000; и при отсутствии сигнала с датчика сохранить time в переменную, потом их сравнивать. и если разница достигнет 35 сбросить значения key1-key4
Можно к отображаемым данным, если это БД или просто веб-страничка, добавить параметр "Время приема последнего пакета от датчика". Тогда сразу будет видно, как давно ваш датчик отдавал данные.
В данном случае я бы сделал так: Код (C++): #include <SPI.h> #include <Ethernet.h> #include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); float tempout1 = 0, Hr1 = 0, tempout2 = 0, Hr2 = 0; bool is_timer_enabled = false; unsigned long timer; #define key1 11000 // датчик температуры 1 #define key2 12000 // датчик влажность 1 #define key3 21000 // датчик температуры 2 #define key4 22000 // датчик влажность 2 #define REQ_BUF_SZ 20 char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string char req_index = 0; // index into HTTP_req buffer byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192, 168, 1, 20); EthernetServer server(80); void setup() { Ethernet.begin(mac, ip); mySwitch.enableReceive(0); server.begin(); } void loop() { if (mySwitch.available()) { unsigned long receivedCode = mySwitch.getReceivedValue(); if(!is_timer_enabled) { timer=millis(); is_timer_enabled = true; } if (receivedCode == 0) { // обработка:не верный формат данных } else { if (key1 <= receivedCode && key1 + 999 > receivedCode) tempout1 = (float)(receivedCode - key1 - 500) / 10; else if (key2 <= receivedCode && key2 + 999 > receivedCode) Hr1 = (float)(receivedCode - key2) / 10; else if (key3 <= receivedCode && key3 + 999 > receivedCode) tempout2 = (float)(receivedCode - key3 - 500) / 10; else if (key4 <= receivedCode && key4 + 999 > receivedCode) Hr2 = (float)(receivedCode - key4) / 10; } if(is_timer_enabled) { if(millis()-timer > 30*60*1000) { //Сбрасываем все, что нужно is_timer_enabled = false; //Затем опускаем флаг работы таймера } } mySwitch.resetAvailable(); // сброс данных. } // listen for incoming clients EthernetClient client = server.available(); if (client) { // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // save HTTP request character req_index++; } if (c == '\n' && currentLineIsBlank) { if (StrContains(HTTP_req, "GET / ")) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Connection: close"); client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); client.println("<link rel='shortcut icon' href='favicon.ico' type='image/x-icon'>"); client.println("<meta http-equiv='refresh' content='10'/>"); client.println("<meta http-equiv='content-type' content='text/html; charset=UTF-8'>"); client.println("<title>Данные с датчиков</title>"); client.print("Температура1 = "); client.print(tempout1); client.print(" °C<br/>"); client.print("Влажность1 = "); client.print(Hr1); client.print(" %<br/>"); client.print("Температура2 = "); client.print(tempout2); client.print(" °C<br/>"); client.print("Влажность2 = "); client.print(Hr2); client.print(" %<br/>"); client.println("</html>"); } req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); break; } if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); } } void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } } char StrContains(char *str, char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; }
Откуда вы будете брать время? Тут ардуино сама предоставляет интерфейс к данным. И ваш совет можно реализовать только с помощью javascript со стороны клиента, отправляя ajax запросы к серверу, проверяя ответ на корректность, и уже после этого обновляя данные на странице, включая время. При этом надо не забыть написать на сервере обработчик ajax запросов, конечно.
Не надо так усложнять. 1.Раз уж Ардуина подключена к Ethernet, то почему бы не получить время из сети? Это сложно? Нет! 2.Если мы знаем текущее время, то мы можем зафиксировать момент времени приема данных от датчика. 3.Теперь мы можем в выходных данных добавить строчку, в которой указано время приема пакета данных от датчика. Таков мой план. И никаких javascript_ов, ajax_ов и прочих громких терминов, которыми вы так щедро все усложнили.