Skip to Content

How to send and receive SMS with Raspberry Pi automation

AT commands and a Python script with a SIM7600E-H 4G HAT
May 19, 2021 by
How to send and receive SMS with Raspberry Pi automation
Boot & Work Corp. S.L, Fernandez Queralt Martinez

Complete guide: Choosing an industrial controller

To send an SMS from a Raspberry Pi with a SIM7600E-H 4G HAT, connect the HAT by USB, open its AT port (usually /dev/ttyUSB2) at 115200 bit/s and send AT+CMGF=1 (text mode), AT+CMGS="+number", the text and Ctrl+Z. To read the received messages, send AT+CMGL="ALL" in text mode.

The test of this post used a Raspberry Pi 4, the board inside the TouchBerry Pi 10.1" panel PC, and a SIM7600E-H 4G HAT (LTE Cat-4, 4G, 3G and 2G, with GNSS) to send an SMS to a mobile phone and read the answer. At the end you have a Python script that sends an alarm by SMS.

GSM, GPRS, LTE and SMS in short

TermWhat it is
GSMGlobal System for Mobile Communications, the 2G standard for voice and SMS
GPRSPacket data over GSM, for slow internet access
LTE Cat-44G category of the SIM7600E-H: up to 150 Mbit/s down and 50 Mbit/s up, depending on the network
SMSShort text message. The modem handles it with the AT commands of 3GPP TS 27.005, in text mode or PDU mode

An SMS needs only network coverage and a SIM with SMS service, not a data plan. That is why it is still used for alarms in remote sites.

Connect the SIM7600E-H 4G HAT to the Raspberry Pi

Insert the SIM card in the HAT, connect the LTE antenna, and connect the USB port of the HAT to a USB port of the Raspberry Pi. Set the jumpers of the HAT as its user manual says for USB use.

Raspberry Pi 4 connected with a USB cable to the USB port of the SIM7600X 4G HAT; red arrows mark the jumpers to check
Raspberry Pi 4 connected by USB to the SIM7600X 4G HAT, with the antennas and the jumpers to check.

Over USB the HAT creates several /dev/ttyUSB ports, and one of them takes AT commands. In our test it was /dev/ttyUSB2. The serial port option of raspi-config is only needed if you connect the HAT through the UART pins of the GPIO header instead of USB.

Open the AT port and check the modem

Install screen, list the ports and open the AT port:

sudo apt update
sudo apt install screen
ls /dev/ttyUSB*
screen /dev/ttyUSB2 115200

Type each command and press Enter. The modem answers OK or ERROR. To leave screen, press Ctrl+A and then K.

CommandExpected answerWhat it checks
ATOKThe port and the modem answer
AT+CPIN?+CPIN: READYThe SIM is present and has no PIN pending
AT+CSQ+CSQ: 20,99Signal level, from 0 to 31; 99 is unknown
AT+CREG?+CREG: 0,1 or 0,5Registered on the home network (1) or roaming (5)
AT+CFUN=1OKFull functionality of the modem

Send an SMS with AT commands

Set text mode, give the number in international format and write the text after the > prompt. End the text with Ctrl+Z, not with Enter. The modem answers with +CMGS: and a reference number when the network accepts the message.

AT+CMGF=1
OK
AT+CMGS="+34600000000"
> Type your text here
+CMGS: 12

OK

Read the received SMS

AT+CMGL lists the messages stored in the SIM or in the modem. In text mode it takes a filter: "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT" or "ALL".

AT+CMGF=1
OK
AT+CMGL="ALL"
+CMGL: 0,"REC READ","+346XXXXXXX6","","21/05/21,12:32:09+08"
HIGH Temperature

OK

Each message gives its index, its status, the sender, and the date and time. The last part of the time, +08, is the time zone in quarters of an hour: +08 is UTC+2.

  • AT+CMGR=0 reads only the message with index 0.
  • AT+CMGD=0 deletes it. Delete the messages that you have processed, because the SIM memory is small.
  • AT+CNMI=2,1 makes the modem announce each new message with +CMTI: "SM",<index>, so a program does not need to poll.

Send an SMS alarm from a Python script

In an automation, a program sends the SMS when an alarm starts. This script uses pyserial, checks the SIM and the network, and sends one message:

import time

import serial  # pyserial

PORT = "/dev/ttyUSB2"     # AT port of the SIM7600 over USB, check with: ls /dev/ttyUSB*
NUMBER = "+34600000000"   # destination in international format
TEXT = "PLC alarm: high temperature in line 2"


def read_until(ser, tokens, timeout):
    """Read the modem answer until one of the tokens arrives or the time runs out."""
    end = time.monotonic() + timeout
    answer = b""
    while time.monotonic() < end:
        answer += ser.read(ser.in_waiting or 1)
        if any(token in answer for token in tokens):
            break
    return answer.decode(errors="replace").strip()


def command(ser, cmd, wait_for=b"OK", timeout=5):
    ser.write(cmd.encode() + b"\r")
    return read_until(ser, (wait_for, b"ERROR"), timeout)


with serial.Serial(PORT, 115200, timeout=0.2) as ser:
    print(command(ser, "AT"))
    print(command(ser, "AT+CPIN?"))    # +CPIN: READY means the SIM is unlocked
    print(command(ser, "AT+CREG?"))    # +CREG: 0,1 (home) or 0,5 (roaming) means registered
    print(command(ser, "AT+CMGF=1"))   # SMS text mode
    print(command(ser, f'AT+CMGS="{NUMBER}"', wait_for=b">"))
    ser.write(TEXT.encode() + b"\x1a")  # Ctrl+Z (0x1A) ends the text and sends it
    print(read_until(ser, (b"OK", b"ERROR"), 60))  # +CMGS: <reference> and OK
sudo apt install python3-serial
python3 send_sms.py

Output against our test modem:

OK
+CPIN: READY

OK
+CREG: 0,1

OK
OK
>
+CMGS: 12

OK

What we tested. The script ran with Python 3.13 and pyserial 3.5 on Linux, against a simulated modem on a virtual serial link that answers the commands of this post as in 3GPP TS 27.005 text mode. The simulated modem received the commands and the text in the right order. We did not send a real SMS for this update: on a real modem, the command echo also appears in the output.

If the SMS does not go out

What you seeUsual causeWhat to check
No /dev/ttyUSB portThe HAT is not detected by USBUSB cable, jumpers, power of the HAT, lsusb
No answer to ATWrong port or wrong speedTry the other ttyUSB ports at 115200
+CPIN: SIM PINThe SIM asks for its PINAT+CPIN="1234" with your PIN, or remove the PIN with a phone
+CREG: 0,2 or 0,3Searching or registration deniedAntenna, coverage, and that the SIM is active
+CMS ERROR after Ctrl+ZThe network refused the messageNumber format, SMS service of the SIM, service center with AT+CSCA?

SMS and 4G in an industrial project

SMS is a good channel for a few alarms when there is no internet. For data, the usual way is MQTT or HTTPS over the 4G data connection. Industrial Shields controllers have cellular options of their own: the Raspberry PLC takes LTE Cat 4 or NB-IoT/LTE-M expansion boards, the TouchBerry Pi takes a 4G LTE expansion, and the ESP32 PLC can also connect over 4G. The SMS commands of 3GPP TS 27.005 are standard, so the sequence of this post is the same. The port name and the setup change with each module: check its user guide.

Alarms that reach the phone. In the hospital room alarm case study, a PLC turns on the local alarms and sends the call to the nurses on Telegram. In the railway carriage case study, an ESP32 PLC 57R sends its data over 4G LTE-M.

Read the hospital alarm case studyRead the railway case study

FAQ about SMS with a Raspberry Pi

Do I need a data plan to send SMS?

No. You need a SIM with SMS service and network coverage. A data plan is only needed for internet access.

Which ttyUSB port is the AT port?

In our test, /dev/ttyUSB2. If it does not answer, try the other ttyUSB ports with AT.

Why does the message not send when I press Enter?

Because in text mode the modem waits for Ctrl+Z (0x1A) to end the text. Enter only adds a new line to the message. Esc cancels it.

Can a received SMS start an action in the PLC?

Yes. A program reads the new messages with AT+CMGL or +CMTI, checks the sender and the text, and then acts. Accept commands only from known numbers.

Text mode or PDU mode?

Text mode is easier to read and to test. PDU mode is needed for special cases, such as long messages in several parts or alphabets outside the GSM alphabet.

​Search in our Blog

How to send and receive SMS with Raspberry Pi automation
Boot & Work Corp. S.L, Fernandez Queralt Martinez May 19, 2021
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

PLC Comparison