Нужна помощь со скетчем

Тема в разделе "Arduino & Shields", создана пользователем Максим_Николаевич, 28 ноя 2016.

  1. Доброе утро всем! Очень нужна помощь знатоков в завершении одного скетча под 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;
    }
     
  2. Tomasina

    Tomasina Сушитель лампочек Модератор

    при отваливании датчика какие оказания на входе?
     
  3. Тут дело не в показаниях. Датчик беспроводной по радиоканалу представляет из себя тиньку 13+ds18b20+STX882. Запитано это все от батарейки, точнее двух ААА. И вот если вдруг батарейка сдохла, то на принимающей ардуинке так и будут висеть последние принятые данные.
     
  4. как я понимаю в это вместо
    Код (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

    Осталось только программно это реализовать.
     
  5. Vetrinus

    Vetrinus Гик

    Ну я бы предположил, что проверку таймера нужно впихнуть перед сбросом данных, но здравый смысл возражает против такого решения. Из этого вопрос - в каком месте останавливается ваша программа?
     
  6. VITAL_P

    VITAL_P Нерд

    Можно организовать счетчик с помощью millis() типа :
    time = millis()/60000;
    и при отсутствии сигнала с датчика сохранить time в переменную, потом их сравнивать.
    и если разница достигнет 35 сбросить значения key1-key4
     
  7. AlexVS

    AlexVS Гик

    Можно к отображаемым данным, если это БД или просто веб-страничка, добавить параметр "Время приема последнего пакета от датчика".
    Тогда сразу будет видно, как давно ваш датчик отдавал данные.
     
    Последнее редактирование: 28 ноя 2016
  8. Прием данных на это закончился, далее отображение в сети. Полный код в первом посте.
     
  9. Vetrinus

    Vetrinus Гик

    В данном случае я бы сделал так:
    Код (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;
    }
     
  10. Vetrinus

    Vetrinus Гик

    Откуда вы будете брать время? Тут ардуино сама предоставляет интерфейс к данным. И ваш совет можно реализовать только с помощью javascript со стороны клиента, отправляя ajax запросы к серверу, проверяя ответ на корректность, и уже после этого обновляя данные на странице, включая время.
    При этом надо не забыть написать на сервере обработчик ajax запросов, конечно.
     
  11. AlexVS

    AlexVS Гик

    Не надо так усложнять.
    1.Раз уж Ардуина подключена к Ethernet, то почему бы не получить время из сети? Это сложно? Нет!
    2.Если мы знаем текущее время, то мы можем зафиксировать момент времени приема данных от датчика.
    3.Теперь мы можем в выходных данных добавить строчку, в которой указано время приема пакета данных от датчика.
    Таков мой план. И никаких javascript_ов, ajax_ов и прочих громких терминов, которыми вы так щедро все усложнили.
     
  12. Vetrinus

    Vetrinus Гик

    Вы правы, на счет NTP я не подумал, с ним реально проще будет.
     
  13. AlexVS

    AlexVS Гик

    Спасибо за понимание :)