Отправка СМС через GSM модуль SIM800L без delay()

Нет ответов
mrPG
Offline
Зарегистрирован: 01.06.2016

При работе с GSM модулем, в моем случае - SIM800L, весь процесс неизбежно делится на сбор/обработку данных и отправку СМС. Все попавшиеся мне примеры с отправкой СМС используют delay() для задержки между последовательно отправляемыми АТ командами. Странно, т.к. при работе с DS18B20 использование delay() является дурным тоном.

Задержек при отправке СМС минимум 3, причем их величина - сотни мсек. Останавливать работу остальных функций на это время - непозволительная роскошь. Поэтому решил использовать класс таймера noDelay, который скопировал в самом начале освоения Ардуины, - респект автору noDelay !

Скетч с демонстрацией работы выкладываю для всеобщей пользы. Пример состоит из четырех файлов:

- основного

// первое СМС отправляется через SMS_INTERVAL после старта программы
// остальные - через SMS_INTERVAL после прдыдущего СМС
// !!!!!!!!! SIM800L подключен к Serial1 (для Mega2560)
// для Uno и др. - используйте библиотеку SoftSerial
//-------------------------------------------------------------------------------------------------------------
#include "noDelay.h"

#define TEST_MODE                1                      // режим отладки  = 1, рабочий = 0
                                                        // используется для отключения вывода в Serial
                                                        
#define SMSSEND_MODE             0                      // отправлять СМС = 1, не отправлять = 0
                                                        // при 0 - вывод в Serial

noDELAY nD_SMSsend;                                      // таймер отправки СМС

// для SIM800L
const long         SMS_INTERVAL         = 5000;          // мин интервал между СМС, мсек
String  myPhoneNumber = "+79000000000";                  // ИЗМЕНИТЬ НА РЕАЛЬНЫЙ !!!!!!!
String  SMStext       = "My first SMS";                  // текст СМС
byte    SMSpartNumber = 0;                               // служебная переменная, порядковый номер части СМС 
boolean flag_SMS_send = true;                            // флаг отправки СМС
//---------------------------------------------------------------------------------------------------    
void loop()
{
  if (flag_SMS_send)                                      // проверка флага для отправки СМС    
     if (nD_SMSsend.tick())                               // проверка таймера между СМС, 
                                                          // требуется при последовательной отправкенескольких СМС
       { f_SendSMS(SMStext, myPhoneNumber);  }            // функция отправки СМС на заданный номер
            
   
} // end of loop
//***************************************************************************************************

- setup(обычно, я выношу его в отдельный файл для удобства восприятия)

//--------------------------------------------------------------------------------------------------------
// SETUP function
void setup(void)
{
  Serial.begin(9600);
  delay(500);
    
 #if TEST_MODE
 Serial.println(" SETUP begin");
 delay(50);
 #endif

// настройка SIM800L        
 Serial1.begin(19200);  //Скорость порта для связи Arduino с GSM модулем
 Serial1.println("AT");
 delay(300);
 
 #if TEST_MODE
 while (Serial1.available())
       Serial.write(Serial1.read());
 #endif
 
 Serial1.println("AT+CMGF=1");
 delay(300);
 
 #if TEST_MODE
 while (Serial1.available())
       Serial.write(Serial1.read());
 #endif           
 
 Serial1.println("AT+CSCS=\"GSM\"");
 delay(300);
 
 #if TEST_MODE
 while (Serial1.available())
       Serial.write(Serial1.read());
#endif            

 delay(1000);
  
 nD_SMSsend.start(SMS_INTERVAL);  // запуск таймера отправки СМС
 
}// end of setup 
//***************************************************************************

- функция отправки СМС

//--------------------------------------------------------------------
// отправка СМС без использования delay()
void f_SendSMS(String text, String phone) 
{
 switch (SMSpartNumber)
 {
  case 0 : SMSpartNumber++;
           #if SMSSEND_MODE
             Serial1.println("AT+CMGS=\"" + phone + "\"");
           #else
             Serial.println("SMS send started");
             delay(50);
             Serial.println("AT+CMGS=\"" + phone + "\"");
             delay(50);
           #endif             
           nD_SMSsend.start(1000);           
           break;
  case 1 : SMSpartNumber++;
           #if SMSSEND_MODE
             Serial1.print(text);           
           #else
             Serial.println(text);           
             delay(50);
           #endif
           nD_SMSsend.start(300);
           break;
  case 2 : SMSpartNumber++;
           #if SMSSEND_MODE
             Serial1.print((char)26);           
           #endif
           nD_SMSsend.start(300);
           break;
  case 3 : SMSpartNumber = 0;
           flag_SMS_send = false;                        // сбрасываем флаг отправки СМС
           #if SMSSEND_MODE
             nD_SMSsend.start(SMS_INTERVAL);
           #else
             Serial.println("SMS send finish");
             delay(50);
           #endif            
           break;  
 } // end of switch
    
} // end of f_SendSMS
//----------------------------------------------------------------------------------

- класс noDelay.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
#include <Arduino.h>

class noDELAY 
{
  private:
    unsigned long previous;
    unsigned long interval;
    boolean s;
  
  public:  
//-------------------------------------------------------------------------------  
// конструктор  
  noDELAY() {s = false;}
//-------------------------------------------------------------------------------  
// запуск таймера
void start(unsigned long _interval) 
  {
    interval = _interval; 
    s = true;
    previous  = millis();
  }
//-------------------------------------------------------------------------------
// остановка таймера  
  void  stop() {s = false;}
//-------------------------------------------------------------------------------
// проверка окончания заданного интервала
boolean tick() 
  {
    unsigned long current  =  millis();
    if (!s) { return false; }
    else 
      if (current - previous >=  interval) 
        {
          previous = current; 
          return true;
        }
      else { return false; }
  }
//-------------------------------------------------------------------------------  
}; // end of class
//===============================================================================