Sim800l и ардуино перестает принимать и отправлять смс

Всем доброго времени суток.Собрал девайс для управления отоплением на sim800l и ардуино уно.Код позаимствовал в сети,немного подкорректировал под свои нужды и вылезшие косяки.Все хорошо работает около 2х недель,потом перестает принимать и отправлять смс,хотя SIM800 мерцает 1 раз как при нормальной работе,ардуино продолжает выполнять программу.помогает только выкл питания и вкл, и опять на 2 недели± хватает.впечатление,где-то заполняется память,Помогите,пожалуйста.


#include "SoftwareSerial.h"
#include "SimpleDHT.h"
#include <OneWire.h>
#define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное
OneWire sensDs (A0);  // датчик подключен к выводу 14
byte bufData[9];  // буфер данных
int p8 = 11, t_1 = 0, pinDHT11 = 15, humidity = 0, msgphone = 0;
SimpleDHT11 dht11(pinDHT11);
SoftwareSerial SIM800(2, 3); //программные RX, TX для связи с модулем SIM800L
unsigned long timing1, timing2, timing3, timing4, timing5, timing6, timing7, timing8, timing9, timing10, timing11;
// Перемен. для хранения точки отсчета для таймеров
int j = 0, k = 0, a = 0, x2 = 20,r = 0, v = 0, w = 0;
String _response = "";                          // Переменная для хранения ответа модуля
long lastUpdate = millis();                     // Время последнего обновления
long updatePeriod = 60000;                      // Проверять каждую минуту
String phones = "...."; //Список разрешенных номеров
                   //номера вписываются в международном формате начиная с +
String waitResponse() {                  // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                     // Переменная для хранения результата
  long _timeout = millis() + 10000;      // Переменная для отслеживания тайм аута (10 секунд)
  while (!SIM800.available() && millis() < _timeout) {};// Ждем ответа 10 секунд, если пришел ответ или наступил тайм аут, то...
  if (SIM800.available()) {              // Если есть, что считывать
    _resp = SIM800.readString();         //считываем и запоминаем
  } else {                               // Если пришел тайм аут, то
    Serial.println("Timeout...");        //оповещаем об этом и
  } return _resp;                        //возвращаем результат. Пусто, если проблема
}
String sendATCommand(String cmd, bool waiting) {
  String _resp = "";            // Переменная для хранения результата
  Serial.println(cmd);          // Дублируем команду в монитор порта
  SIM800.println(cmd);          // Отправляем команду модулю
  if (waiting) {                // Если необходимо дождаться ответа
    _resp = waitResponse();     // ждем, когда будет передан ответ
    // Если Echo Mode выключен (ATE0), то эти 3 строки можно за комментировать
    if (_resp.startsWith(cmd)) { // Убираем из ответа дублирующую команду
      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
    }
    Serial.println(_resp);  // Дублируем ответ в Serial
  } return _resp;           // Возвращаем результат. Пусто, если проблема
  
}
void parseSMS(String msg) { // Парсим SMS
  String msgheader = "";
  String msgbody = "";
  String msgphone = "";
  msg = msg.substring(msg.indexOf("+CMGR: "));
  msgheader = msg.substring(0, msg.indexOf("\r")); // Выдергиваем телефон
  msgbody = msg.substring(msgheader.length() + 2);
  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));// Выдергиваем текст SMS
  msgbody.trim();
  int firstIndex = msgheader.indexOf("\",\"") + 3;
  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
  msgphone = msgheader.substring(firstIndex, secondIndex);
  Serial.println("Phone: " + msgphone);  // Выводим номер телефона
  Serial.println("Message: " + msgbody); // Выводим текст SMS
  if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1) { // Если телефон в белом списке, то
    if (msgbody == "Pr0") {
      j = 0;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr1") {
      j = 1;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr2") {
      j = 2;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr3") {
      j = 3;
    }
    if (msgbody == "Pr20") {
      j = 4;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Ktr") {
      k = 1;
    }
    if (msgbody == "Klx2+") {
      x2 = x2 + 3;
    }
    if (msgbody == "Klx2-") {
      x2 = x2 - 3;
    }
      if (msgbody == "Al-of") {
      w = 2;
    }
        if (msgbody == "Al-on") {
      w = 0;
    }
  } else {
    Serial.println("Unknown phonenumber");
  }
}
void setup() {
  
  pinMode(12, OUTPUT);
  pinMode(p8, OUTPUT);
  digitalWrite(12, LOW);
  digitalWrite(p8, LOW);
  pinMode(7, INPUT);
  Serial.begin(9600); // Скорость обмена данными с компьютером
  SIM800.begin(9600); // Скорость обмена данными с модемом
  Serial.println("Start!");
  analogReference(INTERNAL);
  sendATCommand("AT", true);                   // Отправили AT для настройки скорости обмена данными
  sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все SMS, чтобы не забивать память
  sendATCommand("AT+CMGF=1;&W", true);         // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
  lastUpdate = millis(); // Обнуляем таймер
}
bool hasmsg = false;                           // Флаг наличия сообщений к удалению
void loop() {
  int sensorVal = digitalRead(7);
 
  if (sensorVal == HIGH) {
 
    v = 220;
  } else {
    v = 0;
  }
  if (millis() - timing9 > 60000) {
    timing9 = millis();
       sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  sensDs.write(0x44, POWER_MODE); // инициализация измерения
  delay(6000);  // пауза 0,9 сек
  sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
  sensDs.read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов
  if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
    // данные правильные
    t_1=  ((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;     
  }
  else { 
    // ошибка CRC, отображается ----   
  }   
    byte temperature = 0;
    byte humidity = 0;
    dht11.read(&temperature, &humidity, NULL);
    Serial.print("T1 = "); Serial.print(t_1); Serial.print("*C, ");
    Serial.print("T2 = "); Serial.print((int)temperature); Serial.print("*C, ");
    Serial.print((int)humidity); Serial.println("%");
  }
  if (lastUpdate + updatePeriod < millis() ) {                     // Пора проверить наличие новых сообщений
    do {
      _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true ); // Отправляем запрос чтения непрочитанных сообщений
      if (_response.indexOf("+CMGL: ") > -1) {                     // Если есть хоть одно, получаем его индекс
        int msgIndex = _response.substring( _response.indexOf ("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
        char i = 0; // Объявляем счетчик попыток
        do {
          i++; // Увеличиваем счетчик
          _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true); // Пробуем получить текст SMS по индексу
          _response.trim();                // Убираем пробелы в начале/конце
          if (_response.endsWith("OK")) {  // Если ответ заканчивается на "ОК"
            if (!hasmsg) hasmsg = true;    // Ставим флаг наличия сообщений для удаления
            sendATCommand("AT+CMGR=" + (String)msgIndex, true); // Делаем сообщение прочитанным
            sendATCommand("\n", true);     // Перестраховка - вывод новой строки
            parseSMS(_response);           // Отправляем текст сообщения на обработку
            break; // Выход из do
          } else { // Если сообщение не заканчивается на OK
            Serial.println ("Error");//ошибка
            sendATCommand("\n", true); // Отправляем новую строку и повторяем попытку
            }
        }
        while (i < 10); break;
      } else {
        lastUpdate = millis();         // Обнуляем таймер
        if (hasmsg) {
          sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все прочитанные сообщения
          hasmsg = false;
        } break;
      }
    } while (1);
  }
  if (SIM800.available()) {     // Если модем, что-то отправил
    _response = waitResponse(); // Получаем ответ от модема для анализа
    _response.trim();           // Убираем лишние пробелы в начале и конце
    Serial.println(_response);  // Если нужно выводим в монитор порта
    if (_response.indexOf("+CMTI:") > -1) { // Пришло сообщение об отправке SMS
      lastUpdate = millis() - updatePeriod; // Теперь нет необходимости обрабатывать SMS здесь, достаточно просто сбросить счетчик авто проверки, и в следующем цикле все будет обработано
    }
  }
  if (Serial.available()) {      // Ожидаем команды по Serial
    SIM800.write(Serial.read()); //и отправляем полученную команду модему
  };
  if (j == 0) { //Программа 0
    digitalWrite(p8, HIGH);
  } else {
    digitalWrite(p8, LOW);
  }
  if (j == 1) { //Программа 1
    if (millis() - timing1 > 12600000) { //3 часа 30 минут = 12600000 мс
      timing1 = millis(); timing2 = millis();
      digitalWrite(12, HIGH);
    }
    if (millis() - timing2 > 1800000) { // 30 минут = 1800000 мс
      digitalWrite(12, LOW);
    }
    if (millis() - timing6 > 3000) {
      timing6 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  }
  if (j == 2) { //Программа 2
    if (millis() - timing3 > 23400000) { // 6 часа 30 минут = 23400000 мс
      timing3 = millis(); timing4 = millis(); digitalWrite(12, HIGH);
    }
    if (millis() - timing4 > 1800000) {  // 30 минут = 1800000 мс
      digitalWrite(12, LOW);
    }
    if (millis() - timing7 > 3000) {
      timing7 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  }
  if (j == 3) {
    digitalWrite(12, HIGH); //Программа 3
    if (millis() - timing8 > 3000) {
      timing8 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  } a = j;
  if (j == 4) {
    a = 20; //Программа 4
    if (millis() - timing5 > 3000) {
      timing5 = millis();
      byte temperature = 0;
      byte humidity = 0;
      dht11.read(&temperature, &humidity, NULL);
      if ((int)temperature <= x2) {
        digitalWrite(12, HIGH);
      }
      if ((int)temperature > x2) {
        digitalWrite(12, LOW);
      }
    }
    if (millis() - timing8 > 3000) {
      timing8 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
      }
    }
     if (r== 5) { //Программа 1
    if (millis() - timing10 > 3600000) { //3 часа 30 минут = 12600000 мс
      timing10 = millis();
      SIM800.println( "AT+CPOWD=1");
    }
 
  } else {
    a = j;
  }
  if (k == 1) {
    delay(300);
    byte temperature = 0;
    byte humidity = 0;
    dht11.read(&temperature, &humidity, NULL); delay(300);
    SIM800.println( "AT+CMGS=\....\""); //номер на который будет приходить SMS отчет
    delay(3000);                                //номер вписывается в международном формате начиная с +
    SIM800.print("T1=");
    delay(300); SIM800.print(t_1);
    delay(300); SIM800.print("*C, T2=");
    delay(300); SIM800.print((int)temperature);
    delay(300); SIM800.print("*C, T2-VL=");
    delay(300); SIM800.print((int)humidity);
    delay(300); SIM800.print("% Pr="); delay(300); SIM800.print(a);
    delay(300); SIM800.print(" t=");
    delay(300); SIM800.print(x2);
    delay(300); SIM800.print(" Set=");
    delay(300); SIM800.print(v);
    delay(300); SIM800.print("volt");
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } k = 0;
     if ((millis() - timing11 > 1800000)&&(t_1<=15)&&(w == 0)) {
      timing11 = millis(); 
    delay(300);
     
    SIM800.println( "AT+CMGS=\....\""); //номер на который будет приходить SMS отчет
    delay(3000);SIM800.print("T1=");
    delay(300); SIM800.print(t_1);
    delay(300); SIM800.print("ALARM");
   
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } 
    if ((millis() - timing11 > 1800000)&&(sensorVal == LOW)&&(w == 0)) {
      timing11 = millis(); 
    delay(300);
     
    SIM800.println( "AT+CMGS=\....\""); //номер на который будет приходить SMS отчет
  
    delay(300); SIM800.print("Set=ALARM");
   
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } 
    r = 5;
}

№1

Строки №№20-21 являются бредом сивой кобылы. Переменная _timeout локальна и всегда получает значение, зависящее от свежего миллис. На лицо опасность переполнения.

№2

Вообще, вся работа с миллис написана в корне неправильно. Во-первых с переполнением, а во вторых - в знаковых переменных.

Код просто обязан вешаться раз в три недели.

Вы пишете:

Точно не трёх? Если трёх, то ничего удивительного он (код) так написан.

Возможно (и даже наверняка) есть и другие косяки, но сначала исправьте эти – потом будем смотреть дальше.

Спасибо.Буду изучать и ковырять миллис.
По поводу 2х недель- в последний раз дней 10 было.
Подскажите,пожалуйста,откуда 3 недели? это можно в коде найти?

Конечно можно. Три недели (примерно) это 2 147 483 648 миллисекунд – т.е. максимальное число типа long, который Вы зачем-то используете при работе с millis.

Зачем, кстати? Чтобы по граблям оттоптаться? Запомните, никогда (от слова совсем никогда, ну, вот, совсем-совсем!!!) не смешивайте в одном выражении знаковые и беззнаковые величины. Если уж millis имеет тип unsigned long, так и переменные для работы с нею используйте типа unsigned long. См. подробности и примеры.

Далее, если у Вас нет цели добавить в свою жизнь веселья и драйва, никогда не определяйте конец интервала сложением с millis! Используйте только вычитание. Вычитайте из текущего millis стартовое (ранее запомненное) и сравнивайте с длительность интервала. Только так! Это должно быть на подкорке, просто руки должны сами писать только так и никогда так, как Вы. См. подробности и примеры.

2 лайка

Премного благодарен за внимание и ответ от слова ПРЕМНОГО.
2 месяца колдую грешил на память модуля и симки .
Еще раз спасибо за необходимый вектор.
По результатам ,обязательно ,отпишусь.

Этими словами, чаще всего, заканчивается большинство тем на форумах )))

Учитывая специфику ошибки,и мою недостаточную компетентность,мне до необходимого результата два локтя по карте и ещё не один визит сюда)))


#include "SoftwareSerial.h"
#include "SimpleDHT.h"
#include <OneWire.h>
#define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное
OneWire sensDs (A0);  // датчик подключен к выводу 14
byte bufData[9];  // буфер данных
int p8 = 11, t_1 = 0, pinDHT11 = 15, humidity = 0, msgphone = 0;
SimpleDHT11 dht11(pinDHT11);
SoftwareSerial SIM800(2, 3); //программные RX, TX для связи с модулем SIM800L
unsigned long timing1, timing2, timing3, timing4, timing5, timing6, timing7, timing8, timing9, timing10, timing11, lastUpdate;// Перемен. для хранения точки отсчета для таймеров
int j = 0, k = 0, a = 0, x2 = 20,r = 0, v = 0, w = 0;
String _response = ""; // Переменная для хранения ответа модуля
String phones = "...."; //Список разрешенных //номера вписываются в международном формате начиная с +
String waitResponse() {                  // Функция ожидания ответа и возврата полученного результата
  String _resp = "";                     // Переменная для хранения результата
  while (!SIM800.available()) {};// Ждем ответа, если пришел ответ или наступил тайм аут, то...
  if (SIM800.available()) {              // Если есть, что считывать
    _resp = SIM800.readString();         //считываем и запоминаем
  } else {                               // Если пришел тайм аут, то
    Serial.println("Timeout...");        //оповещаем об этом и
      } return _resp;                        //возвращаем результат. Пусто, если проблема
}
String sendATCommand(String cmd, bool waiting) {
  String _resp = "";            // Переменная для хранения результата
  Serial.println(cmd);          // Дублируем команду в монитор порта
  SIM800.println(cmd);          // Отправляем команду модулю
  if (waiting) {                // Если необходимо дождаться ответа
    _resp = waitResponse();     // ждем, когда будет передан ответ
    // Если Echo Mode выключен (ATE0), то эти 3 строки можно за комментировать
    if (_resp.startsWith(cmd)) { // Убираем из ответа дублирующую команду
      _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2);
    }
    Serial.println(_resp);  // Дублируем ответ в Serial
  } return _resp;           // Возвращаем результат. Пусто, если проблема
  
}
void parseSMS(String msg) { // Парсим SMS
  String msgheader = "";
  String msgbody = "";
  String msgphone = "";
  msg = msg.substring(msg.indexOf("+CMGR: "));
  msgheader = msg.substring(0, msg.indexOf("\r")); // Выдергиваем телефон
  msgbody = msg.substring(msgheader.length() + 2);
  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));// Выдергиваем текст SMS
  msgbody.trim();
  int firstIndex = msgheader.indexOf("\",\"") + 3;
  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
  msgphone = msgheader.substring(firstIndex, secondIndex);
  Serial.println("Phone: " + msgphone);  // Выводим номер телефона
  Serial.println("Message: " + msgbody); // Выводим текст SMS
  if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1) { // Если телефон в белом списке, то
    if (msgbody == "Pr0") {
      j = 0;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr1") {
      j = 1;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr2") {
      j = 2;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Pr3") {
      j = 3;
    }
    if (msgbody == "Pr20") {
      j = 4;
      digitalWrite(12, LOW);
    }
    if (msgbody == "Ktr") {
      k = 1;
    }
    if (msgbody == "Klx2+") {
      x2 = x2 + 3;
    }
    if (msgbody == "Klx2-") {
      x2 = x2 - 3;
    }
      if (msgbody == "Al-of") {
      w = 2;
    }
        if (msgbody == "Al-on") {
      w = 0;
    }
  } else {
    Serial.println("Unknown phonenumber");
  }
}
void setup() {
  
  pinMode(12, OUTPUT);
  pinMode(p8, OUTPUT);
  digitalWrite(12, LOW);
  digitalWrite(p8, LOW);
  pinMode(7, INPUT);
  Serial.begin(9600); // Скорость обмена данными с компьютером
  SIM800.begin(9600); // Скорость обмена данными с модемом
  Serial.println("Start!");
  analogReference(INTERNAL);
  sendATCommand("AT", true);                   // Отправили AT для настройки скорости обмена данными
  sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все SMS, чтобы не забивать память
  sendATCommand("AT+CMGF=1;&W", true);         // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)!
  lastUpdate = millis(); // Обнуляем таймер
}
bool hasmsg = false;                           // Флаг наличия сообщений к удалению
void loop() {
  int sensorVal = digitalRead(7);
 
  if (sensorVal == HIGH) {
 
    v = 220;
  } else {
    v = 0;
  }
  if (millis() - timing9 > 60000) {
    timing9 = millis();
       sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM
  sensDs.write(0x44, POWER_MODE); // инициализация измерения
  delay(6000);  // пауза 0,9 сек
  sensDs.reset();  // сброс шины
  sensDs.write(0xCC, POWER_MODE); // пропуск ROM 
  sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика 
  sensDs.read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов
  if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
    // данные правильные
    t_1=  ((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;     
  }
  else { 
    // ошибка CRC, отображается ----   
  }   
    byte temperature = 0;
    byte humidity = 0;
    dht11.read(&temperature, &humidity, NULL);
    Serial.print("T1 = "); Serial.print(t_1); Serial.print("*C, ");
    Serial.print("T2 = "); Serial.print((int)temperature); Serial.print("*C, ");
    Serial.print((int)humidity); Serial.println("%");
  }
  if (millis() - lastUpdate > 60000) {                     // Пора проверить наличие новых сообщений
    do {
      _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true ); // Отправляем запрос чтения непрочитанных сообщений
      if (_response.indexOf("+CMGL: ") > -1) {                     // Если есть хоть одно, получаем его индекс
        int msgIndex = _response.substring( _response.indexOf ("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
        char i = 0; // Объявляем счетчик попыток
        do {
          i++; // Увеличиваем счетчик
          _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true); // Пробуем получить текст SMS по индексу
          _response.trim();                // Убираем пробелы в начале/конце
          if (_response.endsWith("OK")) {  // Если ответ заканчивается на "ОК"
            if (!hasmsg) hasmsg = true;    // Ставим флаг наличия сообщений для удаления
            sendATCommand("AT+CMGR=" + (String)msgIndex, true); // Делаем сообщение прочитанным
            sendATCommand("\n", true);     // Перестраховка - вывод новой строки
            parseSMS(_response);           // Отправляем текст сообщения на обработку
            break; // Выход из do
          } else { // Если сообщение не заканчивается на OK
            Serial.println ("Error");//ошибка
            sendATCommand("\n", true); // Отправляем новую строку и повторяем попытку
            }
        }
        while (i < 10); break;
      } else {
        lastUpdate = millis();         // Обнуляем таймер
        if (hasmsg) {
          sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все прочитанные сообщения
          hasmsg = false;
        } break;
      }
    } while (1);
  }
  if (SIM800.available()) {     // Если модем, что-то отправил
    _response = waitResponse(); // Получаем ответ от модема для анализа
    _response.trim();           // Убираем лишние пробелы в начале и конце
    Serial.println(_response);  // Если нужно выводим в монитор порта
    if (_response.indexOf("+CMTI:") > -1) { // Пришло сообщение об отправке SMS
      lastUpdate = millis(); // Теперь нет необходимости обрабатывать SMS здесь, достаточно просто сбросить счетчик авто проверки, и в следующем цикле все будет обработано
    }
  }
  if (Serial.available()) {      // Ожидаем команды по Serial
    SIM800.write(Serial.read()); //и отправляем полученную команду модему
  };
  if (j == 0) { //Программа 0
    digitalWrite(p8, HIGH);
  } else {
    digitalWrite(p8, LOW);
  }
  if (j == 1) { //Программа 1
    if (millis() - timing1 > 12600000) { //3 часа 30 минут = 12600000 мс
      timing1 = millis(); timing2 = millis();
      digitalWrite(12, HIGH);
    }
    if (millis() - timing2 > 1800000) { // 30 минут = 1800000 мс
      digitalWrite(12, LOW);
    }
    if (millis() - timing6 > 3000) {
      timing6 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  }
  if (j == 2) { //Программа 2
    if (millis() - timing3 > 23400000) { // 6 часа 30 минут = 23400000 мс
      timing3 = millis(); timing4 = millis(); digitalWrite(12, HIGH);
    }
    if (millis() - timing4 > 1800000) {  // 30 минут = 1800000 мс
      digitalWrite(12, LOW);
    }
    if (millis() - timing7 > 3000) {
      timing7 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  }
  if (j == 3) {
    digitalWrite(12, HIGH); //Программа 3
    if (millis() - timing8 > 3000) {
      timing8 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
    }
  } a = j;
  if (j == 4) {
    a = 20; //Программа 4
    if (millis() - timing5 > 3000) {
      timing5 = millis();
      byte temperature = 0;
      byte humidity = 0;
      dht11.read(&temperature, &humidity, NULL);
      if ((int)temperature <= x2) {
        digitalWrite(12, HIGH);
      }
      if ((int)temperature > x2) {
        digitalWrite(12, LOW);
      }
    }
    if (millis() - timing8 > 3000) {
      timing8 = millis();
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW); delay(300);
      digitalWrite(p8, HIGH); delay(100); digitalWrite(p8, LOW);
      }
    }
     if (r== 5) { //Программа 1
    if (millis() - timing10 > 3600000) { //3 часа 30 минут = 12600000 мс
      timing10 = millis();
      SIM800.println( "AT+CPOWD=1");
    }
 
  } else {
    a = j;
  }
  if (k == 1) {
    delay(300);
    byte temperature = 0;
    byte humidity = 0;
    dht11.read(&temperature, &humidity, NULL); delay(300);
    SIM800.println( "AT+CMGS=\"....\""); //номер на который будет приходить SMS отчет
    delay(3000);                                //номер вписывается в международном формате начиная с +
    SIM800.print("T1=");
    delay(300); SIM800.print(t_1);
    delay(300); SIM800.print("*C, T2=");
    delay(300); SIM800.print((int)temperature);
    delay(300); SIM800.print("*C, T2-VL=");
    delay(300); SIM800.print((int)humidity);
    delay(300); SIM800.print("% Pr="); delay(300); SIM800.print(a);
    delay(300); SIM800.print(" t=");
    delay(300); SIM800.print(x2);
    delay(300); SIM800.print(" Set=");
    delay(300); SIM800.print(v);
    delay(300); SIM800.print("volt");
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } k = 0;
     if ((millis() - timing11 > 1800000)&&(t_1<=15)&&(w == 0)) {
      timing11 = millis(); 
    delay(300);
     
    SIM800.println( "AT+CMGS=\"....\""); //номер на который будет приходить SMS отчет
    delay(3000);SIM800.print("T1=");
    delay(300); SIM800.print(t_1);
    delay(300); SIM800.print("ALARM");
   
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } 
    if ((millis() - timing11 > 1800000)&&(sensorVal == LOW)&&(w == 0)) {
      timing11 = millis(); 
    delay(300);
     
    SIM800.println( "AT+CMGS=\"....\""); //номер на который будет приходить SMS отчет
  
    delay(300); SIM800.print("Set=ALARM");
   
    delay(300); SIM800.print((char)26);//команда для отправки SMS
    delay(300); Serial.println("SMS send finish");
  } 
    r = 5;
}

Доброго времени суток.Так ,вроде,по проще и пока работает.
Буду наблюдать.
Если есть явные косяки,прошу ткнуть носом.
Спасибо

Конечно, есть, куда ж они денутся.

№1
Строка №17. Проверка условия лишняя. Если бы оно было неверно, то программа не вышла бы из строки №16. А уж если вышла, то чего проверять, понятно, что там что-то есть.

№2
Строка №18. Пока Вы убедились лишь в том, что пришёл один байт. Ниоткуда не следует, что строка пришла целиком, а Вы кидаетесь её читать. Правда, она (функция чтения) и сама умная, может немножко подождать, но Вы не установили таймаут и надеетесь на умолчательный. А Вы знаете какой он там? Я бы так не читал. Это просто как закрыть себе глаза и надеяться, что пронесёт.

№3
Строки №№ 23 и 37. Каждый раз при входе в эти функции Вы создаёте новые копии строк-параметров (cmd и msg соответственно), т.е. запрашиваете новую память и копируете туда строку. Вы уверены, что это то, чего Вы хотели? Почему не пользоваться уже готовой переданной строкой, зачем запрашивать память и создавать новую?
Да, я вижу, что в случае с msg это “оправдано”, т.к. Вы “портите” её внутри функции. Но, неужели это Вам так необходимо? Ну, а в случае с cmd никакого оправдания созданию копии нет.

Замечания о комментариях

Я не могу посмотреть на логику парсинга потому, что Вы наплодили огромное количество бессмысленных комментариев (например: “Дублируем команду в монитор порта” – но это же очевидно из кода, зачем это писать?), но при этом не привели осмысленные. Например, нигде не описан формат принимаемой строки, а потому я не могу понять правильно ли Вы её парсите.

Кроме того, комментарий должен помогать читать и понимать текст. У Вас же иногда создаётся впечатление, что комментарии стоят для того, чтобы врагов запутать. Например, в строке №121 в комментарии написана просто брехня. Кого обманываем?

Замечание о переменных

Строка №11. Если бы это была студенческая работа, я бы дальше этой строки не проверял, завернул бы сразу. Однобуквенные имена глобальных переменных – это такой говнокод, что остальное можно и не смотреть.

Имена переменных у Вас “неговорящие” и, кстати, объявления переменных не прокомментированы. Ну, вот, Вы уверены, что через полгода Вы вспомните какие именно интервалы хранят переменные: timing1, timing2, timing3, timing4, timing5, timing6, timing7, timing8, timing9, timing10 и timing11. Уверен, что нет и даже не спорьте. Думаю, что Вы и сейчас-то их путаете. Вот тут (в плюс к “говорящему” имени) не помешал бы комментарий при объявлении каждой, но с информативными комментариями у Вас напряг, как я уже писал.

Переменная, особенно глобальная, должна в своём имени нести информацию о том, что она хранит. Запомните слова Владимира Владимировича:

Если тебе “корова” имя,
У тебя должно быть молоко и вымя.
А если нет ни молока, ни вымени,
То чёрта-ль в твоём коровьем имени.

И всегда называйте переменные так, чтобы было понятно что в них хранится.

Вообще, у Вас неоправданно много глобальных переменных. Это делает программу трудночитаемой, трудноотлаживаемой и, скорее всего “странно-глючной”. Например, bufData используется только в одной функции loop, так какого хрена Вы сделали её глобальной и видимой из всех функций? Это касается большинства Ваших глобальных переменных.

=================

Больше пока не смотрел, попробую вернуться попозже. Но смотреть очень трудно – программа просто “бессистемно” написана. Если бы Вы поделились внятным описанием задачи, я подсказал бы как её “системно” писать, чтобы и читать и отлаживать было легче.

1 лайк

Спасибо.коментарии поправлю.(код правлю,а комментарии нет)поэтому и путаница.
Код “лёг” через 10часов.
Будем дальше "курить"матчасть.
СПАСИБО.

Найдите у себя файл WString.cpp. У меня он расположен:

C:\Users\Eugene\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino

Найдите у себя.

В нём найдите функцию String::changeBuffer. Она выглядит вот так:

unsigned char String::changeBuffer(unsigned int maxStrLen)
{
	char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
	if (newbuffer) {
		buffer = newbuffer;
		capacity = maxStrLen;
		return 1;
	}
	return 0;
}

и между строками №№ 8 и 9 вставьте печать сообщения об ошибке памяти:

	Serial.println("\r\n*** БЕДА ***");

И сохраните, разумеется. Так Вы хоть исключите возможную нехватку памяти при Вашей активной работе со String. Потом это можно будет закомментировать, но пока отлаживаетесь, пусть будет.

1 лайк