Hoje eu trago uma montagem que
é uma espécie de alarme e automação juntos, utilizando o SIM800L. O modem é
GPRS que precisa de um cartão SIM. Vamos dizer que esse cara é um
“celularzinho” e é muito legal porque é extremamente barato e te possibilita
desenvolver projetos surpreendentes. Enfim, vou te apresentar a montagem e
código fonte com ESP32, SIM800L e um sensor de barreira, além de efetuar
ligações e envio de alerta por SMS para smartphones.
Demonstração
Montagem
Recursos usados
- ESP32 – WROOM
- SIM800L
- Display TFT 1.8’’
- Sensor de barreira
- Módulo de 2 Reles
- Resistor 10k ohm
- Fonte 4.1V e 5V
- Jumpers
- 1x Cartão SIM com plano SMS para o Smartphone
- 1x Cartão SIM com plano SMS e ligação para o SIM800L
- Smartphone
Pinout ESP32
Pinout SIM800L
Montagem
*Deixe os GND em comum
Montagem - Tabela
Código
Instalação de bibliotecas
Código ESP32
Declarações e variáveis
#include <Arduino.h> //biblioteca arduino (opcional)
#include <Adafruit_GFX.h> //biblioteca do display grafico
#include <Fonts/FreeSans9pt7b.h> //fonte usada no display
#include <Adafruit_ST7735.h> // biblioteca de hardware do display
#include <SPI.h> // biblioteca de comunicação SPI
#define TINY_GSM_MODEM_SIM800 // definição do modem usado (SIM800L)
#include <TinyGsmClient.h> // biblioteca com comandos GSM
// pinos display
#define TFT_CS 22 // CS
#define TFT_RST 21 // RESET
#define TFT_DC 5 // A0
#define TFT_MOSI 23 // SDA
#define TFT_CLK 18 // SCK
// objeto do display
Adafruit_ST7735 display = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST);
// tamanho da fonte do display
int fontHeight = 12;
// objeto de comunicação serial do SIM800L
HardwareSerial SerialGSM(1);
// objeto da bibliteca com as funções GSM
TinyGsm modemGSM(SerialGSM);
// velocidade da serial tanto do SIM800L quanto do monitor serial
const int BAUD_RATE = 9600;
// variáveis usadas para contar o tempo sem travar a função loop
// millis de referencia
long int millisRefCon, millisUserResp;
// flag que indica a contagem de tempo (usadas pela função 'timeout')
bool flagCon = false, flagUserResp = false;
// pinos aonde os reles serão ligados e RX / TX aonde o SIM800L será ligado
const int relayPin1 = 17, relayPin2 = 15, sensorPin = 16, RX_PIN = 4, TX_PIN = 2;
//Access point name da vivo
const char *APN = "zap.vivo.com.br";
//Usuario, se não existir deixe em vazio
const char *USER = "";
//Password, se não existir deixe em vazio
const char *PASSWORD = "";
// as variáveis abaixo usadas pela função loop
// flag que indica se, após a ligação feita pelo SIM800L, um usuario respondeu com um SMS em até 1min
bool userResponseSMS = false;
// flag que indica se o sensor está ativo
bool sensorActivated = false;
// index do vetor de numeros de celular, usado para percorrer o vetor
int i = 0;
// quantidade de celulares que receberão mensagens e ligações e poderão enviar comandos SMS
const int numbersTL = 2;
// numero de celulares, a ordem de chamada pelo programa é da esquerda para a direita
const String numbers[numbersTL] = {"+5518999999999", "+5518999999999"};
Setup
void setup()
{
Serial.begin(BAUD_RATE);
Serial.println("Starting...");
// seta pinos do sensor como entrada
pinMode(sensorPin, INPUT);
// seta pinos dos reles como saída
pinMode(relayPin1, OUTPUT);
pinMode(relayPin2, OUTPUT);
// os reles trabalham com lógica inversa, setamos como HIGH para desligá-los de início
digitalWrite(relayPin1, HIGH);
digitalWrite(relayPin2, HIGH);
// atribui para as variáveis de contagem de tempo o tempo atual antes de entrar no loop
millisRefCon = millisUserResp = millis();
display.initR(INITR_BLACKTAB);
resetDisplay();
// inicia e configura o SIM800L
setupGSM();
resetDisplay();
display.println("GPRS: Connected");
}
SetupGSM
// inicializa GSM
void setupGSM()
{
display.println("Setup GSM...");
display.setTextColor(ST7735_GREEN);
// inicia serial SIM800L
SerialGSM.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN, false);
delay(3000);
// exibe info do modem no monitor serial
Serial.println(modemGSM.getModemInfo());
// inicia o modem
if (!modemGSM.restart())
{
display.setTextColor(ST7735_RED);
display.println("Restarting GSM\nModem failed");
delay(10000);
ESP.restart();
return;
}
display.println("Modem restart OK");
// aguarda network
if (!modemGSM.waitForNetwork())
{
display.setTextColor(ST7735_RED);
display.println("Failed to connect\nto network");
delay(10000);
ESP.restart();
return;
}
display.println("Modem network OK");
// conecta na rede (tecnologia GPRS)
if(!modemGSM.gprsConnect(APN,USER,PASSWORD))
{
display.setTextColor(ST7735_RED);
display.println("GPRS Connection\nFailed");
delay(10000);
ESP.restart();
return;
}
display.println("GPRS Connect OK");
//Define modo SMS para texto (0 = PDU mode, 1 = Text mode)
if(sendAT("AT+CMGF=1").indexOf("OK") < 0)
{
display.setTextColor(ST7735_RED);
display.println("SMS Txt mode Error");
delay(10000);
ESP.restart();
return;
}
display.println("SMS Txt mode OK");
//Exclui todos SMS armazenados
sendAT("AT + CMGD=1,4");
resetDisplay();
display.setTextColor(ST7735_WHITE);
}
sendAT e resetDisplay
//Envia comando AT e aguarda até que uma resposta seja obtida
String sendAT(String command)
{
String response = "";
SerialGSM.println(command);
// aguardamos até que haja resposta do SIM800L
while(!SerialGSM.available());
response = SerialGSM.readString();
return response;
}
// limpa e configura display
void resetDisplay()
{
display.setRotation(1);
display.setFont(&FreeSans9pt7b);
display.fillScreen(ST77XX_BLACK);
display.setTextColor(ST7735_WHITE);
display.setCursor(0,fontHeight);
}
Loop
void loop()
{
String msg, number;
// de 5 em 5 segundos, verifica se o SIM800L está desconectado, se sim, tenta reconectar
if(timeout(5000, &millisRefCon, &flagCon))
verifyGPRSConnection();
// se o SIM800L está conectado
if(modemGSM.isGprsConnected())
{
// função que verifica se deve-se efetuar a chamada ou não
if(isItToCall())
{
// sinaliza que o sensor foi ativado
sensorActivated = true;
userResponseSMS = false;
// atribui à variavel de referencia para contar o tempo, o valor atual do millis
millisUserResp = millis();
Serial.println("Sensor activated!");
Serial.println("Calling to number "+String(i+1));
display.println("Sensor activated!");
display.println("Calling to number "+String(i+1));
// efetua a ligação para um dos nºs do vetor, iniciando com 0
call(numbers[i++]);
// após a chamada soma-se 1 ao i
// se chegou ao fim do vetor, retorna ao início (0)
if(i>=numbersTL)
i = 0;
}
// verifica se foi recebido um SMS
if(SMSMessageRecv(&msg, &number))
{
// exibe mensagem no display e monitor serial
resetDisplay();
display.println("SMS Msg Received");
Serial.println("SMS Msg Received");
delay(2500);
// validamos o SMS e executamos uma ação
executeCommand(number, msg);
}
}
else // exibe na serial que o modem está desconectado
Serial.println("Disconnected");
// único delay no loop de 10ms (desconsiderando a função de reconexão, que possui delay para exibição do display)
delay(10);
}
Timeout
// Função que compara se o tempo foi atingido, sem que 'congele' a execução do loop
bool timeout(const int DELAY, long *previousMillis, bool *flag)
{
if(*flag)
{
*previousMillis = millis();
*flag = false;
}
if((*previousMillis + DELAY) < millis())
{
*flag = true;
return true;
}
return false;
}
verifyGPRSConnection
// verifica se o SIM800L se desconectou, se sim tenta reconectar
void verifyGPRSConnection()
{
resetDisplay();
display.print("GPRS: ");
if(modemGSM.isGprsConnected())
display.println("Connected");
else
{
display.println("Disconnect");
display.println("Reconnecting...");
if(!modemGSM.waitForNetwork())
{
display.setTextColor(ST7735_RED);
display.println("GPRS Con. Failed");
delay(5000);
display.setTextColor(ST7735_WHITE);
}
else
{
if(!modemGSM.gprsConnect(APN,USER,PASSWORD))
{
display.setTextColor(ST7735_RED);
display.println("GPRS Con. Failed");
delay(5000);
display.setTextColor(ST7735_WHITE);
}
else
{
display.setTextColor(ST7735_GREEN);
display.println("GPRS Con. OK");
}
}
}
}
isItToCall e call
bool isItToCall()
{
// se o sensor de barreira está ativo ou foi uma vez ativado e não foi recebido um SMS em 1 min, retornamos true indicando que deve-se ligar parao próx número
return digitalRead(sensorPin) == HIGH || (sensorActivated && !userResponseSMS && timeout(60000, &millisUserResp, &flagUserResp));
}
// executa chamada
void call(String number)
{
display.print("Calling...");
Serial.println(number);
// tenta executar chamada
bool res = modemGSM.callNumber(number);
// se obteve sucesso exibe OK, se não, fail
if(res)
display.println(" OK");
else
display.println(" fail");
call (continuação) e SMSMessageRecv
if (res)
{
// assim que a chamada for feita é finalizada
res = modemGSM.callHangup();
// exibe se foi possível finalizar ou não
display.print("Hang up: ");
if(res)
display.println("OK");
else
display.println("fail");
}
}
// verifica se um sms é recebido e obtem o número de quem o enviou
bool SMSMessageRecv(String *msg, String *number)
{
// comando AT que lista todos os SMS armazenados
*msg = sendAT("AT+CMGL=\"ALL\"");
// se o SIM800L responder com SM, significa que um novo SMS acaba de chegar
// então pedimos novamente que o SIM nos liste os SMS armazenados
if((*msg).indexOf("+CMTI: \"SM\"")>=0)
*msg = sendAT("AT+CMGL=\"ALL\"");
SMSMessageRecv (continuação)
// se a mensagem possui um OK e possui mais que 10 caracteres (existe pelo menos um SMS)
if((*msg).indexOf("OK")>=0 && (*msg).length()>10)
{
// exibe a mensagem na serial
Serial.println(*msg);
// obtém o número que nos enviou o SMS e exibe se obteve sucesso
if(getSMSNumber(*msg, *&number))
{
Serial.println("numero obtido: "+*number);
return true;
}
else
{
Serial.println("Erro ao obter numero");
return false;
}
}
// exibe na serial um ponto (debug)
Serial.print(".");
return false;
}
ExecuteCommand
void executeCommand(String number, String msg)
{
// se o número não é válido, exibe mensagem e não faz nada
if(!numberIsValid(number))
{
display.println("Number is not valid");
Serial.println("Number is not valid");
Serial.println(number);
delay(2500);
}
else
{
// se o número é valido
// obtem o texto do SMS recebido
Serial.println("Msg: '"+msg+"'");
getTextSMS(&msg);
Serial.println("Cmd: '"+msg+"'");
// executa comando de acordo com o texto recebido
if(commandOK(number, msg))
{
// sinaliza que o usuario respondeu com um SMS válido
userResponseSMS = true;
// retorna para false a flag que indica se sensor está ativo
sensorActivated = false;
display.println("Sending status");
Serial.println("Sending status");
// Envia o estado dos dois relés em um SMS
sendResponse(number);
}
else
{
// se o comando é inválido, exibe no display
// sinaliza que o usuario respondeu com um SMS inválido
userResponseSMS = false;
display.println("Cmd is not valid");
Serial.println("Cmd is not valid");
}
}
// exclui todos os SMS armazenados
sendAT("AT + CMGD=1,4");
}
GetTextSMS
// obtem texto da mensagem e o retorna por parâmetro
void getTextSMS(String *msg)
{
String aux;
/*
Exemplo de mensagmem:
[
+CMGL: 1,"REC UNREAD","+5518999999999","","18/11/30,11:36:14-08"
Hello
OK
]
*/
//pula primeiro \n
*msg = (*msg).substring((*msg).indexOf( "\n" )+1);
//pula primeira linha: 'Cmd: +CMGL: 1,"REC UNREAD","+5518999999999","","18/11/30,11:04:30-08"'
*msg = (*msg).substring((*msg).indexOf( "\n" )+1);
aux = *msg;
if(aux.length() <= 8)
return;
*msg = "";
// retira a substring "\r\n\r\nOK\r\n" (8 caracteres)
for(int i=0; i<aux.length()-8; i++)
*msg += aux.charAt(i);
}
CommandOK
// executa comando de acordo com a variavel 'msg'
bool commandOK(String number, String msg)
{
// flag que indica se entrou em algum if (indicando comando válido)
bool smsOK = false;
// verifica se a msg corresponde a algum dos comandos existentes e seta os pinos correspondentes
// os reles possuem lógica inversa
if(msg.equalsIgnoreCase("relay 1 on"))
{
digitalWrite(relayPin1, LOW);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("relay 1 off"))
{
digitalWrite(relayPin1, HIGH);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("relay 2 on"))
{
digitalWrite(relayPin2, LOW);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("relay 2 off"))
{
digitalWrite(relayPin2, HIGH);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("relays off"))
{
digitalWrite(relayPin1, HIGH);
digitalWrite(relayPin2, HIGH);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("relays on"))
{
digitalWrite(relayPin1, LOW);
digitalWrite(relayPin2, LOW);
smsOK = true;
}
else
if(msg.equalsIgnoreCase("ok")) // comando OK, usado para sinalizar alarme falso
smsOK = true;
else
if(msg.equalsIgnoreCase("hello")) // comando hello, usado para verificar o funcionamento
{
modemGSM.sendSMS(number, "Hello!");
smsOK = true;
}
else
if(msg.equalsIgnoreCase("status")) // comando status que obtém os estados dos pinos
smsOK = true;
return smsOK;
}
Faça o download dos arquivos














18 Comentários
Muito bom professor! O detalhe das tensões de alimentação para mim foram muito importantes!
ResponderExcluirOlá Boa noit muito bom esse projeto Ai to tentando monta com arduio uno e sensor pir e sim 800l como faço des de ja agradeco
ResponderExcluirParabéns professor!
ResponderExcluirSerá que consigo usar o esp-01 junto com o SIM800L ?
Reduziria o custo do meu projeto, já que precisaria apenas enviar SMS e conectar a internet.
Boa tarde Fernando,
ResponderExcluirSeus projetos com o SIM800L ainda funcionam?
Comprei um e não consigo usar.
No site da anatel apresenta a mensagem:
"O IMEI informado possui restrição de uso. Para maiores informações acesse aqui."
Será que consigo contornar isso?
Comprei um similar, também SIM800L mas não consigo usar.
ExcluirNo hotsite da Anatel "consultaserialaparelho" e mostra que "Até o momento o IMEI informado não possui restrições de uso".
veja meu comentário abaixo :-(
Olá
ResponderExcluirEu tenho dois módulos: A6 e SIM800L ( https://www.filipeflop.com/produto/modulo-gsm-gprs-sim800l-antena-sma ) este que chegou na minha casa na última terça-feira mas eu não estou conseguindo conectividade com a rede, mesmo usando meu chip Claro que uso no meu celular atual.
O led NET (que indica conexão com a rede) pisca a cada 1 segundo (ou menos).
Estou usando a biblioteca TinyGsmClient.h (recentemente baiaxda) e ESP32.
A conexão com microcontrolador está ok pois envio e recebo dados do módulo a 115200 e 9600 sem problemas:
> modemGSM.getModemInfo() retorna SIM800 R14.18
> !modemGSM.restart() retorna true (ok)
só aqui que falha:
> modemGSM.waitForNetwork()
Veja no vídeo que estou alimentando o módulo com uma fonte exclusiva para ele e a antena está ligada, mas o led pisca na mesma frequência por horas.
https://photos.app.goo.gl/dLcPgHxju7Bw5rR17
- Alguma dica sobre outras formas de verificar isso?
- Tem algum procedimento no SIM card que preciso fazer?
- Será que foi bloqueado pela ANATEL?
Olá. Comprei (com nota fiscal) e conectei o sim800l evb com um ard. uno e conforme esquemas que se acha na internet. Não usei nenhuma biblioteca para o sim800l, somente software serial e comandos AT. A maior dificuldade foi descobrir que precisa de um ";" apos o numero a discar no comando ATD+5511987654321; Curioso que num chip TIM pré pago funcionou normal e num chip VIVO o led net piscava a cada 1 seg (sem conexão com a rede, portanto), o led on acendia e depois de uns 4 seg. caia tudo, como se houvesse dado um reset. Continuo com o TIM e tá ok. Espero ter ajudado a vc e a outros.
ExcluirEstava com problemas mais consegui contornar não usando mais a protoboard.
ResponderExcluirAntes piscava a cada 1 segundo o SIM800L (Indicação que não esta conectado a rede GSM) quando fiz a ligação de energia da fonte direto ao SIM800L o problema foi resolvido e ele passou a piscar a cada 3 segundos (Indicação que está conectado a rede GSM).
É importante se atentar a tensão e corrente, 4.2V + 2A.
Também checar a soldagem da antena.
Resolvido.
ExcluirColoquei outros chips da vivo e a tim e funcionou.
Willian, exatamente. No meu caso estava com fonte de bancada, tensão e corrente bem reguladas e o led fica piscando a cada segundo. Após muito penar troquei os cabos que estava usando, aqueles finos de prototipagem arduino, por cabos mais espessos e removí o módulo da "proto" e o bendito funciona muito bem. Fica a dica aos desenvolvedores. Cuidado ao desenvolver alguma PCB, vai precisar de trilhas e tensões bem planejadas.
ExcluirAchei interessante o projeto e tentei reproduzi-lo, porém há um erro: "'getSMSNumber' was not declared in this scope", na linha do código "if(getSMSNumber(*msg, *&number))".
ResponderExcluiralguém saberia o motivo do erro? Se sim, diga-me por favor.
grato, Pedro.
Amigo,
ResponderExcluirPoste sua dúvida no www.forum.fernandok.com.
Vamos formar uma comunidade e ajudar uns aos outros.
http://www.forum.fernandok.com/viewtopic.php?f=4&t=14830&p=16032&hilit=getSMSNumber#p16032
ExcluirTá postado no forum mas ninguém ajuda
Olá, teria como utilizar o modulo sim800l com um esp12f?
ResponderExcluirParece que a anatel bloqueou o sim800l junto com todos os celulares vindo da china sem homologação, pelo que eu pesquisei o sim900 ainda está funcionando, para resolver isso comprei o Arduino MKR1400GSM esse é homologado.
ResponderExcluirvc tem um numero para contato
ResponderExcluirI'm having problem to interface my sim800l to my esp32. I don't know how to set pins Tx and Rx.
ResponderExcluirI have tried to use the tinygsm library but nothing until now
Bom dia, alguem pode me ajudar?
ResponderExcluirNesse projeto estou com 2 erros
C:\Users\PC\AppData\Local\Temp\.arduinoIDE-unsaved2022514-8596-o2rwwt.q9bq\sketch_jun14c\sketch_jun14c.ino: In function 'void setupGSM()':
C:\Users\PC\AppData\Local\Temp\.arduinoIDE-unsaved2022514-8596-o2rwwt.q9bq\sketch_jun14c\sketch_jun14c.ino:82:42: error: invalid conversion from 'int' to 'SerialMode' [-fpermissive]
82 | SerialGSM.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN, false);
| ^~~~~~
| |
| int
In file included from C:\Users\PC\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.1\cores\esp8266/Arduino.h:288,
from C:\Users\PC\AppData\Local\Temp\.arduinoIDE-unsaved2022514-8596-o2rwwt.q9bq\sketch_jun14c\sketch_jun14c.ino:1:
C:\Users\PC\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.1\cores\esp8266/HardwareSerial.h:92:68: note: initializing argument 3 of 'void HardwareSerial::begin(long unsigned int, SerialConfig, SerialMode, uint8_t, bool)'
92 | void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin, bool invert);
| ~~~~~~~~~~~^~~~
Compilation error: exit status 1
Alguem pode me ajudar? Obrigado