SIM800L и Arduino Sleep — получение странного последовательного вывода после 5 вызовов

Я работаю над проектом, в котором я пытаюсь получить этот идентификатор вызывающего абонента с помощью arduino, чтобы я мог использовать его позже для отправки SMS с данными считывания датчика.

Каким-то образом я сделал этот код (много погуглив), и он отлично работает... Но когда я включаю спящую часть Arduino, он работает в начале, но после того, как я позвоню SIM800 4-5 раз с разницей в 30 секунд, я получить непригодные для использования данные о серийном номере, поэтому я больше не могу анализировать правильный номер.

Я много чего перепробовал, сбросил скорость до 1200, изменил задержку, но после нескольких вызовов все равно получаю странные символы.

Кто-нибудь может мне помочь?

Микроконтроллер PS ATMEGA328P ic

Спасибо, Матия

#include <SoftwareSerial.h>
#include <avr/sleep.h>


SoftwareSerial SIM800(8, 7);

String buffer1;
unsigned int current_millis = 0;
String phone;

void setup() {
     buffer1.reserve(200);
     phone.reserve(20);

     Serial.begin(19200); //
     SIM800.begin(9600);
     delay(1000);
     SIM800.write("AT\r");  // из-за режима автопривязки SIM800L
     delay(1000);
     SIM800.write("AT+IPR=9600\r");  // установить скорость 9600, я пробовал 1200
     and  other, and with autobauding but still got same problem
     delay(1000);
     SIM800.write("AT+CMGF=1\r");  // установить режим SMS на текст
     delay(1000);
     SIM800.write("AT+CNMI=2,2,0,0,0\r");
     delay(1000);
     Serial.print(SIM800.readString());
     SIM800.write("AT+CLIP=1\r\n");
     delay(1000);
     SIM800.write("AT+SGPIO=0,7,1,0\r");
     delay(1000);
     SIM800.write("AT+CSCLK=2\r"); //режим энергосбережения SIM800L
     delay(1000);
     current_millis = millis();
}

void loop() {
   // поместите сюда ваш основной код для многократного запуска:
   if (SIM800.available() > 0) {
      buffer1 = SIM800.readStringUntil('\n'); //Сохраняем строку, затем анализируем
           caller number from it
      Serial.println(buffer1);
      parse();
      current_millis = millis();
      }

    if ((millis() - current_millis) > 10000) { // Переводим atmega tu в сон
       sleepNow();
       delay(1000);// пробовал много задержек
       current_millis = millis();
     }

 }

void parse() {
    if (buffer1.indexOf("CLIP:") > 0) {
        phone = buffer1.substring(buffer1.indexOf("+CLIP: ") + 8, 
        buffer1.indexOf("+CLIP: ") + 21); //парсинг номера вызывающего абонента
        Serial.println(phone);
        SIM800.write("ATH\r"); //повесить телефонный звонок
        delay(500);
        SIM800.write("ATH\r");
        delay(500);
  }

}

void sleepNow() { // ПРЕРЫВАНИЕ ИЗМЕНЕНИЯ ВЫВОДВ НА контактах 7,8, ПОТОМУ ЧТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПОСЛЕДОВАТЕЛЬНО
                   LIBRARY USE IT AND IT WILL WAKE UP ATMEGA
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // здесь устанавливается спящий режим
                                          sleep bit in the mcucr register
    sleep_mode();            // здесь устройство действительно усыплено!!
                         // ПРОГРАММА ПРОДОЛЖАЕТСЯ С ЭТОГО ПОСЛЕ ПРОБУЖДЕНИЯ
    sleep_disable();         // первое, что нужно сделать после пробуждения ото сна: отключить
                                sleep...
    }

Последовательный ВЫВОД

, 👍4

Обсуждение

С SoftwareSerial можно только догадываться, что может происходить. Добавьте несколько дополнительных вызовов Serial.println() со статическим текстом, чтобы выяснить, является ли ошибка ПК => Arduino или Arduino => SIM800., @Majenko

Привет, Маженко, ошибка между Arduino и SIM800 (я знаю, потому что телефонный звонок не является ATH, когда он должен быть). Я попробовал ваше решение, но оно не сработало... Я также пробовал SIM800.end() и SIM800.begin(9600) перед тем, как перевести Arduino в спящий режим... Это не работает... Единственное, что у меня работает, это сброс Arduino после выполнения работы. Добавление void(* resetFunc) (void) = 0; после функции настройки и вызовите ее resetFunc(); после того, как я отправлю сообщение вызывающему абоненту. Спасибо, если у вас есть идея, которая решает проблему, лучше опубликуйте ее здесь, может быть, это кому-то поможет., @user3613833


2 ответа


1

Попробуйте AltSoftSerial, это бесспорно лучше.

Сброс может сработать, но на самом деле он не решит вашу проблему, он просто проведет его под матрас. Кроме того, вы не думали об отказе от этой строки? Это источник многих проблем с памятью. Вместо этого вы могли бы относительно легко заменить его массивом символов. Примерно так, взято из примера №2:

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // завершаем строку
            ndx = 0;
            newData = true;
        }
    }
}
,

1

Когда вы используете спящий режим SLEEP_MODE_PWR_DOWN, вы отключаете все таймеры микроконтроллера, включая таймер, который использует SoftSerial. Я предполагаю, что отключение, а затем повторное включение таймеров при выходе из спящего режима повлияет на синхронизацию последовательной связи.

Попробуйте использовать SLEEP_MODE_IDLE вместо SLEEP_MODE_PWR_DOWN и посмотрите, решит ли это проблему.

,