Trying to connect and send text using ESP32 with the SIM800L V2 module but I am receiving error after pressing the button. Can anyone check if there are issues with my code/connections?
#include <HardwareSerial.h>
HardwareSerial sim800(2); // Use UART2 for SIM800L
const int buttonPin = 15; // Pin where the button is connected
int buttonState = LOW; // Variable for reading the button status
int lastButtonState = LOW; // Variable to store the previous button state
unsigned long lastDebounceTime = 0; // The last time the button state was toggled
unsigned long debounceDelay = 50; // Debounce time in milliseconds
unsigned long commandTimeout = 3000; // Time to wait for command responses
unsigned long lastCommandTime = 0;
bool awaitingResponse = false;
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Enable internal pull-up resistor
sim800.begin(115200, SERIAL_8N1, 16, 17); // SIM800L baud rate, using GPIO16 (RX2) and GPIO17 (TX2)
Serial.begin(115200); // Serial monitor for debugging
Serial.println("Initializing SIM800L...");
// Initialize SIM800L
sendCommand("AT");
delay(1000); // Wait for the module to respond
sendCommand("AT+CSCS=\"GSM\"");
delay(1000);
sendCommand("AT+CMGF=1"); // Set SMS to text mode
delay(1000);
}
void loop() {
handleButton();
handleResponse();
}
void handleButton() {
int reading = digitalRead(buttonPin);
// Check if the button state has changed
if (reading != lastButtonState) {
lastDebounceTime = millis(); // Reset the debouncing timer
}
// If the button state has been stable for the debounce delay, take it as an actual press
if ((millis() - lastDebounceTime) > debounceDelay) {
// If the button state has changed
if (reading != buttonState) {
buttonState = reading;
// Only send SMS when the button is pressed (not released)
if (buttonState == LOW) { // LOW because INPUT_PULLUP means button press is LOW
sendSMS("+6***********", "Hello");
}
}
}
lastButtonState = reading; // Save the reading for the next loop iteration
}
void handleResponse() {
if (awaitingResponse) {
if (millis() - lastCommandTime > commandTimeout) {
// Time out handling
awaitingResponse = false;
Serial.println("Command timeout.");
}
while (sim800.available()) {
Serial.write(sim800.read());
}
awaitingResponse = false;
}
}
void sendCommand(String command) {
sim800.println(command);
Serial.print("Sending command: ");
Serial.println(command);
lastCommandTime = millis();
awaitingResponse = true;
}
void sendSMS(String number, String text) {
sendCommand("AT+CMGS=\"" + number + "\"");
waitForResponse();
sim800.print(text);
waitForResponse();
sim800.write(26); // ASCII code for Ctrl+Z to send the SMS
waitForResponse();
}
void waitForResponse() {
lastCommandTime = millis();
awaitingResponse = true;
while (awaitingResponse) {
handleResponse();
}
}
Error below:
as you don't wait for a response to AT commands you are probably sending too fast
have you attempted to type AT commands and wait for the OK response?
try this
// // SIM800L EVB ESP32 test using Serial2 (pins 16 Rx and 17 Tx)
// connect so
// SIM800 5V to ESP32 5V
// SIM800 GND to ESP32 GND
// SIM800 VDD to ESP32 3.3v
// SIM800 TXD to ESP32 pin 16 Rx
// SIM800 TXD to ESP32 pin 17 tx
// AT+CGMI returns the manufacturer's name
// AT+CGMM returns the MODEM model number
// AT+CGMR returns details of the software and model revision level
// AT+CGSN returns the MODEM's serial number
#include <Arduino.h>
// ESP32 example using HardwareSerial library to access Serial port 2 (pins 16 and 17)
// from https://programming.vip/docs/esp32-use-of-hardwareserial-library.html
#define SERIAL_BAUD 9600//115200
int distance = 0;
void setup() {
//Initialize serial port 0
Serial.begin(115200);
//Initialize serial port 2
Serial2.begin(SERIAL_BAUD, SERIAL_8N1);
Serial.println("\nSIM800 EVB to ESP32 Serial port 2 test");
}
void loop() {
while (Serial2.available() > 0) {
uint8_t byteFromSerial = Serial2.read();
Serial.write(byteFromSerial);
}
while (Serial.available() > 0) {
uint8_t byteFromSerial1 = Serial.read();
Serial2.write(byteFromSerial1);
}
}
text typed on keyboard is sent to SIM800 and response displayed on screen
a run gave
at
OK
at+cgmi
SIMCOM_Ltd
OK
at+cgmm
SIMCOM_SIM800L
OK
at+cgmr
Revision:1418B05SIM800L24
OK
also when you send a command to send a text you should wait for > response, e.g.
AT+CMGS=”+TTTTT”
>
also avoid uploading screen images - they waste space and are impossible to copy from - copy the text and post it using code tags </>
Correct me from what I understood so far @horace
I ran the code you provided and the response is similar to the one you provided.
As much as possible, I would like to send a message when the button is clicked.
Right now I modified my code to reflect what you did in your code but it looks like it's still isnt working.
#include <HardwareSerial.h>
// HardwareSerial sim800(2); // Use UART2 for SIM800L
const int buttonPin = 15; // Pin where the button is connected
int buttonState = LOW; // Variable for reading the button status
int lastButtonState = LOW; // Variable to store the previous button state
unsigned long lastDebounceTime = 0; // The last time the button state was toggled
unsigned long debounceDelay = 50; // Debounce time in milliseconds
unsigned long commandTimeout = 3000; // Time to wait for command responses
unsigned long lastCommandTime = 0;
bool awaitingResponse = false;
String phoneNumber = "+6***********"
String yourMessage = "Hello"
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Enable internal pull-up resistor
Serial2.begin(9600, SERIAL_8N1); // SIM800L baud rate, using GPIO16 (RX2) and GPIO17 (TX2)
Serial.begin(115200); // Serial monitor for debugging
Serial.println("Initializing SIM800L...");
// Initialize SIM800L
sendCommand("AT");
delay(1000); // Wait for the module to respond
sendCommand("AT+CSCS=\"GSM\"");
delay(1000);
sendCommand("AT+CMGF=1"); // Set SMS to text mode
delay(1000);
}
void loop() {
handleButton();
handleResponse();
}
void handleButton() {
int reading = digitalRead(buttonPin);
// Check if the button state has changed
if (reading != lastButtonState) {
lastDebounceTime = millis(); // Reset the debouncing timer
}
// If the button state has been stable for the debounce delay, take it as an actual press
if ((millis() - lastDebounceTime) > debounceDelay) {
// If the button state has changed
if (reading != buttonState) {
buttonState = reading;
// Only send SMS when the button is pressed (not released)
if (buttonState == LOW) { // LOW because INPUT_PULLUP means button press is LOW
Serial.println("Button pressed, sending SMS...");
sendSMS(phoneNumber, yourMessage);
}
}
}
lastButtonState = reading; // Save the reading for the next loop iteration
}
void handleResponse() {
if (awaitingResponse) {
if (millis() - lastCommandTime > commandTimeout) {
// Time out handling
awaitingResponse = false;
Serial.println("Command timeout.");
}
while (Serial2.available()) {
char c = Serial2.read();
Serial.write(c); // Print response to Serial Monitor
}
awaitingResponse = false;
}
}
void sendCommand(String command) {
Serial2.println(command);
Serial.print("Sending command: ");
Serial.println(command);
lastCommandTime = millis();
awaitingResponse = true;
}
void sendSMS(String number, String text) {
sendCommand("AT+CMGS=\"" + number + "\"");
waitForResponse();
Serial2.print(text);
waitForResponse();
Serial2.write(26); // ASCII code for Ctrl+Z to send the SMS
waitForResponse();
}
void waitForResponse() {
lastCommandTime = millis();
awaitingResponse = true;
while (awaitingResponse) {
handleResponse();
}
}
void testCommunication() {
Serial.println("Testing communication with SIM800L...");
sendCommand("AT");
waitForResponse();
}
Result from bootup based on Serial output:
01:36:27.010 -> AT+CSCS="GSM"
01:36:27.010 -> OK
01:36:27.010 -> AT+CMGF=1
01:36:27.010 -> OK
01:36:36.813 -> Button pressed, sending SMS...
01:36:36.850 -> Sending command: AT+CMGS="+6***********"
01:44:47.034 -> Sending command: AT+CSCS="GSM"
01:44:48.005 -> Sending command: AT+CMGF=1
01:44:49.008 -> AT
01:44:49.008 -> OK
01:44:49.008 -> AT+CSCS="GSM"
01:44:49.008 -> OK
01:44:49.008 -> AT+CMGF=1
01:44:49.008 -> OK
01:44:59.906 -> Button pressed, sending SMS...
01:44:59.906 -> Sending command: AT+CMGS="+6***********"
Were my changes correct or am I still missing something?
Looking at the code. I think I can try doing the following.
- Connect SIM800L V2 VDD to 3.3V of ESP32.
- Use your code and send a text so something like:
sim.println("AT+CMGF=1");
sim.println("AT+CMGS=\"" + number + "\"\r");
sim.println("Hey");
sim.println((char)26);// ASCII code of CTRL+Z
- Add ""\r" to my sendCommand("AT+CSCS="GSM"");
Let me know if there's anything else I can do
after sending the AT+CMGS command you need to wait for > or error message before attempting to send text terminated by CTRL/Z
e.g. using a SIM900 (none of my working SIMs fit the SIM800)
at+cgmm
SIMCOM_SIM900
OK
AT+CMGS="+44xxxxxxxxxxx"
> testing test
> test2 1234567890
>
+CMGS: 137
OK
I got it to work with this code:
#include <HardwareSerial.h>
HardwareSerial sim800(2); // Use UART2 for SIM800L
const int buttonPin = 15; // Pin where the button is connected
int buttonState = LOW; // Variable for reading the button status
int lastButtonState = LOW; // Variable to store the previous button state
unsigned long lastDebounceTime = 0; // The last time the button state was toggled
unsigned long debounceDelay = 50; // Debounce time in milliseconds
unsigned long commandTimeout = 3000; // Time to wait for command responses
unsigned long lastCommandTime = 0;
bool awaitingResponse = false;
String myNumber = "+6**********"; //change to your number
String myMessage = "My message"; //change to my message
void setup() {
pinMode(buttonPin, INPUT_PULLUP); // Enable internal pull-up resistor
sim800.begin(9600, SERIAL_8N1); // SIM800L baud rate, using GPIO16 (RX2) and GPIO17 (TX2)
Serial.begin(115200); // Serial monitor for debugging
Serial.println("Initializing SIM800L...");
// Initialize SIM800L
sendCommand("AT");
delay(1000); // Wait for the module to respond
sendCommand("AT+CSCS=\"GSM\"");
delay(1000);
sendCommand("AT+CMGF=1"); // Set SMS to text mode
delay(1000);
}
void loop() {
handleButton();
handleResponse();
}
void handleButton() {
int reading = digitalRead(buttonPin);
// Check if the button state has changed
if (reading != lastButtonState) {
lastDebounceTime = millis(); // Reset the debouncing timer
}
// If the button state has been stable for the debounce delay, take it as an actual press
if ((millis() - lastDebounceTime) > debounceDelay) {
// If the button state has changed
if (reading != buttonState) {
buttonState = reading;
// Only send SMS when the button is pressed (not released)
if (buttonState == LOW) { // LOW because INPUT_PULLUP means button press is LOW
Serial.println("Button pressed, sending SMS...");
sendSMS(myNumber, myMessage);
}
}
}
lastButtonState = reading; // Save the reading for the next loop iteration
}
void handleResponse() {
if (awaitingResponse) {
if (millis() - lastCommandTime > commandTimeout) {
// Time out handling
awaitingResponse = false;
Serial.println("Command timeout.");
}
while (sim800.available()) {
char c = sim800.read();
Serial.write(c); // Print response to Serial Monitor
}
awaitingResponse = false;
}
}
void sendCommand(String command) {
sim800.println(command);
Serial.print("Sending command: ");
Serial.println(command);
lastCommandTime = millis();
awaitingResponse = true;
}
void sendSMS(String number, String text) {
sendCommand("AT+CMGS=\"" + number + "\"\r");
waitForResponse();
sim800.print(text);
// waitForResponse();
delay(500);
sim800.println((char)26); // ASCII code for Ctrl+Z to send the SMS
delay(1000);
// waitForResponse();
}
void waitForResponse() {
lastCommandTime = millis();
awaitingResponse = true;
while (awaitingResponse) {
handleResponse();
}
}
void testCommunication() {
Serial.println("Testing communication with SIM800L...");
sendCommand("AT");
waitForResponse();
}
What I did different were:
- VDD of SIM800L v2 is connected to 3V of ESP32
- Added "\r" to
sendCommand("AT+CMGS=\"" + number + "\"");
- sendSMS function uses less waitForResponse function and more delays
- sendSMS function used
sim800.println((char)26);
instead of
sim800.write(26); // ASCII code for Ctrl+Z to send the SMS
void sendSMS(String number, String text) {
sendCommand("AT+CMGS=\"" + number + "\"\r");
waitForResponse();
sim800.print(text);
// waitForResponse();
delay(500);
sim800.println((char)26); // ASCII code for Ctrl+Z to send the SMS
delay(1000);
// waitForResponse();
}
My thoughts:
I think I could make it work without using delays because my entire code would freeze up using it. Also, I don't think "\r" is necessary as well as the HardwareSerial library since ESP32 has a 2nd serial port so I can do "serial2".
Let me know what you think about these.