Ir al contenido

Crear variables externas en OpenPLC para interactuar con una extensión Arduino

Comparte valores BOOL, UINT y STRING entre Ladder y C++
8 de enero de 2025 por
Boot & Work Corp. S.L, Arnau Tena

Guía completa: OpenPLC con PLC industriales

Una variable externa en OpenPLC es una variable que comparten el diagrama Ladder y el código C++ de una extensión Arduino. Declárala en la tabla de variables de Ladder con la clase External, declara una variable con el mismo nombre y tipo en la extensión Arduino con un valor inicial, y después léela o escríbela por su nombre en sketch_loop(). Los valores BOOL y UINT se asignan directamente; un STRING necesita su longitud y sus caracteres.

Las extensiones Arduino permiten añadir C++ a un proyecto de OpenPLC para lo que Ladder no puede hacer: una petición HTTP, una función de una librería, el protocolo de un sensor. Las variables externas son el puente entre las dos partes. Esta guía muestra los tres tipos más habituales en un M-Duino 42+, con código que compila con los tipos de OpenPLC, y cómo leer una entrada del PLC directamente desde la extensión.

Antes de empezar

Versión del Editor. Las extensiones Arduino y las capturas de esta guía son del OpenPLC Editor clásico, para el que se hizo el mod de Industrial Shields en 2024. OpenPLC Editor v4 es una aplicación nueva: comprueba que tu modelo de PLC y la extensión Arduino están disponibles en ella antes de empezar un proyecto.

Cómo declarar una variable externa

  1. En la tabla de variables de Ladder, añade una variable y pon su clase en External.
Tabla de variables de OpenPLC con una variable BOOL llamada extVar de clase External
  1. Crea una extensión Arduino: haz clic en el icono + gris del árbol del proyecto y selecciona Arduino extension.
Árbol del proyecto del OpenPLC Editor con el menú + gris abierto y Arduino extension seleccionado
  1. En la tabla de variables de la extensión, declara la misma variable, con el mismo nombre y tipo, y dale un valor inicial.
Tabla de variables de la extensión Arduino con extVar declarada como BOOL con valor inicial false

La variable ya está disponible en los dos sitios. En la extensión la usas por su nombre: el Editor genera un #define que apunta el nombre a la variable del PLC, así que extVar = true; escribe la misma memoria que lee el diagrama Ladder.

Cuándo se ejecuta el código de la extensión

La extensión tiene dos funciones. sketch_setup() se ejecuta una vez al arrancar, después de que OpenPLC haya configurado las entradas y salidas. sketch_loop() se ejecuta una vez por ciclo de scan, después de que el PLC haya leído las entradas, resuelto la lógica Ladder y escrito las salidas. De ahí salen tres consecuencias:

  • Un valor escrito por la extensión llega a la lógica Ladder en el scan siguiente.
  • Un delay() o una espera larga dentro de sketch_loop() retrasa todo el scan del PLC. Para temporizar, usa millis().
  • No escribas desde la extensión en una salida que también tenga una variable con dirección en Ladder (por ejemplo %QX0.0): OpenPLC la vuelve a escribir en cada scan. Pasa el valor a Ladder con una variable externa, como en los ejemplos de abajo.

Qué tipo de C corresponde a cada tipo de OpenPLC

OpenPLC guarda las variables como tipos IEC 61131-3. En la extensión son tipos de C normales, salvo STRING, que es una estructura.

Tipo de OpenPLCTipo de C en la extensiónRango
BOOLuint8_tfalse (0) o true (1)
INTint16_t-32768 a 32767
UINT, WORDuint16_t0 a 65535
DINTint32_t-2147483648 a 2147483647
REALfloatComa flotante de 32 bits
STRINGestructura con len y bodyHasta 126 caracteres

Variables externas BOOL

BOOL es el caso más sencillo: asigna true o false en la extensión. En este ejemplo el diagrama Ladder copia ex_bool en la salida digital Q0_0 (%QX0.0) y la extensión la activa.

Variables Ladder Q0_0 en %QX0.0 y ex_bool de clase External, con ex_bool conectada a la bobina Q0_0
// Arduino extension: turn on the output while the extension says so
void sketch_setup()
{

}

void sketch_loop()
{
    ex_bool = true;
}

Variables externas UINT y escalado analógico

Los valores UINT también se asignan directamente, pero los analógicos hay que escalarlos. OpenPLC usa de 0 a 65535 para cualquier señal analógica, mientras que analogRead() en un M-Duino devuelve de 0 a 1023. Este ejemplo lee la entrada analógica I0_7 en la extensión, la multiplica por 64 y la pasa al diagrama Ladder, que la envía a la salida analógica A0_5 (%QW0).

Variables Ladder A0_5 en %QW0 y ext_uint de clase External, con ext_uint conectada a A0_5
// Arduino extension: copy analog input I0_7 to the Ladder variable
void sketch_setup()
{
    pinMode(I0_7, INPUT);
}

void sketch_loop()
{
    ext_uint = analogRead(I0_7) * 64;   // 0 to 1023 becomes 0 to 65472
}

Leer la entrada en la extensión es también la forma de usar un pin directamente desde C++. Aquí la entrada no tiene variable con dirección en Ladder, así que la extensión es la única que la lee. Usa estos factores para convertir entre las funciones del PLC y el rango de OpenPLC:

Familia de PLCDe analogRead() a OpenPLCDe OpenPLC a analogWrite()
M-Duino y Ardboxmultiplicar por 64dividir entre 256
ESP32 PLC (todos los modelos salvo el 14)multiplicar por 32dividir entre 16
ESP32 PLC 14multiplicar por 16dividir entre 16

Por ejemplo, para mover una salida analógica de un M-Duino a partir de un UINT que escribe Ladder, usa analogWrite(A0_5, ext_uint / 256); en la extensión y no des dirección a esa salida en Ladder.

Variables externas STRING

Un STRING es una estructura con dos campos: len, el número de caracteres, y body, un array de hasta 126 caracteres. Para escribirlo copias los caracteres en body y fijas len. En este ejemplo la extensión escribe "Hello" y el diagrama Ladder activa Q0_0 cuando ext_str es igual a 'Hello'.

Diagrama Ladder con un bloque EQ que compara la constante 'Hello' con el STRING externo ext_str y activa la bobina Q0_0
// Arduino extension: write "Hello" into a STRING variable
void sketch_setup()
{

}

void sketch_loop()
{
    const char *str = "Hello";
    size_t n = strlen(str);
    if (n > STR_MAX_LEN) {
        n = STR_MAX_LEN;               // the body holds 126 characters
    }
    memcpy(ext_str.body, str, n);      // copy the characters
    ext_str.len = n;                   // then set the length
}

Aquí importan dos detalles. En C un texto va entre comillas dobles ("Hello"); las simples son para un solo carácter, y 'Hello' no compila como cadena. En Ladder es al revés: IEC 61131-3 escribe las cadenas entre comillas simples. OpenPLC usa len para saber dónde acaba el texto, así que body no necesita un cero final.

Coincidencia exacta. En la librería de OpenPLC, EQ entre dos STRING compara solo tantos caracteres como tiene el más corto, así que una cadena vacía es igual a 'Hello'. Si la coincidencia debe ser exacta, comprueba también que LEN(ext_str) sea 5.

Errores habituales

Qué vesCausa probableQué hacer
La compilación falla por una variable no declaradaLa variable es External en Ladder pero falta en la tabla de la extensión, o el nombre no coincideDeclárala en la extensión con el mismo nombre y tipo
La salida analógica apenas se mueveEl valor de analogRead() (0 a 1023) no se ha escaladoMultiplica por el factor de tu familia de PLC
Una salida activada desde la extensión se vuelve a apagarLa salida también tiene dirección en Ladder y OpenPLC la reescribe en cada scanPasa el valor por una variable externa o quita la dirección
El scan del PLC se vuelve lentodelay() dentro de sketch_loop()Temporiza con millis()
La comparación de STRING da true antes de tiempoEQ solo compara la cadena más cortaCompara también LEN()

Ladder y C++ en proyectos reales

Mezclar un programa de PLC con C++ es habitual cuando un proyecto necesita un protocolo o una librería que el lenguaje del PLC no tiene, como en HTTP en M-Duino con OpenPLC. Si la parte en C++ crece, el Arduino IDE con las placas de Industrial Shields da acceso directo a todas las librerías. La guía de OpenPLC compara las dos opciones, y cómo elegir un controlador industrial te ayuda si aún estás eligiendo el hardware.

Mira cómo un PLC ejecuta una secuencia antes de escribir la tuya. En el simulador de planta de proceso, un PLC arranca una turbina o una bomba paso a paso y la para de forma segura. Cambia las condiciones y observa cómo cada paso espera sus señales.

Abrir el simulador de planta de procesoConsulta tu proyecto con un ingeniero

Preguntas frecuentes sobre variables externas en OpenPLC

¿Qué diferencia hay entre una variable Local, Global y External?

Una variable Local pertenece a un programa. Una Global pertenece al recurso y la pueden usar todos los programas. External le dice a un programa que la variable está declarada en otro sitio, aquí en la extensión Arduino, y que debe usar esa.

¿La extensión puede leer una variable que escribe Ladder?

Sí. Se comparte en los dos sentidos. La extensión ve el valor escrito por Ladder en el mismo scan, porque sketch_loop() se ejecuta después de la lógica.

¿Puedo usar variables externas REAL o DINT?

Sí. En la extensión son float e int32_t y se asignan directamente, como BOOL y UINT.

¿Qué longitud puede tener un STRING?

Hasta 126 caracteres, el STR_MAX_LEN por defecto de OpenPLC. Limita la copia a ese tamaño, como hace el ejemplo.

¿Puedo usar las librerías de Industrial Shields en la extensión?

Sí. Con el mod de Industrial Shields, la extensión se compila para el modelo de PLC que seleccionas, así que puedes usar sus nombres de pin y sus librerías como en el Arduino IDE.

Buscar en nuestro blog

Boot & Work Corp. S.L, Arnau Tena 8 de enero de 2025
Compartir esta publicación
Etiquetas

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.

Comparativa de PLCs