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();
}
}
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 </>
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();
}
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
#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".