http://lazysmart.ru/ - кто пробовал и какие аналоги есть в интернет*

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

http://lazysmart.ru/  ктонибудь пробовал  сервис и скетч оттуда?

#include <OneWire.h>  //Подключаем библиотеку для обмена с датчиком температуры
#include <avr/wdt.h>  //Подключаем библиотеку для использования сторожевого таймера

//----------------------------------Флаги -----------------------------------------
bool GPRS_connect=false;     //Флаг "Есть подключение к GPRS"
bool CSt_send_success=true;  //Флаг "Текущая команда реле передана успешно"
bool BT_send_success=true;   //Флаг "Значение текущей температуры передано успешно"
bool change_request = false; //Флаг "Запрос на сервер изменён". Устанавливается в момент когда необходимо отправить на сервер новые данные
bool blink_led;              //Флаг "Светодиод "В работе" горит"
//----------------------------------------------------------------------------------

//--------------------------------------
int Command;          //Содержит команду для реле, полученную от сервера
int Command_o=-1;     //Предыдущая команда для реле. Служит для фиксации факта изменения комады. Проинициализирована заведомо ложным значением -1
int term;             //Содержит последнее измеренное значение температуры
int term_o;           //Содержит предпоследнее измеренное значение температуры. Служит для фиксации факта изменения температуры.

int GET_step, GET_step_o;     //Текущий и предыдущий шаги посылки запроса серверу
int SRead_step, SRead_step_o; //Текущий и предыдущий шаги получения ответа от сервера
unsigned long Startup_time_s;     //Время с момента включения в секундах
unsigned long Last_succsess_time; //Время, последнего успешного обмена с сервером
unsigned long Last_blink_time;    //Время, последнего моргания светодиодом "В работе"

int DO=38;             //Номер пина, который управляет выходным реле
long int LOG=1234;     //Логин устройства. Его можно посмотреть в настройках устройства на сервисе LS Cloud
long int PAS=1111;     //Пароль устройства. Его можно посмотреть в настройках устройства на сервисе LS Cloud

OneWire  ds(42);      // Линия 1-Wire для опроса датчика температуры будет на пине 42
byte data[2];         // Массив для обмена с датчиком температуры


unsigned char Step;      //Номер шага, на котором находится основной цикл программы ("Отправка запроса на сервер", "Получение ответа от сервера", "Анализ системы")
String responce_status;  //Хранит статус обмена с модемом на текущем шаге
 
String Request;          //Хранит строку запроса на сервер
String Responce;         //Хранит строку ответа от сервера
String SIM_Data;         //Строка содержит символы, полученные от модема при "общении" с ним            

void setup()
{
 /* ----------------------Включаем сторожевой таймер на 8 секунд.---------------- */
 /* Сторожевой таймер служит для защиты контроллера от зависания.                 */
 /* Программа выполняется циклично и в каждом цикле производится сброс таймера.   */   
 /* Если контроллер зависнет, таймер не будет сброшен программно и через 8 секунд */
 /*  контроллер автоматически перезагрузится.                                     */
 wdt_enable(WDTO_8S);

 /*Формируем первичный запрос к серверу.                                     */
 /*Добавляем в параметры логин и пароль для авторизации устройства на сервере*/
 Request = "http://t.lazysmart.ru/device_status.php?LOG=";
 Request+=String(LOG);
 Request+="&PAS=";
 Request+=String(PAS);

 /*Инициализируем COM-порты*/
 Serial.begin(57600);                  // скорость обмена с отладочным портом 
 Serial1.begin(19200);                 // скорость обмена с модемом
 Serial1.setTimeout(1000);             // 1000 мс ждать данных от модема до генерации таймаута           

 /*Инициализируем порт, который управляет реле перезагрузки модема*/ 
 pinMode(48,OUTPUT);  //Для вкл./выкл. модема

 /*Инициализируем порты, к которым подлючены сигнальные светодиоды*/ 
 pinMode(49,OUTPUT);  //Для индикации "В работе". Моргает не чаще раза в секунду, если контроллер работает (т.е. не завис)
 pinMode(50,OUTPUT);  //Для индикации нового запроса. Загорается при каждом запросе и гаснет после получения ответа
 pinMode(52,OUTPUT);  //Для индикации подключения к GPRS

 /*Инициализируем порт, который управляет выходным реле*/ 
 pinMode(DO,OUTPUT);  //Дискретные выход

 digitalWrite(48,HIGH); //Подаём питание на модем
 digitalWrite(49,HIGH); //Начальное состояние светодиода "В работе": "горит"

 /*Запускаем модем*/
 powerUp();           //Запускаем GPRS-модем
 //---------------------------!ИНИЦИАЛИЗАЦИЯ ЗАВЕРШЕНА-----------------------------------------------------------------------------
 
 //---------------------------ПОДКЛЮЧЕНИЕ К GPRS-----------------------------------------------------------------------------------
 GPRS_Init();
}
 //--------------------------!ПОДКЛЮЧЕНИЕ К GPRS-----------------------------------------------------------------------------------

 //--------------------------------------ОСНОВНОЙ ЦИКЛ-----------------------------------------------------------------------------
void loop()
{    
  //Моргаем сетодиодом "В работе" не чаще раза в секунду
  if(blink_led && Last_blink_time - (millis()/1000) > 1){
    Last_blink_time = (millis()/1000);    //Время с момента последнего моргания 
    digitalWrite(49,LOW); //Переключаем светодиод "В работе"
    blink_led = false;
  }
  else if(Last_blink_time - (millis()/1000) > 1){
    Last_blink_time = (millis()/1000);    //Время с момента последнего моргания 
    digitalWrite(49,HIGH); //Переключаем светодиод "В работе"
    blink_led = true;
  }

  /*Главный цикл программы выполняется пошагово*/
  if(Step != ' '){
     switch(Step){
        /* На первом шаге отправляем запрос серверу */
        case '1': {                                       
                    digitalWrite(50,HIGH); //Зажигаем светодиод при отправке запроса
                    int SendStatus = SendGETRequest();
                    // Определяем статус отправки запроса
                    if(SendStatus==1){                      
                      Step = '2';   //Запрос успешно отправлен - переходим к следующему шагу
                    }
                    else if(SendStatus==-1){                      
                      SIM900_Reload();  //При отправке возникла критическая ошибка - нужно перезагрузить модем
                    }          
                  }
                  break; 
                  
        /* На втором шаге ожидаем ответ сервера */
        case '2': switch(WaitForResponce()){
                     case 0: {
                             break; //еще анализируем ответ от сервера
                     }
                     case 1: {
                            //Ответ получен успешно
                             PrintlnToSerial(Responce); //Посылаем текст ответа на отладочный порт  
                             digitalWrite(50,LOW);      //Гасим светодиод при успешном ответе
                             String S = AnalizeResponce("COMMAND"); //По кодовому слову "вычленяем" полезные данные из ответа                                                        
                             if(S != "NOT_STR"){
                                //Если ответ валиден и в нём найдены полезнае данные (команда устройству от сервера) - 
                                // то выполняем полученные команду, если она отлична от предыдущей
                                PerformCommands(S);
                             }
                             Step = '3'; //Переходим на следующий шаг
                             break; 
                     }
                     case -1:{
                             Step = '1';    //Возникла ошибка, вернул -1. Возвращаемся на предыдущий шаг для отправки нового запроса                            
                     }
                  }
                  break;

        /* На третьем шаге производится обмен с датчиком температуры (для получения её актуального значения),
           выполняются полученные от сервера команды и формируется новый запрос */          
        case '3': {
                     AnalizeSystem();                                      
                     Step = '1'; //Возвращаемся на первый шаг
                  }
     }           
  }
  
  //Сбрасываем сторожевой таймер на каждом цикле программы
  wdt_reset();
  
//-------------------------------------------Алгоритм "выживания" -----------------------------------------------------------------
/* Алгоритм выживания используется для предотвращения непредвиденных ситуаций в обмене с модемом.                                               */
/* Сбои программной логике модема, "мусор" полученный от сети и другие ситуации - могут привести к зависанию модема или его неадекватной работе */
/* Применяем простейший алгоритм "выживания" в таких ситуациях: если в течение 3-х минут от сервера не получено никаких полезных данных -      */
/* - перезагружаем модем                                                                                                                        */

  if(((millis()/1000) - Last_succsess_time) >180){ //Если в течение 3-х минут ни разу не получили полезные данные - перегружаем мождем
      PrintlnToSerial("Last_succsess_responce_time > 180 s. Reload modem..."); //Отправляем сообщение о перезагрузке в отладочный порт     
      SIM900_Reload(); //Перегружаем модем
  }
}
 //--------------------------------------!КОНЕЦ ОСНОВНОГО ЦИКЛА--------------------------------------------------------------------

/*------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция ConnectToGPRS()                                                                                */                  
/*           Производит подключение модема к GPRS и открывает HTTP-сеанс                                            */ 
/* Входы:    -----                                                                                                  */
/* Выходы:   Возвращает true в случае успешного подключения и false - в противном случае                            */  
/*------------------------------------------------------------------------------------------------------------------*/
bool ConnectToGPRS()
{  
 Startup_time_s = (millis()/1000);    //Время с момента включения в секундах.

 //Последовательно выполняем команды для подключения модема к GPRS и открытия HTTP-сеанса
 //После каждой команды ожидаем ответа в цикле while. 
 //Для избежания зависания на каждом цикле выполняем функцию SIM900_answ_test()

 Serial1.println("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"");
 while(!ShowSerialData("OK","ERROR")){if(!SIM900_answ_test()) return false;}
 if(responce_status == "OK")
 {
     Serial1.println("AT+SAPBR=3,1,\"APN\",\"internet\"");
     while(!ShowSerialData("OK","ERROR")){if(!SIM900_answ_test()) return false;}
     if(responce_status == "OK")
     {  
        while(1){
           delay(1000);
           Serial1.println("AT+SAPBR=1,1");  //модем может вернуть ERROR  
                                             //но это не ошибка, если продолжать запросы в конце концов может подключиться и вернуть ОК
                                             //поэтому если получаем ERROR - продолжаем посылать такие запросы                                             
           while(!ShowSerialData("OK","ERROR")){if(!SIM900_answ_test()) return false;}
           if(responce_status == "OK")
           { 
               Serial1.println("AT+HTTPINIT");
               while(!ShowSerialData("OK","ERROR")){if(!SIM900_answ_test()) return false;}
               if(responce_status == "OK")
               {
                   Serial1.println("AT+HTTPPARA=\"CID\",1");
                   while(!ShowSerialData("OK","ERROR")){if(!SIM900_answ_test()) return false;}
                   if(responce_status == "OK")
                   {
                         return true; //Сеанс обмена успешно открыт
                   }
               }
           } 
        }   
     }
 }     
 return false;
}

/*------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция ShowSerialData(String OK, String ERR)                                                          */                  
/*           Читает ответ от модема контроллеру по последовательному порту                                          */ 
/*           Когда ответ получен, функция записывает его в переменную responce_status                               */ 
/* Входы:    Принимает строку успешного ответа на команду и строку ответа-ошибки                                    */
/* Выходы:   Возвращает true если ответ получен(успешный или ошибка), false - ответ от модема еще анализируется     */ 
/*------------------------------------------------------------------------------------------------------------------*/
boolean ShowSerialData(String OK, String ERR)
{
   responce_status = "!";  //Инициализируем заведомо ложным значением
   if(Serial1.available())  //Если в порт уже пришли новые данные от модема
   {   
       Startup_time_s = (millis()/1000);    //Время с момента включения в секундах.
       while(Serial1.available())  //Пока не прочитаем то, что уже пришло
       {                        
          SIM_Data = Serial1.readStringUntil(char(13));     // читаем ответ до символа перевода на след. строку '\r'
          PrintlnToSerial(SIM_Data); //Посылаем в отладочный порт полученные данные             

          //Сравниваем полученные данные с кодом успешного ответа и ответа-ошибки
          if (SIM_Data.substring(SIM_Data.length()- OK.length()) == OK) 
          {
              responce_status = OK;   
              Serial1.flush();   //Ждём пока данные перестанут лететь и освобождаем буфер
              return true;          
          }
          else if (SIM_Data.substring(SIM_Data.length()- ERR.length()) == ERR)
          {
              responce_status = ERR;   
              Serial1.flush();   //Ждём пока данные перестанут лететь и освобождаем буфер
              return true;
          }
         //Если каким-то немыслимым образом тут зависли (данные из порта продолжают приходить),
         //выходом из цикла while будет подпрограмма защиты от зависания
         if(!SIM900_answ_test()) return false;                                                   
       }  
   } 
   
   else return false;  
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция WaitReadyToRead(String OK)                                                                      */
/*           Ждёт от модема приглашения прочитать данные, полученные от сервера.                                     */
/*           Когда приглашение получено, функция анализирует код ответа сервера (следует в той же строке после ","). */
/*           Если код ответа 200 - данные успешно получены. responce_status = "GOOD RESPONCE"                        */
/*           Если код ответа отличен от 200 - сервер ответил ошибкой. responce_status = "BAD RESPONCE"               */
/* Входы:    Принимает строку-приглашение от модема.                                                                 */
/* Выходы:   Возвращает true если ответ получен, false - ответ от модема еще ожидается                               */
/*-------------------------------------------------------------------------------------------------------------------*/
boolean WaitReadyToRead(String OK) 
{
   responce_status = "!";  //Инициализируем заведомо ложным значением
   if(Serial1.available())
   {   
       Startup_time_s = (millis()/1000);    //Время с момента включения в секундах.
       while(Serial1.available())  //Пока не прочитаем то, что уже пришло
       {                        
          SIM_Data = Serial1.readStringUntil(char(13));     // читаем ответ до символа перевода на след. строку '\r'
          PrintlnToSerial(SIM_Data);                        // Посылаем в отладочный порт полученные данные  
          if (OK.equals(SIM_Data.substring(1,OK.length()+1))){ //Если строка-приглашение получена, смотрим что идёт дальше
                                                               // - это код ошибки.
              if (SIM_Data.substring(OK.length()+1,OK.length()+4) == "200"){ 
                 //Если код ошибки 200 - обмен прошёл успешно
                 responce_status = "GOOD RESPONCE";   
                 Serial1.flush();   //Ждём пока данные перестанут лететь и освобождаем буфер
                 return true;
              }
              else{
                 //Если код ошибки не 200 - сервер ответил ошибкой
                 responce_status = "BAD RESPONCE";   
                 Serial1.flush();   //Ждём пока данные перестанут лететь и освобождаем буфер
                 return true;
              }
          }    
          //Если каким-то немыслимым образом тут зависли (данные из порта продолжают приходить),
          //выходом из цикла while будет подпрограмма защиты от зависания
          if(!SIM900_answ_test()) return false;
       }  
   } 
   
   else return false;  
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция ReadServerResponce()                                                                            */
/*           Читает данные полученные от сервера.                                                                    */
/*           Признаком конца сообщение служит строка "ОК"                                                            */
/* Входы:                                                                                                            */
/* Выходы:   Возвращает true если ответ получен, false - ещё читаем                                                  */
/*-------------------------------------------------------------------------------------------------------------------*/
boolean ReadServerResponce(){ 
   responce_status = "!";  //Инициализируем заведомо ложным значением
        
   if(Serial1.available()) {   
     Startup_time_s = (millis()/1000);    //Время с момента включения в секундах.       
     while(Serial1.available()){
        Responce=Serial1.readString();            
        if(Responce.substring(Responce.length()-4,Responce.length()-2) == "OK"){ // Ждём "ОК" в конце сообщения
            responce_status = "OK";
            return true;
        } 
        if(!SIM900_answ_test()) return false; //Если каким-то непостижимым образом тут повисли
     }        
   }
   return false; 
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция SendGETRequest()                                                                                */
/*           Посылает GET-запрос на сервер.                                                                          */
/*           Устанавливает responce_status = "ОК", при успешной передаче команды модему.                             */
/*           Устанавливает responce_status = "ERROR", если модем в процессе обмена ответил ошибкой.                  */
/* Входы:                                                                                                            */
/* Выходы:   Возвращает 1 если запрос передан, -1 - если в процессе передачи запроса модем ответил ошибкой, 0 - если */
/*           процесс передачи запроса на сервер ещё продолжается.                                                    */
/*-------------------------------------------------------------------------------------------------------------------*/
int SendGETRequest()
{
   responce_status = "!"; //Инициализируем заведомо ложным значением
   switch(GET_step) 
   {
     case 1:  //Передаём модему новый запрос для сервера
              Serial1.println("AT+HTTPPARA=\"URL\",\""+Request+"\""); //
              GET_step++;
              break;
     case 2:  //Читаем ответ модема на предыдущую команду 
              if(ShowSerialData("OK","ERROR"))
              {
                if(responce_status == "OK") GET_step++;
                else if(responce_status == "ERROR") {GET_step=1; return -1;}  
              }
              break;
     case 3:  //Командуем модему передать запрос на сервер
              Serial1.println("AT+HTTPACTION=0");
              GET_step++;
              break;
     case 4:  //Читаем ответ модема на предыдущую команду 
              if(ShowSerialData("OK","ERROR"))
              {
                 if(responce_status == "OK"){GET_step=3; return 1;}
                 else if(responce_status == "ERROR") {GET_step=1; return -1;} 
              }        
   } 
   return 0;   
}   

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция AnalizeResponce()                                                                               */
/*           Вычленяет из ответа сервера команду для выходного реле.                                                 */
/*           Команда следует в ответе за кодовым словом.                                                             */
/* Входы:    Принимает кодовое слово                                                                                 */
/* Выходы:   Возвращает строку, содержащую команду для выходного реле                                                */
/*-------------------------------------------------------------------------------------------------------------------*/
String AnalizeResponce(String Code_Str)  
{
   String OutStr;
   for(int i=Responce.length()-1; i > 0; i--)
   { 
         if(Responce[i] == Code_Str[0]) //Ищем в полученном от сервера ответе кодовое слово COMMAND начиная с конца.
         {                              //Если нашли первую букву кодового слова - проверяем дальше,
                                        //действительно ли это кодовое слово
            for(int j = i+1, k=1; k < Code_Str.length(); j++, k++)
            {
                if(Responce[j] != Code_Str[k]) //Если следующий символ не совпал
                {
                   k = Code_Str.length(); // выходим из перебора - это не то слово
                }
                else
                {
                   //Все символы совпали
                   if(k == Code_Str.length()-1) //значит это действительно кодовое слово - дальше идут полезнае данные
                   {
                        for(int  f=j+2; f<Responce.length() && Responce[f]!=(char)32; f++) //копируем строку с полезными данными
                        {
                            OutStr += (char)Responce[f];
                        }
                        Last_succsess_time = (millis()/1000); //Время с момента последнего успешного обмена с сервером
                        //Удаляем из запроса все передаваемые параметры
                        CSt_send_success=true; 
                        BT_send_success=true;
                        return OutStr;
                   }
                }  
            }
         }   
   }
   return "NOT_STR";
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: Функция WaitForResponce()                                                                               */
/*           Управляет процессом получения ответа от сервера.                                                        */
/* Входы:                                                                                                            */
/* Выходы:   Возвращает 1 - если получен успешный ответ, -1 - сервер ответил ошибкой, 0 - ответ еще не получен.      */
/*-------------------------------------------------------------------------------------------------------------------*/
int WaitForResponce() 
{ 
   responce_status = "!"; //Инициализируем заведомо ложным значением
   switch(SRead_step){
     case 1: if(WaitReadyToRead("+HTTPACTION:0,")){  //Ждём приглашения от SIM900 вида +HTTPACTION:0,<...>, 
                                                     //Приглашение означает, что сервер ответил
                                                     //После приглашения <...> - идет код ответа (200 - успешный ответ)
                if(responce_status == "GOOD RESPONCE"){
                   SRead_step++; //Если получен "хороший" ответ - двигаемся на шаг чтения данных
                }
                else if(responce_status == "BAD RESPONCE"){
                   SRead_step = 1;
                   return -1;   //Если получен "плохой" ответ - выходим из функции
                }
             }     
             break; 
     case 2: Serial1.println("AT+HTTPREAD"); //Команда модему SIM900 на выдачу ответа, полученного от сервера 
             SRead_step++;       
             break;      
     case 3: if(ReadServerResponce()){ //Читаем ответ сервера
                SRead_step = 1;
                return 1;
             }   
   } 
   return 0;
             
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: PerformCommands(String S)                                                                               */
/*           Меняет состояние выходного реле в соответствии с командой, полученной от сервера.                       */
/* Входы:    Принимает строку, содержащую команду для выходного реле.                                                */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void PerformCommands(String S)
{
   Command = S.toInt();  
   
   if(Command == 1){ 
      digitalWrite(DO,HIGH);
   }
   else{
      digitalWrite(DO,LOW);
   }   
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: AnalizeSystem()                                                                                         */
/*           Анализирует текущее состояние системы(температура, сотояние реле) и формирует новый запрос на сервер.   */
/* Входы:                                                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void AnalizeSystem(){
   BoardTermRead();  //Получаем от датчика текущую температуру
   int delta = term - term_o; //Вычисляем разницу между текущим и предыдущим значением температуры
   
   //Формируем очередной запрос
   //Удаляем все предыдущие передаваемые параметры из запроса                    
   Request = "http://t.lazysmart.ru/device_status.php?LOG=";
   Request+=String(LOG);
   Request+="&PAS=";
   Request+=String(PAS); 
   change_request = false;       
                                                        
   //Добавляем к запросу параметры, которые поменялись или не были успешно переданы 
   //Если состояние выходного реле изменилось, добавляем этот параметр в запрос - даст серверу понять,
   //что устройство приняло и выполнило команду
   if(Command != Command_o || !CSt_send_success){
      Request+="&CSt="+String(Command);
      CSt_send_success = false; //сбрасываем флаг успешной передачи параметра
      change_request=true;      //устанавливаем флаг "Запрос на сервер изменён"
   }
   //Если температура изменилась больше чем на 0.5 градуса, добавляем этот параметр в запрос
   if(abs(delta) > 5 || !BT_send_success){
         Request+="&BT="+String(term);
         term_o = term;           //приравниваем предыдущую температуру текущей
         BT_send_success = false; //сбрасываем флаг успешной передачи параметра
         change_request=true;     //устанавливаем флаг "Запрос на сервер изменён"
   }
   
   if(change_request){  
       GET_step=1;   //Если запрос поменялся                                               
   }      
   
   Command_o = Command; //Приравниваем предыдущую команду текущей
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: BoardTermRead()                                                                                         */
/*           Реализует обмен с датчиком температуры.                                                                 */
/* Входы:                                                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void BoardTermRead(){ 
   ds.reset();                 //сбрасываем линию
   ds.skip();                  //команда SKIP_ROM, т.к. на линии только один датчик
   ds.write(0x44,1);           // запускаем конвертацию
   delay(1000);
   ds.reset();                 //сбрасываем линию
   ds.skip();                  //команда SKIP_ROM, т.к. на линии только один датчик
   ds.write(0xBE);             // считываем ОЗУ датчика
   for (int i = 0; i < 2; i++) {  // читаем переданные датчиком 2 первых байта, содержащих информацию о температуре
      data[i] = ds.read();
   }    
   unsigned char znak = (data[1]&0xF8); //раскодируем знак температуры
   if(znak == 0xF8) {
      data[0] = ~data[0];  //побитово инвертируем полезные байты, если занк отрицательный
      data[1] = ~data[1];
   }                 
   unsigned char digit=data[0]>>4; //вычисляем целую часть
   digit|=(data[1]&0x7)<<4;        
   
   unsigned char decimal=(data[0]&0xf)>>2; //вычисляем дробную часть
   if(decimal==0x00) term = 0;
   if(decimal==0x01) term =3;
   if(decimal==0x02) term =5;
   if(decimal==0x03) term =8;

   //Сохраняем температуру в глобальную переменную
   term = 10*digit+term;  //объединяем целую и дробную части - получаем текущую температуру                        
   if(znak == 0xF8) term = -term; //Добавляем знак "-", если нужно
   Serial.print("Temperature=");  //Выводим в отладочный порт значение температуры
   Serial.println(term);
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: PrintlnToSerial(String S)                                                                               */
/*           Выводит строку в отладочный порт.                                                                       */
/* Входы:    Принимает строку для вывода.                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void PrintlnToSerial(String S)
{
    Serial.println(S);    
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: PrintlnToSerial(String S)                                                                               */
/*           Перезагружает модем SIM900.                                                                             */
/* Входы:                                                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void SIM900_Reload()
{   
    CSt_send_success=true; //Сбрасываем флаги успешной передачи параметров
    BT_send_success=true;
    digitalWrite(50,LOW); //Выключаем светодиод индикации запросов
    PrintlnToSerial("RELOAD..."); //Передаём сообщение о перезагрузке модема на отладочный порт
    digitalWrite(48,LOW);  //Снимаем питание с модема
    delay(1000);           //Выдерживаем паузу 1 с.
    digitalWrite(48,HIGH); //Подаём питание на модем
    
    wdt_reset(); //Сбрасываем сторожевой таймер
    powerUp();   //Подаём команду на включение модема 
    GPRS_Init(); //Инициализируем GPRS модема
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: GPRS_Init()                                                                                             */
/*           Ожидает готовности модема к работе. Управляет подключением модема к GPRS.                               */
/* Входы:                                                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void GPRS_Init()
{
   Startup_time_s = (millis()/1000);    //Инициализируем время с момента включения в секундах. 
   Last_blink_time = (millis()/1000);   //Инициализируем время крайнего моргания лампочки "Я жив"
   GPRS_connect=false;                  //Сбрасываем флаг "Есть подключение к GPRS"
   digitalWrite(52,LOW);   //GPRS не подключен - светодиод не горит
   while(!ShowSerialData("Call Ready","ERROR"))   //ждём пока модем ответит, что готов принимать АТ-команды
   {
        if(!SIM900_answ_test()) SIM900_Reload(); //Если не отвечает - перезагружаем     
   } 

   delay(3000); //Если ответил, что готов - делаем задержку на всякий пожарный
   
   while(!GPRS_connect)
   {
        GPRS_connect = ConnectToGPRS(); //Состояние флага "Есть подключение к GPRS" соответствует статусу подключения
        if(GPRS_connect==true)
        { 
             digitalWrite(52,HIGH); //GPRS  подключен - зажигаем светодиод
            
             GET_step=1, GET_step_o=1, SRead_step=1, SRead_step_o=1; //Начинаем сначала все этапы обмена
             PrintlnToSerial("Connected to GPRS");  //Сообщение в отладочный порт
             Step='1';                              //Начинаем основной цикл сначала
             Last_succsess_time = (millis()/1000);  //Инициализируем время последнего успешного обмена с сервером
        }   
        else
        {    //Не смог подключиться к GPRS
             PrintlnToSerial("Cannot connect to GPRS. Reload modem..."); //Сообщение в отладочный порт
             SIM900_Reload(); //Перезагружаем модем
        }
   }
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: SIM900_answ_test()                                                                                      */
/*           Функция используется в локальных циклах при обмене с модемом, когда время прохождения основного         */
/*           цикла увеличивается.                                                                                    */
/*           В таких случаях сторожевой таймер может быть не сброшен программно за необходимое время и контроллер    */
/*           перезагрузится аппаратно.                                                                               */
/*           Функция вместо глобального цикла продолжает моргать светодиодом "В работе" и сбрасывать                 */
/*           сторожевой таймер.                                                                                      */
/*           Если функция вызывается дольше 25 секунд - считаем что время обмена с модемом превышено, он             */
/*           завис и не отвечает (необходима перезагрузка).                                                          */
/* Входы:                                                                                                            */
/* Выходы:   Возвращает false, если время ожидания превышено и true - в противном случае.                            */
/*-------------------------------------------------------------------------------------------------------------------*/
boolean SIM900_answ_test(){
   //Моргаем сетодиодом "В работе" не чаще раза в секунду
   if(blink_led && Last_blink_time - (millis()/1000) > 1){
        Last_blink_time = (millis()/1000);    //Время с момента последнего моргания 
        digitalWrite(49,LOW); //Переключаем светодиод "В работе"
        blink_led = false;
   }
   else if(Last_blink_time - (millis()/1000) > 1){
        Last_blink_time = (millis()/1000);    //Время с момента последнего моргания 
        digitalWrite(49,HIGH); //Переключаем светодиод "В работе"
        blink_led = true;
   }

   //Сбрасываем сторожевой таймер
   wdt_reset();
  
   if((millis()/1000 - Startup_time_s)>25){ //Если функция вызывается дольше 25 секунд - считаем что время 
                                            //обмена с модемом превышено, он завис и не отвечает.
        PrintlnToSerial("Sim900 not answer. Reload modem..."); //Сообщение в отладочный порт
        return false;
   }
   return true;
}

/*-------------------------------------------------------------------------------------------------------------------*/
/* Описание: powerUp()                                                                                               */
/*           Подаёт последовательность импульсов на вход PWRKEY модема для его включения.                            */
/* Входы:                                                                                                            */
/* Выходы:                                                                                                           */
/*-------------------------------------------------------------------------------------------------------------------*/
void powerUp()
{
 PrintlnToSerial("Turn modem on");  //Сообщение в отладочный порт

 //Последовательность импульсов на вход PWRKEY модема SIM900
 pinMode(9, OUTPUT); 
 digitalWrite(9,LOW);
 delay(1000);
 digitalWrite(9,HIGH);
 delay(2000);
 digitalWrite(9,LOW);
 delay(3000);
 PrintlnToSerial("Modem power on"); //Сообщение в отладочный порт
}

 

b707
Offline
Зарегистрирован: 26.05.2017

Short Circuit, а при чем тут раздел "Проекты"?

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

это готовый проект. можете по ссылсе  сходить и посмотреть.

мне интересна модификация, и кто  пользовался тем сервером.

http://lazysmart.ru/nabor-konstruktor-dlya-interneta-veshhej-iot-ls-moni... - могу выложить переделаный скетч под уно.

 

 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

IoT со String? Really?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Short Circuit пишет:

это готовый проект. можете по ссылсе  сходить и посмотреть.

мне интересна модификация, и кто  пользовался тем сервером.

http://lazysmart.ru/nabor-konstruktor-dlya-interneta-veshhej-iot-ls-moni... - могу выложить переделаный скетч под уно.

 

 

Чтоб вы поняли масштаб кривизны кода, приведу пример: вот уже недели три занимаемся отладкой кода и железки с заказчиком, добиваемся почти абсолютной надёжности и круглосуточной работы, в связи с кучей хотелок заказчика уменьшил код с 70 % до 40, иначе ничего не влезет....я к тому что если вы думаете что данный код со String будет долго и хорошо работать то вы сильно ошибаетесь, мало строк инициализации, в случае оперативной замены работать не будет, никаких delay в принципе не должно быть иначе никуда уже саму логику программы не впихнете.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

код выше - для меги.

Есть примеры скетчей "правильного" кода  без String? 

любопытно посмотреть.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Short Circuit пишет:

код выше - для меги.

Есть примеры скетчей "правильного" кода  без String? 

любопытно посмотреть.

Да пожалуйста, не жалко, не претендую на совсем правильность, но работает, ещё добавил работу с gprs и dtmf, засунул все строки в progmem и ещё кучу улучшений, но извините это код заказчика и он за него заплатил, выложить окончательный вариант не могу

http://arduino.ru/forum/proekty/ocherednaya-temperaturnaya-signalizatsiy...

b707
Offline
Зарегистрирован: 26.05.2017

Short Circuit, код полное Г. и вряд ли стоит "пробовать" этот проект. В коде, кроме String - невероятное количество делеев, так что при попытке подгрузить эти процедуры в собственный проект вы огребете кучу проблем. Процедура измерения температуры со "знаменитой" задержкой в секунду - так писать просто стыдно.

Ребята, судя по всему, просто набрали куски кода в инете, не особо разбираясь, как они работают.

Short Circuit пишет:

Есть примеры скетчей "правильного" кода  без String? 

вы сомневаетесь, что это можно было написать на char array ? - зря.

Код будет точно меньше и несравненно эффективнее.

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

я не сомневаюсь, я точно знаю, что еще мало знаю..

Поэтому спросил - покажите реальные примеры кода. Я войду в курс дела, изучу, сделаю как мне нужно и буду использовать.

ЗЫ: String  я успешно использую, ничего не зависает(оптимизировал как умел)

в итоге скетчи под 1000 строк занимает к примеру до 31кб флеш, и до 35-40% ! памяти.  

Там не все идеально конечно, но хотелось бы научится всячески парсить уже принятые char строки  - не используя String, буду признателен за такие примеры.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Э....берете пример выше, там тупо процедура поиска постройки и парсите на здоровье

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

ааа... понял куда смотреть.. спасибо.