Guía completa: Cómo elegir un controlador industrial
Para enviar un SMS desde una Raspberry Pi con un SIM7600E-H 4G HAT, conecta el HAT por USB, abre su puerto AT (normalmente /dev/ttyUSB2) a 115200 bit/s y envía AT+CMGF=1 (modo texto), AT+CMGS="+número", el texto y Ctrl+Z. Para leer los mensajes recibidos, envía AT+CMGL="ALL" en modo texto.
La prueba de este post usó una Raspberry Pi 4, la placa que llevan los panel PC TouchBerry Pi 10,1", y un SIM7600E-H 4G HAT (LTE Cat-4, 4G, 3G y 2G, con GNSS) para enviar un SMS a un teléfono móvil y leer la respuesta. Al final tienes un script de Python que envía una alarma por SMS.
GSM, GPRS, LTE y SMS en resumen
| Término | Qué es |
|---|---|
| GSM | Global System for Mobile Communications, el estándar 2G para voz y SMS |
| GPRS | Datos por paquetes sobre GSM, para un acceso a internet lento |
| LTE Cat-4 | Categoría 4G del SIM7600E-H: hasta 150 Mbit/s de bajada y 50 Mbit/s de subida, según la red |
| SMS | Mensaje de texto corto. El módem lo gestiona con los comandos AT de 3GPP TS 27.005, en modo texto o en modo PDU |
Un SMS solo necesita cobertura y una SIM con servicio de SMS, no una tarifa de datos. Por eso se sigue usando para alarmas en instalaciones remotas.
Conecta el SIM7600E-H 4G HAT a la Raspberry Pi
Inserta la tarjeta SIM en el HAT, conecta la antena LTE y conecta el puerto USB del HAT a un puerto USB de la Raspberry Pi. Coloca los jumpers del HAT como indica su manual para el uso por USB.

Por USB, el HAT crea varios puertos /dev/ttyUSB, y uno de ellos acepta comandos AT. En nuestra prueba era /dev/ttyUSB2. La opción de puerto serie de raspi-config solo es necesaria si conectas el HAT por los pines UART del conector GPIO en lugar de por USB.
Abre el puerto AT y comprueba el módem
Instala screen, lista los puertos y abre el puerto AT:
sudo apt update
sudo apt install screen
ls /dev/ttyUSB*
screen /dev/ttyUSB2 115200
Escribe cada comando y pulsa Enter. El módem responde OK o ERROR. Para salir de screen, pulsa Ctrl+A y después K.
| Comando | Respuesta esperada | Qué comprueba |
|---|---|---|
AT | OK | El puerto y el módem responden |
AT+CPIN? | +CPIN: READY | La SIM está presente y no tiene el PIN pendiente |
AT+CSQ | +CSQ: 20,99 | Nivel de señal, de 0 a 31; 99 es desconocido |
AT+CREG? | +CREG: 0,1 o 0,5 | Registrado en la red propia (1) o en itinerancia (5) |
AT+CFUN=1 | OK | Funcionalidad completa del módem |
Envía un SMS con comandos AT
Activa el modo texto, indica el número en formato internacional y escribe el texto después del indicador >. Termina el texto con Ctrl+Z, no con Enter. El módem responde con +CMGS: y un número de referencia cuando la red acepta el mensaje.
AT+CMGF=1
OK
AT+CMGS="+34600000000"
> Escribe aquí tu texto
+CMGS: 12
OK
Lee los SMS recibidos
AT+CMGL lista los mensajes guardados en la SIM o en el módem. En modo texto acepta un filtro: "REC UNREAD", "REC READ", "STO UNSENT", "STO SENT" o "ALL".
AT+CMGF=1
OK
AT+CMGL="ALL"
+CMGL: 0,"REC READ","+346XXXXXXX6","","21/05/21,12:32:09+08"
HIGH Temperature
OK
Cada mensaje indica su índice, su estado, el remitente y la fecha y la hora. La última parte de la hora, +08, es la zona horaria en cuartos de hora: +08 es UTC+2.
AT+CMGR=0lee solo el mensaje con índice 0.AT+CMGD=0lo borra. Borra los mensajes que ya hayas procesado, porque la memoria de la SIM es pequeña.AT+CNMI=2,1hace que el módem avise de cada mensaje nuevo con+CMTI: "SM",<index>, así un programa no necesita consultar.
Envía una alarma por SMS desde un script de Python
En una automatización, un programa envía el SMS cuando empieza una alarma. Este script usa pyserial, comprueba la SIM y la red, y envía un mensaje:
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
Salida con nuestro módem de prueba:
OK
+CPIN: READY
OK
+CREG: 0,1
OK
OK
>
+CMGS: 12
OK
Qué hemos probado. El script se ejecutó con Python 3.13 y pyserial 3.5 en Linux, contra un módem simulado en un enlace serie virtual que responde a los comandos de este post como en el modo texto de 3GPP TS 27.005. El módem simulado recibió los comandos y el texto en el orden correcto. No hemos enviado un SMS real para esta actualización: en un módem real, el eco de los comandos también aparece en la salida.
Si el SMS no sale
| Qué ves | Causa habitual | Qué revisar |
|---|---|---|
No hay ningún puerto /dev/ttyUSB | El HAT no se detecta por USB | Cable USB, jumpers, alimentación del HAT, lsusb |
No hay respuesta a AT | Puerto o velocidad incorrectos | Prueba los otros puertos ttyUSB a 115200 |
+CPIN: SIM PIN | La SIM pide su PIN | AT+CPIN="1234" con tu PIN, o quita el PIN con un teléfono |
+CREG: 0,2 o 0,3 | Buscando red o registro denegado | Antena, cobertura, y que la SIM esté activa |
+CMS ERROR después de Ctrl+Z | La red ha rechazado el mensaje | Formato del número, servicio de SMS de la SIM, centro de servicio con AT+CSCA? |
SMS y 4G en un proyecto industrial
El SMS es un buen canal para unas pocas alarmas cuando no hay internet. Para datos, lo habitual es MQTT o HTTPS sobre la conexión de datos 4G. Los controladores de Industrial Shields tienen sus propias opciones celulares: el Raspberry PLC admite placas de expansión LTE Cat 4 o NB-IoT/LTE-M, el TouchBerry Pi admite una expansión 4G LTE, y el ESP32 PLC también puede conectarse por 4G. Los comandos SMS de 3GPP TS 27.005 son estándar, así que la secuencia de este post es la misma. El nombre del puerto y la configuración cambian con cada módulo: consulta su guía de usuario.
Alarmas que llegan al teléfono. En el caso de estudio de la alarma de habitación de hospital, un PLC enciende las alarmas locales y envía la llamada a las enfermeras por Telegram. En el caso de estudio del vagón de tren, un ESP32 PLC 57R envía sus datos por 4G LTE-M.
Lee el caso de la alarma de hospitalLee el caso del vagón de tren
Preguntas frecuentes sobre SMS con una Raspberry Pi
¿Necesito una tarifa de datos para enviar SMS?
No. Necesitas una SIM con servicio de SMS y cobertura. La tarifa de datos solo hace falta para el acceso a internet.
¿Qué puerto ttyUSB es el puerto AT?
En nuestra prueba, /dev/ttyUSB2. Si no responde, prueba los otros puertos ttyUSB con AT.
¿Por qué el mensaje no se envía cuando pulso Enter?
Porque en modo texto el módem espera Ctrl+Z (0x1A) para terminar el texto. Enter solo añade una línea nueva al mensaje. Esc lo cancela.
¿Un SMS recibido puede iniciar una acción en el PLC?
Sí. Un programa lee los mensajes nuevos con AT+CMGL o +CMTI, comprueba el remitente y el texto, y después actúa. Acepta órdenes solo de números conocidos.
¿Modo texto o modo PDU?
El modo texto es más fácil de leer y de probar. El modo PDU es necesario en casos especiales, como mensajes largos en varias partes o alfabetos fuera del alfabeto GSM.