Manual

do

Maker

.

com

SIM900: Enviar SMS, receber SMS e apagar SMS

SIM900: Enviar SMS, receber SMS e apagar SMS

Escrevi no artigo anterior sobre esse shield EFCom e coloquei algum código inicial. Mas pensando um pouco, achei que seria bem mais útil um artigo com uma rotina mais completa, mostrando como enviar SMS, receber SMS e, coisa que não vi citações, apagar SMS. Imagine receber um monte de SMS; qual o limite de armazenamento? Não importa! Basta excluir a cada boot ou com periodicidade, quando for o caso de manter a MCU rodando ininterruptamente.

Onde comprar?

Esse shield SIM900 EFCom pode ser adquirido em nosso parceiro Baú da Eletrônica, através desse link. A vantagem em adquirir esse shield invés de comprar módulos pequenos começa no fato de não ter que regular a tensão em 4.1V, pois ele já é controlado no shield, basta entrar com uma fonte de 9V a 12V no Arduino, com pelo menos 2 amperes. Fora isso, ele tem entrada para microfone e saída para caixa de som, de modo que facilita fazer ligação (pretendo mostrar em outro artigo).

Hardware

Preferi utilizar o Arduino Leonardo para fazer essa configuração de teste, mais pelo cabo micro USB que já estava à mão, mas basta utilizar a biblioteca SoftwareSerial e substituir a Serial1 por ela.

Como utilizei hardware serial, mudei os jumpers para cofigurar a comunicação serial nos pinos 0 e 1 do Arduino, já que o Leonardo possui duas seriais.

Utilizei uma fonte de 12V@3A, garantindo assim a alimentação do shield. Não tem problema ligar o cabo USB enquanto o Arduino é alimentado pela fonte externa, fique tranquilo.

Quando energizado, o shield já mantém um LED vermelho acesso. Segure o botão PWR por uns 4 segundos (dos três botões, é o do meio). Ele possui 3 LEDs e, após segurar o botão de power por tempo suficiente, outro LED se acenderá. Nesse momento, pode soltar o botão de power.

O LED de rede ficará intermitente e rápido. Para encontrar a rede da primeira vez, leva um pouco mais de tempo. Ao encontrar a rede, o LED piscará uma vez a cada 3 segundos, aproximadamente. Será a hora que poderemos interagir com ele através do Arduino.

Código para enviar SMS, receber SMS e apagar SMS

Não vou dizer que foi exatamente "fácil" escrever esse código. Para receber o retorno esperado, tive que enviar 25 SMS até acertar o código para enviar SMS. Para receber automaticamente após o boot (foi o primeiro teste que fiz), recebi 11 mensagens. Gastei uns trocos, hum?

Como resultado do esforço, cheguei a um código bastante didático, acredito. Digo "didático" porque utilizei alguns recursos pouco utilizados em sketches, como as funções C strtok_r, strstr e até o método indexOf, do objeto String do Arduino.

Vale lembrar que "string" em C é um array de char com terminador nulo. Já um objeto String contém métodos que facilitam a manipulação dos dados de uma string, como é o caso do indexOf. Para ver os métodos oferecidos pelo objeto String do Arduino, dê uma olhada nesse link.

O código utilizado mantém apenas a chamada da função receiveSMS() dentro da função loop. Não é necessário adicionar delay porque já é feito isso dentro da função.

#include <Arduino.h>

//defina o numero real que poderá enviar SMS ao shield:
#define CEL_NUMBER "987654321"
#define KEYWORD "status"

char rcv[100] = {0};
uint8_t index = 0;
char incoming = 0;

//Protótipos de funções
void sendSMS(char *msg);
void receiveSMS();
bool parseCelNumber(char *tok, bool is_done);
void parseMessage(char *tok);
void deleteSMS();

//O espaço é limitado. A exclusão pode ser feita com periodicidade ou a cada boot da MCU.
void deleteSMS(){
    Serial1.print("AT+CMGDA=\"");
    Serial1.println("DEL ALL\"");
    delay(2000);
    Serial.println("Mensagens deletadas");
}
//Só dá atenção à mensagem se for originada pelo celular da macro CEL_NUMBER.
bool parseCelNumber(char *tok, bool is_done){
    if (is_done){
        return true;
    }

    char *pch = 0;
    pch = strstr(tok,CEL_NUMBER);
    if (pch != NULL){
        Serial.println("Numero de comando OK. Lendo...");
        return true;
    }
    return false;
}

//Le a mensagem. se tiver "Djames", imprime um texto na serial. Se for status, envia o status por SMS.
void parseMessage(char *tok){
    String msg = tok;
    if (msg.indexOf("Djames") > -1){
        Serial.println("Manual do Maker");
    }
    else if (msg.indexOf(KEYWORD) >-1){
        sendSMS("Tudo tranquilo.");
    }
}

//Rotina para enviar SMS. Não deve ser utilizada no loop.
void sendSMS(char *msg){
  Serial.println("Um momento...");
  Serial1.print("\r");
  Serial1.flush();
  delay(1000);
  Serial1.print("AT+CMGF=1\r");
  Serial1.flush();
  delay(1000);
  Serial.println("Enviando para Djames...");
  Serial1.print("AT+CMGS=\"+5511987654321\"\r"); 
  Serial1.flush();
  delay(1000);
  Serial1.print(msg);   //texto
  delay(1000);
  Serial1.write(26);  //Equivalente a Ctrl+Z
}

//Rotina para receber SMS. Pode ser chamada no loop.
void receiveSMS(){
  /* A resposta inicia com +CMT:. todos os campos na resposta são separados por virgula, 
  sendo o primeiro campo o numero do telefone, segundo campo o nome do sender, o terceiro
  campo o timestamp e o quarto campo, a mensagem atual.
  Diferente do envio, o loop pode ser alimentado, fazendo a leitura constante do shield.
  Ex. do formato da mensagem:
  +CMT: "+5511987654321","Quem enviou","01/01/75,01:02:03+14","Ralou, moto."
  */
  Serial1.print("AT+CMGF=1\r");
  Serial1.flush();
  delay(500);
  Serial1.println("AT+CNMI=1,2,0,0,0"); //le a mensagem mais recente
  delay(500);
  memset(rcv,0,100);
  while (Serial1.available()){
    incoming   = Serial1.read();
    rcv[index] = incoming;
    index++;
  }
  index = 0;

  char *rest = rcv;
  char *token;
  bool accept = false;
  if (strstr(rcv,"+CMT")){
      while ((token = strtok_r(rest,",",&rest)) != NULL){
        //Serial.println(token);
        accept = parseCelNumber(token, accept);
        if (accept){
            parseMessage(token);
        }
      }
  }
      delay(1000);
}

void setup()
{
  Serial1.begin(19200);  
  Serial.begin(9600);
  Serial.println("Started!");
  deleteSMS();
}

void loop()
{
    receiveSMS();
}

Saída do código

Utilizando o código acima, se for enviado um SMS para o shield com a palavra "Djames", a serial imprime "Manual do Maker". Se enviar uma mensagem com  "status", o shield envia uma mensagem fake de status (aqui caberia ler sensores e atuadores).

sms-output-300x106.webp

No smartphone:

000-sms-300x163.webp

Precisa de um projeto?

Manual do Maker é mais do que um blog. Somos uma empresa de serviços, cuja principal atividade é desenvolvimento e implementação de projetos embarcados e IoT. Trabalhamos dentro da legalidade, emitindo nota fiscal de serviço, elaboração de requisitos de sistema e documentação do código. Não importa onde você esteja, montamos a prova de conceito e gravamos vídeo do projeto antes de entregar o código e/ou hardware configurado.

Em parceria com a AFEletrônica, projetamos e produzimos hardware industrial, para lhe entregar o melhor para seu projeto. Entre em contato: vendas@afeletronica.com.br Ou direto comigo: djames.suhanko@gmail.com

Será um prazer tê-lo como nosso cliente!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.