Кормушка для птиц по СМС на 8266

Тема в разделе "ESP8266, ESP32", создана пользователем dmb, 11 ноя 2019.

  1. dmb

    dmb Нерд

    Доброе время! Решил сделать кормушку, чтоб при отправке СМС срабатывал серво, который сыпал корм.
    Взял Wemos Di mini (NodeMCU) и SIM800l (все самое дешевое, естественно). Вставил симку, срабатывает при отправке - но только 1 раз, второй раз не срабатывает. Если контроллер перезагрузить нажатием кнопки - то можно опять активировать один раз. Хотя, даже иногда срабатывает два раза (но редко). В чем может быть ошибка? Питание модулей и сервы отдельное, думаю что хорошее. Может есть ошибка в скетче?

    Код (C++):
    #include <SoftwareSerial.h>
    #include <Servo.h>

    #define DEBUG 1
    #define SIM800_TX_PIN D6 // TX pin of SIM800L
    #define SIM800_RX_PIN D5 // RX pin of SIM800L

    SoftwareSerial serialSIM800(SIM800_TX_PIN,SIM800_RX_PIN);
    char responseBuffer[256];

    Servo servo;

    char *checkPhone    = {
                              (char *)"79", // Phone number to check
                            };

    char *checkSms[]    = {
                              (char *)"CMT:", // Sms string
                            };

    char *initSim[]       = {
                              (char *)"AT", // Ping module
                            };


    char *initTextMode[]   = {
                              (char *)"AT+CMGF=1\r\n", // Mobile network status
                            };


    char *initSmsMode[]    = {
                              (char *)"AT+CNMI=1,2,0,0,0\r\n", // Mobile network status
                            };



    void setup() {
      Serial.begin(115200);
      while(!Serial);

      servo.attach(2); //D4
      servo.write(0);

      if(DEBUG) Serial.println("Connecting GSM module");
      if (!connectModule()) {
        delay(1000);
        reboot();
      }

      writeToSim(initTextMode, sizeof(initTextMode)/sizeof(*initTextMode));
      readSim(responseBuffer, 2000);
      Serial.println(responseBuffer);
      delay(1000);

      writeToSim(initSmsMode, sizeof(initSmsMode)/sizeof(*initSmsMode));
      readSim(responseBuffer, 2000);
      Serial.println(responseBuffer);
      delay(1000);
    }

    void loop() {
      readSim(responseBuffer, 2000);
      Serial.println(responseBuffer);

      if(strstr(responseBuffer,  (char *)"CMT:")) {
        if(strstr(responseBuffer, checkPhone)) {
          Serial.println("SMS detected!");
          servo.write(145);
          delay(1000);
          servo.write(0);
          delay(1000);
       
        }
      }
    }


    bool connectModule() {
      serialSIM800.begin(57600);
      Serial.print("Trying 57600 ...");
      writeToSim(initSim, sizeof(initSim)/sizeof(*initSim));
      readSim(responseBuffer, 2000);
      if (isResponseOk(responseBuffer)) {
        Serial.println("Connected to mobile");
        return true;
      }
      Serial.println("Bad");
      return false;
    }


    void writeToSim(char *commands[], int size) {
      for(int i = 0; i < size; i++) {
        serialSIM800.println(commands);
        if(DEBUG) { Serial.print("Writing: "); Serial.println(commands); }
        delay(1000);
      }
    }

    // Read Sim response until timeout
    char* readSim(char* buffer, int timeout) {
      unsigned long timeStart = millis();
      int charCount = 0;

      while(charCount < 256) {
        if(serialSIM800.available()) {
          buffer[charCount++] = serialSIM800.read();
        }
        if(millis() - timeStart > timeout) break;
        delay(10);
      }

      buffer[charCount++] = 0;
      return buffer;
    }


    bool isResponseOk(char* buffer) {
      // 1. Get buflen
      int buflen = 0;
      for(int i = 0; i < 256; i++) {
        if(int(buffer) == 0) {
          buflen = i;
          break;
        }
      }
      if(DEBUG) { Serial.print("Buflen: " ); Serial.println(buflen, DEC); }

      // 2. Is last ok? buffer[buflen] == 0
      while (buflen > 0) {
        buflen--;
        if (int(buffer[buflen]) == 10) {
          continue;
        }
        if (int(buffer[buflen]) == 13) {
          continue;
        }
        if (int(buffer[buflen]) == 75 && int(buffer[buflen-1]) == 79) {
          if(DEBUG) { Serial.println("Response is OK"); }
          return true;
        }
          if(DEBUG) { Serial.println("Response is BAD"); }
        return false;
      }
      return false;
    }

    void reboot() {
      wdt_disable();
      wdt_enable(WDTO_15MS);
      while (1) {}
    }

    Заранее благодарен за ответ!
     
    Последнее редактирование: 11 ноя 2019
  2. parovoZZ

    parovoZZ Гуру

    Я думаю, что надо код вставить правильно - с помощью встроенного редактора.
    plaintext читать невозможно.
     
  3. dmb

    dmb Нерд

    ок, спасибо, отредактировал.
     
  4. Airbus

    Airbus Радиохулиган Модератор

    А зачем node mcu и Sim900?Web управление например по Blynk не?
     
    NikitOS нравится это.
  5. dmb

    dmb Нерд

    НЕ знаю, посоветовали вот и использовал этот контроллер, должно работать - возможно программная ошибка какая-то...
     
  6. parovoZZ

    parovoZZ Гуру

    SIM800 жрет хорошо. Не исключено, что ESP тупо виснет, когда ему не хватает кислорода.
     
  7. dmb

    dmb Нерд

    Запитал от литий-полимерного аккума 7,4 В через понижайку LM 2596, выставил на выходе 4.1 вольта. Мне кажется, все таки, что проблема программная (могитор порта после регистрации сим-карты перестает работать).
     
  8. SergeiL

    SergeiL Оракул Модератор

    Ну Wemos D1 как по питанию подключён?
     
  9. dmb

    dmb Нерд

    Пробовал всякои от LiPo через понижайку, и от 18650 (к пину +5), и от USB.
     
  10. Airbus

    Airbus Радиохулиган Модератор

    Да и есп жрет немало.Поэтому удивился.Это наихудшая связка.Но код реально косячный.Тоже с Забора?Есть много манипуляций ведущих в никуда.Сам писал?Можно все проще и красивше.И в ВИКИ есть пример.
     
  11. SergeiL

    SergeiL Оракул Модератор

    Ну без схемы тут слишком много вариантов. :(
     
  12. dmb

    dmb Нерд

    Вот есть скетч, там при поступлении СМС рабатывают 2 реле. Как будто рабочий. Можно ли просто вместо реле вписать серву?
    Код (C++):
    /*
    Тестировалось на Arduino IDE 1.8.5
    Дата тестирования 14.06.2019г.
    */

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(3, 2);              // Выводы SIM800L Tx & Rx подключены к выводам Arduino 3 и 2
    char incomingByte;
    String inputString;
    int relay_1 = A0;                           // Вывод управления реле 1
    int relay_2 = A1;                           // Вывод управления реле 2
    void setup()
    {
       pinMode(relay_1, OUTPUT);                 // Установим вывод как выход
       digitalWrite(relay_1, HIGH);              // Устанавливаем высокий уровень
       pinMode(relay_2, OUTPUT);                 // Установим вывод как выход
       digitalWrite(relay_2, HIGH);              // Устанавливаем высокий уровень
       Serial.begin(9600);                  
       mySerial.begin(9600);
    while(!mySerial.available()){             // Зацикливаем и ждем инициализацию SIM800L
        mySerial.println("AT");                  // Отправка команды AT
        delay(1000);                             // Пауза
        Serial.println("Connecting…");         // Печатаем текст
        }
        Serial.println("Connected!");            // Печатаем текст
        mySerial.println("AT+CMGF=1");           // Отправка команды AT+CMGF=1
        delay(1000);                             // Пауза
        mySerial.println("AT+CNMI=1,2,0,0,0");   // Отправка команды AT+CNMI=1,2,0,0,0
        delay(1000);                             // Пауза
        mySerial.println("AT+CMGL=\"REC UNREAD\"");
    }
    void loop()
    {
       if(mySerial.available()){                  // Проверяем, если есть доступные данные
           delay(100);                            // Пауза
          while(mySerial.available()){            // Проверяем, есть ли еще данные.  
          incomingByte = mySerial.read();         // Считываем байт и записываем в переменную incomingByte  
          inputString += incomingByte;            // Записываем считанный байт в массив inputString  
        }  
           delay(10);                             // Пауза      
           Serial.println(inputString);           // Отправка в "Мониторинг порта" считанные данные
           inputString.toUpperCase();             // Меняем все буквы на заглавные  
           if (inputString.indexOf("ON_1") > -1){ // Проверяем полученные данные, если ON_1 включаем реле 1
            digitalWrite(relay_1, LOW);      
            sms(String("Relay 1 - ON"), String("+7xxxxxxxxxx"));} // Отправка SMS    
           if (inputString.indexOf("OFF_1") > -1){ // Проверяем полученные данные, если OFF_1 выклюем реле 1
            digitalWrite(relay_1, HIGH);      
            sms(String("Relay 1 - OFF"), String("+7xxxxxxxxxx"));}// Отправка SMS    
           if (inputString.indexOf("ON_2") > -1){ // Проверяем полученные данные, если ON_2 включаем реле 2
            digitalWrite(relay_2, LOW);      
            sms(String("Relay 2 - ON"), String("+7xxxxxxxxxx"));}  // Отправка SMS  
           if (inputString.indexOf("OFF_2") > -1){     // Проверяем  полученные  данные, если OFF_2 выключаем реле 2
            digitalWrite(relay_2, HIGH);      
            sms(String("Relay 2 - OFF"), String("+7xxxxxxxxxx"));} // Отправка SMS  
            delay(50);
           if (inputString.indexOf("OK") == -1){  
            mySerial.println("AT+CMGDA=\"DEL ALL\"");    
            delay(1000);}    
            inputString = "";}
    }
    void sms(String text, String phone)  // Процедура Отправка SMS
    {
       Serial.println("SMS send started");
       mySerial.println("AT+CMGS=\"" + phone + "\"");
       delay(500);
       mySerial.print(text);
       delay(500);
       mySerial.print((char)26);
       delay(500);
       Serial.println("SMS send complete");
       delay(2000);
    }
     
  13. Airbus

    Airbus Радиохулиган Модератор

    Дык....Нужно!А второе реле убрать нах
     
  14. dmb

    dmb Нерд

    А как это сделать, м-р Аирбас? (буду очень благодарен)
     
  15. Airbus

    Airbus Радиохулиган Модератор

    Проверяйте
    Код (Text):
    #include <SoftwareSerial.h>
    #include <Servo.h> // подключаем библиотеку для работы с сервоприводом
    Servo servo1; // объявляем переменную servo типа "servo1"
    SoftwareSerial mySerial(5, 6);              // Выводы SIM800L Tx & Rx подключены к выводам 5 и 6
    char incomingByte;
    String inputString;
    Servo servo;
    void setup()
    {
        mySerial.begin(9600);
        servo1.attach(2); // привязываем сервопривод к аналоговому выходу 2
        while(!mySerial.available()){             // Зацикливаем и ждем инициализацию SIM800L
        mySerial.println("AT");                  // Отправка команды AT
        delay(1000);                             // Пауза
        Serial.println("Connecting…");         // Печатаем текст
        }
        Serial.println("Connected!");            // Печатаем текст
        mySerial.println("AT+CMGF=1");           // Отправка команды AT+CMGF=1
        delay(1000);                             // Пауза
        mySerial.println("AT+CNMI=1,2,0,0,0");   // Отправка команды AT+CNMI=1,2,0,0,0
        delay(1000);                             // Пауза
        mySerial.println("AT+CMGL=\"REC UNREAD\"");
    }
    void loop()
    {
       if(mySerial.available()){                  // Проверяем, если есть доступные данные
           delay(100);                            // Пауза
          while(mySerial.available()){            // Проверяем, есть ли еще данные.
          incomingByte = mySerial.read();         // Считываем байт и записываем в переменную incomingByte
          inputString += incomingByte;            // Записываем считанный байт в массив inputString
        }
           delay(10);                             // Пауза    
           Serial.println(inputString);           // Отправка в "Мониторинг порта" считанные данные
           if (inputString.indexOf("corm") > -1){ // Проверяем полученные данные, если ON_1 включаем реле серву
           servo1.write(90); // ставим угол поворота под 90
           delay(2000); // ждем 2 секунды
           servo1.write(0); // ставим угол поворота под 00
           delay(2000); // ждем 2 секунды
           }
           delay(50);
           if (inputString.indexOf("OK") == -1){
            mySerial.println("AT+CMGDA=\"DEL ALL\"");  
            delay(1000);}  
            inputString = "";}
    }
     
    Команда corm на Ваш номер.Если надо другую-измените в коде
     
    dmb нравится это.
  16. dmb

    dmb Нерд



    На ардуино Нано пойдет?
     
  17. parovoZZ

    parovoZZ Гуру

    зависание программы в одном цикле - и есть программная проблема. Ни разу не аппаратная.
     
  18. SergeiL

    SergeiL Оракул Модератор

    Это крутой ответ, такой возможен только от паровоЗЗ :).
    Еще ошибки пунктуации исправь, для ЧСВ :)
     
    issaom нравится это.
  19. Airbus

    Airbus Радиохулиган Модератор

    Пойдет.Для Наны можно еще проще сделать.
     
  20. dmb

    dmb Нерд

    Блин, что то не срабатывает... RX подключил на пин ардуино через резистор 10 КОМ и такой же резистор поставил между пином и массой. Правильно? Серву переставил на цифровой выход 8 (на аналоговый он вообще не реагировал, а сейчас возвращается в положение 0 при включении питания). Но все равно, при отправке по СМС ничего не происходит - и монитор порта молчит...