Ir al contenido

Comunicaciones básicas: I2C, SPI, RS-485, serie TTL, Ethernet, MQTT y RTC

Lección 1: Comunicaciones básicas en un Raspberry PLC

Un Raspberry PLC rara vez trabaja solo. En una planta se sitúa entre sensores, variadores, otros controladores y la red IT, así que la primera habilidad que debes desarrollar es elegir la interfaz adecuada para cada enlace y probarla antes de montarla en una máquina. Esta lección recorre las interfaces del Raspberry PLC, con una prueba de banco para cada una.

Al final de esta lección sabrás:

  • Elegir entre I2C, SPI, RS-485, serie TTL y Ethernet para un enlace concreto.
  • Verificar los dos puertos RS-485 y conectar un Raspberry PLC a un M-Duino por RS-485.
  • Intercambiar datos por Ethernet con HTTP y MQTT, con autenticación activada en el broker.
  • Leer y ajustar el reloj de hardware (RTC) para que tus registros mantengan marcas de tiempo correctas sin red.
InterfazUso industrial típicoDistancia / topología
I2CPeriféricos integrados (RTC) y sensores cercanosCentímetros, bus compartido
SPIPeriféricos rápidos como ADC, pantallas o memoriasCentímetros, un maestro
RS-485Bus de campo: Modbus RTU, sensores, variadores, otros PLCHasta 1.200 m, multipunto, diferencial
Serie TTLEnlaces entre placas y módulos basados en comandosCorta, punto a punto, no apta para entornos ruidosos
EthernetModbus TCP, MQTT, HTTP, SSH, SCADARed en estrella, basada en switch

1. I2C

I2C (Inter-Integrated Circuit) es un bus serie que usa dos líneas: SCL para el reloj y SDA para los datos. Muchos dispositivos comparten las mismas dos líneas, cada uno con su propia dirección. En el Raspberry PLC también es el bus que usa el RTC integrado (consulta la sección 8), así que actívalo con sudo raspi-config (Interface Options) antes de empezar.

Para probarlo, conecta un acelerómetro Adafruit MMA8451 a los pines I2C y lee sus valores. Necesitas 4 cables: 2 para la alimentación y 2 para I2C.

Cableado de un acelerómetro Adafruit MMA8451 a los pines I2C del Raspberry PLC

Primero comprueba que el sensor responde en el bus. Debería aparecer en la dirección 0x1d (o 0x1c según el pin SA0):

sudo apt install i2c-tools
i2cdetect -y 1

Después instala la librería de Adafruit en un entorno virtual (las versiones recientes de Raspberry Pi OS no permiten instalaciones de pip a nivel de sistema) y ejecuta el ejemplo:

python3 -m venv --system-site-packages ~/venv
. ~/venv/bin/activate
pip install adafruit-circuitpython-mma8451
git clone https://github.com/adafruit/Adafruit_CircuitPython_MMA8451.git
cd Adafruit_CircuitPython_MMA8451/examples
python3 mma8451_simpletest.py

Deberías ver cómo cambian los valores de aceleración y la orientación al mover el sensor:

Salida en el terminal del ejemplo del MMA8451

2. SPI

SPI (Serial Peripheral Interface) es un bus síncrono con un maestro y uno o varios esclavos. Usa cuatro señales: SCK (reloj), MOSI (salida del maestro, entrada del esclavo), MISO (entrada del maestro, salida del esclavo) y SS (selección de esclavo). Es más rápido que I2C, por eso se usa para convertidores, pantallas y memorias.

3. Esquemas de conexión SPI

3.1. Esclavos independientes

Cada esclavo tiene su propia línea SS, mientras que SCK, MOSI y MISO son compartidas.

Maestro SPI con varios esclavos, cada uno con su propia línea de selección de esclavo

Este esquema conviene para pocos esclavos, porque cada esclavo añade una línea: líneas totales = 3 + número de esclavos.

3.2. Conexión en cascada (daisy chain)

Con muchos esclavos, el número de líneas puede volverse poco práctico. En una conexión daisy chain los esclavos comparten SCK y SS, y cada esclavo pasa los datos al siguiente hasta que vuelven al maestro.

SPI en daisy chain: MOSI atraviesa todos los esclavos y vuelve al maestro por MISO

Los datos tienen que atravesar todos los esclavos antes de que la transferencia se complete, así que la velocidad efectiva del bus es menor que con esclavos independientes.

4. RS-485

RS-485 es el caballo de batalla de la planta: señalización diferencial, topología multipunto y largas distancias, por eso Modbus RTU funciona sobre él (consulta el curso Primeros pasos con Modbus). El Raspberry PLC obtiene sus dos puertos RS-485 del chip SC16IS752, una UART de bajo consumo con alimentación de 5 V, corriente media de 300 uA y velocidad máxima de 2,5 Mbps. Cada puerto es half-duplex; para obtener un enlace full-duplex, usa un puerto para enviar y el otro para recibir.

Nota: el Raspberry PLC usa los puertos serie ttySC0 y ttySC1. En el Raspberry PI PLC v4 los puertos son ttySC2 y ttySC3.

Buenas prácticas de cableado de campo: usa par trenzado apantallado, mantén la polaridad A/B coherente en todo el bus, añade una resistencia de terminación de 120 Ω solo en cada extremo de la línea y conecta la pantalla en un solo extremo.

4.1. Prueba de verificación

Esta prueba comprueba los dos puertos RS-485 entre sí. Conecta A1+ con A2+ y B1- con B2-. Después crea un script:

nano testRS485.sh
chmod u+x testRS485.sh

y pega estas líneas:

#!/bin/bash

stty -F /dev/ttySC0 115200 raw -echo
stty -F /dev/ttySC1 115200 raw -echo

# Listen on ttySC1 for 3 seconds in the background
timeout 3 cat /dev/ttySC1 > /tmp/rs485.txt &
sleep 0.5

# Send "OK" from ttySC0
echo "OK" > /dev/ttySC0
wait

RESULT=$(cat /tmp/rs485.txt)
if [ "${RESULT}" = "OK" ]; then
  echo "RS-485 test passed: OK"
else
  echo "RS-485 test failed: received '${RESULT}'"
fi

Todo lo que se recibe en /dev/ttySC1 se guarda en /tmp/rs485.txt. El script envía "OK" desde /dev/ttySC0 y, si el cableado es correcto, /dev/ttySC1 lo recibe. timeout detiene la escucha por sí solo, así que no queda ningún proceso ejecutándose en segundo plano.

4.2. Conexión a un M-Duino

Cuando los dos puertos funcionen, conecta el Raspberry PLC a un PLC M-Duino (aquí, un M-Duino 54 ARA+). Harás que cada PLC envíe datos al otro y comprobarás que llegan. Conecta A+ del M-Duino a A+ del Raspberry PLC y B- a B-.

Conexión RS-485 entre un Raspberry PLC y un M-Duino

El sketch de Arduino empieza con este setup:

// Include Industrial Shields libraries
#include "RS485.h"

//// IMPORTANT: check switches configuration

void setup() {
    // Begin serial port
    Serial.begin(9600);
    // Begin RS485 port
    RS485.begin(115200);
}

Prueba 1: del M-Duino al Raspberry PLC. El M-Duino espera datos en su puerto serie y los reenvía por RS-485. Mientras tanto, el Raspberry PLC escucha durante 5 segundos e imprime lo que recibe. En el M-Duino:

void loop() {
  // wait bytes in the serial port
  if (Serial.available()) {
    byte tx = Serial.read();
    // and send it to the RS-485 port
    RS485.write(tx);
  }
}

En el Raspberry PLC, crea un nuevo script de bash:

#!/bin/bash

stty -F /dev/ttySC0 115200 raw -echo

# Listen for 5 seconds and print what arrives
timeout 5 cat /dev/ttySC0

Escribe un texto en el monitor serie del Arduino IDE y aparecerá en el terminal del Raspberry PLC.

Prueba 2: del Raspberry PLC al M-Duino. El Raspberry PLC envía "Hello World!" desde ttySC0 y el M-Duino lo imprime en el monitor serie. Añade estas líneas antes de setup() en el sketch del M-Duino:

int Period = 1000; // Data sending period in ms
unsigned long Time;
String rcv_message;

y usa este loop():

void loop() {
  // Print received data when available
  if (RS485.available()) {
    rcv_message = RS485.readString();
    Serial.println(rcv_message);
  }
}

En el Raspberry PLC, ejecuta este script:

#!/bin/bash
stty -F /dev/ttySC0 115200 raw -echo
echo "Hello World!" > /dev/ttySC0

5. Serial TTL

La serie TTL (niveles Transistor-Transistor Logic) es la señalización UART que tienen la mayoría de microcontroladores. Es barata y sencilla, full-duplex y punto a punto, lo que la hace ideal para comunicarse con un módulo basado en comandos en el mismo cuadro. Como no es diferencial como RS-232 o RS-485, evítala en largas distancias o en entornos con ruido eléctrico, donde las señales se degradan rápidamente. Para todo lo que salga del armario, usa RS-485.

Recuerda cruzar las líneas: RX del Raspberry PLC va a TX del otro dispositivo, y TX a RX.

5.1. Prueba por software

5.1.1. Enfoque Unix

Siguiendo la filosofía "todo es un archivo", puedes configurar /dev/ttyS0 (el puerto serie del Raspberry PLC) con stty y después leerlo y escribirlo como cualquier archivo:

stty -F /dev/ttyS0 raw speed 115200 -echo

Esto configura el modo raw (los bytes recibidos no se interpretan), una velocidad de 115200 baudios y desactiva el eco. A partir de ahí, cat y echo leen y escriben el puerto, y también puede hacerlo cualquier programa, por ejemplo:

with open("/dev/ttyS0", "rb") as f:
    while True:
        byte_s = f.read(1)  # read 1 byte
        if byte_s:
            print(byte_s)
        else:
            break

El programa imprime todos los caracteres disponibles en el buffer hasta que se vacía.

5.1.2. Enfoque con librería

El enfoque Unix no necesita dependencias, pero un sistema más complejo es más fácil de construir con una librería. En Python, pyserial gestiona el acceso al puerto serie en distintos sistemas operativos:

import serial

port = "/dev/ttyS0"
baudrate = 115200
serial_port = serial.Serial(port=port, baudrate=baudrate, bytesize=8, stopbits=1, timeout=1)

while True:
    try:
        n = serial_port.read(1)
        print(n)
    except KeyboardInterrupt:
        break

serial_port.close()

6. Ethernet

El Raspberry PLC tiene 2 puertos Ethernet: el de la propia Raspberry Pi y un segundo basado en el chip W5500. Ambos son accesibles para la CPU y se pueden usar para cualquier protocolo Ethernet (SSH, TCP, UDP, Modbus TCP, MQTT...). Sus direcciones IP por defecto son 10.10.10.20 para eth0 y 10.10.11.20 para eth1.

Tener dos puertos te permite separar redes, por ejemplo la red de máquina o de control en un puerto y la red de planta o IT en el otro. Mantener el tráfico de control alejado de la red IT es una buena práctica básica de ciberseguridad industrial.

6.1. HTTP

HTTP es el protocolo en el que se basa la web, y también es la forma más sencilla de integrar un PLC con API, dashboards y sistemas MES/ERP.

6.1.1. Peticiones con Python

Una petición GET con Python (define siempre un timeout para que un problema de red no pueda bloquear tu programa):

import requests

url = 'https://www.industrialshields.com'
x = requests.get(url, timeout=5)

print(x.text)

Guárdalo en un archivo (no lo llames http.py, entraría en conflicto con un módulo de Python) y ejecútalo con python3 myfile.py. Una petición POST:

import requests

url = 'https://www.industrialshields.com/'
obj = {'key': 'value'}
x = requests.post(url, json=obj, timeout=5)

print(x.text)

La variable x tiene varios atributos útiles:

  • links: devuelve los enlaces de la cabecera.
  • ok: True si status_code es menor que 400; en caso contrario, False.
  • reason: texto correspondiente al código de estado.
  • status_code: número que indica el estado (200 es OK, 404 es Not Found...).
  • text: contenido de la respuesta en Unicode.
  • url: URL de la respuesta.

6.1.2. Peticiones con bash

En bash, usa curl:

curl -X GET https://www.industrialshields.com/
curl -X POST -d "key1=value1&key2=value2" https://www.industrialshields.com/

7. MQTT

MQTT (Message Queuing Telemetry Transport) es el protocolo de mensajería estándar de OASIS para aplicaciones IoT e IIoT, sobre TCP/IP. Sigue un modelo de publicación/suscripción: un publicador envía datos en un topic, y cada suscriptor de ese topic los recibe. Publicadores y suscriptores nunca se comunican entre sí; un broker recibe los mensajes y los distribuye a los destinos correctos. Ese desacoplamiento es lo que hace que MQTT encaje bien para conectar muchas máquinas a una plataforma de datos.

Arquitectura MQTT: los publicadores envían mensajes a un broker, que los encamina por topic a los suscriptores

7.1. Eclipse Mosquitto

Eclipse Mosquitto es un broker de código abierto que implementa MQTT 5.0, 3.1.1 y 3.1, y también ofrece una librería en C para escribir clientes. Instala el broker y los clientes de línea de comandos en el Raspberry PLC:

sudo apt install mosquitto mosquitto-clients

Desde la versión 2.0, Mosquitto solo acepta por defecto conexiones del propio PLC. Para aceptar clientes por Ethernet, crea un archivo de configuración y exige usuario y contraseña; un broker abierto en una red de planta permite que cualquiera lea y publique hacia tus máquinas.

Primero crea el archivo de contraseñas (te pide la contraseña):

sudo mosquitto_passwd -c /etc/mosquitto/passwd plcuser

Después crea /etc/mosquitto/conf.d/network.conf con:

listener 1883 0.0.0.0
allow_anonymous false
password_file /etc/mosquitto/passwd

y reinicia el servicio:

sudo systemctl restart mosquitto.service

Ahora conecta un PC al Raspberry PLC por Ethernet (asigna al PC una dirección en la misma red, por ejemplo 10.10.10.22) y suscríbete a un topic:

mosquitto_sub -h 10.10.10.20 -u plcuser -P 'your-password' -t "topic"

Desde un segundo terminal, publica un mensaje:

mosquitto_pub -h 10.10.10.20 -u plcuser -P 'your-password' -t "topic" -m "hello this is a test"

El suscriptor muestra el mensaje:

mosquitto_pub publicando un mensaje y mosquitto_sub recibiéndolo

Si obtienes Connection refused, comprueba que el archivo con la línea listener está en /etc/mosquitto/conf.d/, que el servicio se ha reiniciado sin errores (systemctl status mosquitto) y que las direcciones IP están en la misma red. Para el tráfico que sale de la red de máquina, añade también TLS (puerto 8883).

8. RTC

El RTC (Real Time Clock) mantiene la hora del día. En un PLC esto importa porque los registros, las alarmas y los datos de producción necesitan una marca de tiempo fiable incluso cuando no hay red ni servidor NTP. Un RTC de hardware es útil porque:

  • Es más preciso que otros sistemas de reloj.
  • Es independiente de la CPU del sistema principal.
  • Tiene un bajo consumo, algo importante en sistemas embebidos.

El Raspberry PLC incluye un chip DS3231, que se comunica por I2C (así que I2C debe estar activado) y está respaldado por una pila de botón (CR1216 o CR1220). Para trabajar con el reloj de hardware, prueba estos comandos en un terminal:

  • Leer el reloj de hardware: sudo hwclock -r
  • Fijar una fecha personalizada y actualizar las marcas de tiempo en /etc/adjtime: sudo hwclock --set --date="2000-04-22 16:25"
  • Copiar la hora del sistema al RTC: sudo hwclock -w
  • Ajustar la hora del sistema desde el RTC: sudo hwclock -s
  • Más información: man hwclock

Siguiente paso

Ya tienes las piezas básicas para conectar un Raspberry PLC al campo (RS-485), a otros controladores y a la red de planta (Ethernet, MQTT). Continúa con la siguiente lección del curso o explora la gama Raspberry PLC en www.industrialshields.com.

Calificación
0 0

No hay comentarios por ahora.

para ser el primero en comentar.

1. Necesitas conectar un Raspberry PLC a un variador situado a 300 m en un armario con mucho ruido eléctrico. ¿Qué interfaz es la adecuada?
2. En la prueba de verificación RS-485, ¿qué pines conectas entre los dos puertos?