+7(960) 250-82-68 spam@mirossa.ru


  MCU         C           1С         PHP       JAVA      разное 


Статьи
 
 

16 июня 2019 г

Arduino. Отправка СМС. Отладка

Плата Arduino Uno и SIM900 GPRS/GSM Shield

драйвер для USB-UART CH340/CH341 (Windows)

Плата Arduino Uno и SIM900 GPRS/GSM Shield
Плата Arduino Uno и SIM900 GPRS/GSM Shield

Блок питания (например, такой)

Блок питания

код скетча.

#define response_size 100
// подключение библиотеки SoftwareSerial
#include <SoftwareSerial.h>
// Выводы для SoftwareSerial
SoftwareSerial Sim900Serial(7, 8); //Sim900Serial(2, 3); // RX, TX
char response[response_size];  // это буфер для служебного текста ответов сервера
uint8_t  answer;
char telNumber[15] = "+79119991111";
char textSMS[15] = "Hello, World!";
char messageId[10];

void setup()
{
  Sim900Serial.begin(19200);
  Serial.begin(19200);
}

void loop()
{
if (  Serial.available() ){
    while( Serial.available() > 0) 
          Serial.read();    // Clean the input buffer
      
    Serial.println("Debug...");

    
    
    answer = SendTextMessage(telNumber, textSMS, messageId); // отправить sms
    if (answer != 0){
        Serial.print("error of sending\n");
        Serial.println(response); // вывод всего пришедшего ответа
    } else{
        Serial.print("Sms is sended. id - ");
        Serial.println(messageId);
    }   
  }     

  //debug
  delay(3000);
  
} // main loop


// обработка большинства команд завершается на stepP == 1
  uint8_t read_answer_SMS(const char * AtCommand, const char * expected_answer, char * messId, char * text){
      
      unsigned long previous;
      uint8_t x, answer;
      int avail;
      char * istr;
      int pars = 0, stepP = 0;
      char * cc, * ccEnd;
    
      x = 0;
      previous = millis();
      size_t sz, sz_ea;
      
      sz = strlen(AtCommand);
      sz_ea = strlen(expected_answer);
      
     answer = 1; // error

      while( Sim900Serial.available() > 0) 
          Sim900Serial.read();    // Clean the input buffer
    memset(response, '\0', response_size);    // Initialize the string
    
    Sim900Serial.print(AtCommand);    // Отправка AT команды 
    Sim900Serial.print("\r");
    
     while ( ((millis() - previous) < 5000) ){     //  timeout нужно скидывать, когда получаю байты данных
       
       if ( Sim900Serial.available() > 0 ) {
         
          avail = Sim900Serial.read();
//Serial.println(avail, DEC);           
          response[x] = avail;
          x++;
          
        //парсинг ответа
        if ( stepP == 0 ){ 
          istr = strstr ( response + pars, AtCommand);  
          if ( istr != NULL ){
             pars = (istr - response) + sz; 
             stepP = 1;
          }
        } else if ( stepP == 1 ){
              if (sz_ea == 0){ //передана пустая строка в expected_answer (в этой команде ждем ОК и завершаем обарботку;
  //Serial.println(avail, DEC);                
                  istr = strstr ( response + pars , "OK\r\n"); //not "OK\r"
                  if ( istr != NULL ){
                    answer = 0;
                    break;
                  }else{
                    istr = strstr ( response + pars , "ERROR\r\n");  // нужно ли это ?
                    if ( istr != NULL ){
                        break;
                    }
                  }
 
              }else{
                  // сюда пока попадает только, если отправлена команда AT+CMGS ="+79...", требующая доп обработки
//Serial.println(avail, DEC);               
                  istr = strstr ( response + pars , "> ");    /* \62\32  */
                  if ( istr != NULL ){
             
/*  delay(100);                  
if ( Sim900Serial.available() > 0){
  Serial.print("avail ! : ");
  avail = Sim900Serial.read();
Serial.println(avail, DEC);           
  response[x] = avail;
  x++;
}
delay(50);
if ( Sim900Serial.available() > 0){
    Serial.println("avail one more! : ");                  
}
*/
                    Sim900Serial.print(text);  //  ??? при \r\n вместо \r можно отправить второе сообщение
                    // ASCII код ctrl+z - окончание передачи
                    Sim900Serial.print((char)26);

                    pars = (istr - response) + 2;  // 2 - "> "
                    stepP = 2;
                    continue;
                  }
              }
            
            
        }else if ( stepP == 2 ){
            istr = strstr ( response + pars, expected_answer); // +CMGS:  // пример: "+CMGS: 60"
            if ( istr != NULL ){
             pars = (istr - response) + sz_ea + 1; // пропускаем пробел. встаем на начало данных (уид сообщения)
             cc = response + pars; // cc - начало данных
             stepP = 3;
             
            }
        }else if ( stepP == 3 ){
            ccEnd = strstr(cc, "\r\n"); // конец
            if ( ccEnd != NULL ){
              //можно проверить на NULL
              strncpy (messId, cc, ccEnd - cc);
              messId[ccEnd - cc] = '\0';      // добавить в конец строки символ конца строки
              //break;

              pars = (ccEnd - response) + 2;
              stepP = 4;
              continue;
            }
        }else if ( stepP == 4 ){
              istr = strstr ( response + pars , "OK\r\n");
                  if ( istr != NULL ){
                    answer = 0;
                    break;
                  }
          
         }
                  
       }
          
      }
       
    response[x] = '\0';
   //Serial.println(response); // вывод всего пришедшего ответа
  
  return answer;
  }  // read_answer_SMS()
//////////////////////////////////////////////////////////////////////////////////////////////
// процедура отправки sms
uint8_t SendTextMessage(char * telNum, char * text, char * messId){

    uint8_t answer = 0; //ok
    char fullATCMGS[25];  
    
// AT-команда установки text mode

//Serial.println("send AT+CMGF=1");
    answer = read_answer_SMS("AT+CMGF=1", "", NULL, NULL);
    if (answer != 0)
        return answer;

    // ответы приходят в таком виде:
    // "AT+CMGF=1\r\r\nOK\r\n"     // после команды именно \r\r\n . read_answer_SMS() на это не расчитывает, но это канает
    
//Serial.println("send AT+CSCS= \"GSM\"");  //Выбор ASCII кодировки.
    answer = read_answer_SMS("AT+CSCS= \"GSM\"", "", NULL, NULL);
    if (answer != 0)
        return answer;
        
/*Sim900Serial.print("AT+CSCS= \"GSM\"\r");

  //debug
  delay(100);
  while ( Sim900Serial.available() )
     Serial.write ( Sim900Serial.read() ); 
  //
*/
//delay(100);
 // AT+CMGS=<number><CR><message><CTRL-Z> :
 // 1. отправляем AT+CMGS=<number><CR>
 // 2. ждем приглашения сервера ( "> " ).
 // 3. отправляем <message><CTRL-Z>
 // 4. ждем подтверждение сервера:
/*<message>
 *+CMGS: <mr>
 *
 *OK
 */
 // <mr> is the message reference.
    sprintf(fullATCMGS, "AT+CMGS=\"%s\"", telNum);  // "AT+CMGS=\"+79111111111\""
    answer = read_answer_SMS(fullATCMGS, "+CMGS:", messId, text);
    if (answer != 0)
        return answer;
        

  return answer;
}

// https://stackoverflow.com/questions/21522794/atcmgs-returns-error  
// http://www.2150692.ru/faq/47-at-komandy-a6
//
// про UDP (отправка СМС в т.ч. русскими буквами)
// http://hardisoft.ru/soft/samodelkin-soft/poluchenie-i-dekodirovanie-sms-soobshhenij-v-formate-pdu/
// там и про обычные СМС и про Длинные

Подключаем питания плат(SIM900 GPRS/GSM Shield тоже. На одном общем питании обеих плат через USB шилд не работает на 100%). Прошиваем Arduino. Открываем Монитор порта. Вводим любые символы. Отправляем в порт. Получаем СМС на свой номер и отладочную информацию в мониторе порта. Если есть какие-то ошибки, то корректируем команды (AT), отправляемые на сервер.

СМС :

СМС

Комментарии

#2 ?ван 2020-09-13 16:00:11

привет.




information