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