sábado, octubre 08, 2016

Cuando Arduino viene al rescate

La crisis. Sin muchas ganas de gastar dólares y hay problemas que resolver donde tiempo atrás no dudaríamos en colocar un PLC pequeño que nos sacara la pata del barro. Aquí es donde ideas ingeniosas como el uso de una tarjeta Arduino vienen a hacernos el día.

Un Arduino es una plataforma electrónica abierta basada en hardware y software fácil de usar. Se supone que está dirigida a cualquiera que le interese un proyecto donde haga falta un controlador de bajo coste y que nos permita interactuar con dispositivos de campo como motores o sensores de todo tipo. Hay por allí muchas otras plataformas, como el famoso Raspberry por ejemplo, pero creo que Arduino es uno de los más poderosos y populares además de barato.

Supongamos que tenemos en nuestra planta por ejemplo un filtro manga que queremos poner a funcionar y que necesitamos que algo haga operar diez válvulas solenoides que permiten que aire comprimido sople las mangas en secuencia cada cierto tiempo. ¿Podemos hacer eso con un PLC? Desde luego que si, pero con un Arduino es mucho más económico y hasta sencillo.

Lo primero es elegir el Arduino. Creo que lo mejor es tratar de conseguir un Arduino que no sea de esos chinos extremadamente baratos que hay por ahí. El Arduino Uno hecho en Italia es uno de los mejores y más confiables, así que es una buena opción ya que no necesitaremos mayor cosa para esta aplicación sencilla.

El Arduino trae 12 puntos digitales que pueden ser configurados como entradas o salidas así que bastan para cubrir las diez válvulas de nuestro proyecto. También tiene seis entradas analógicas que no usaremos. Y si tuviéramos disponible un interruptor de diferencial de presión que nos permitiera saber si el filtro está muy sucio y tenemos que soplarlo también serviría ya que tenemos dos puntos digitales de reserva.

El Arduino no tiene la capacidad de manejar la carga de las válvulas solenoides así que le podemos colocar módulos de relevadores electromecánicos o de estado sólido que también se consiguen en el mercado a muy bajo precio. El plano de conexiones vendría siendo como luce la figura (click para agrandar).


Para la alimentación solamente nos basta una fuente de poder que nos de los 5 VDC que requiere el Arduino. Dependiendo del ambiente, si es muy húmedo o muy polvoriento por ejemplo, podremos decidir la calidad de esta fuente.

Ahora veamos como se programa.

El Arduino trae su propio ambiente de desarrollo, el cual es gratis y podemos bajar de la página del proyecto. Bajamos este ambiente de desarrollo y lo instalamos.

Una vez instalado el sistema conectamos nuestra placa arduino con el puerto USB y creamos un nuevo programa que en jerga de arduino llamamos "sketch". Este sketch nuevo contiene dos funciones, una llamada setup y otra llamada loop. En setup colocamos lo referente a la inicialización de nuestro programa y en loop lo que queremos que el arduino haga en modo de lazo infinito, es decir, un programa tipo PLC que se ejecutará eternamente en barridos secuenciales.

void setup() {

  // put your setup code here, to run once:

}

void loop() {

  // put your main code here, to run repeatedly:

}


Nada del otro mundo como vemos.

En nuestro caso en particular el código final, usando la librería para escribir en el puerto serial para mensajes de diagnóstico interesantes, sería algo como esto:


const long timer1 = 2000; // tiempo en ms entre soplado de cada válvula
const long timer2 = 120; // tiempo en seg entre soplado del conjunto completo
const long timer3 = 400; // tiempo en ms de soplado de cada válvula

// la función setup inicializa las variables en el inicio

void setup() {

  // inicializar puerto serial para mensajes

  Serial.begin(9600);
  Serial.println("Programa de control de soplado del Filtro Manga");
  Serial.println("Rev 1.1");
  Serial.print("Timer1 = ");
  Serial.println(timer1);
  Serial.print("Timer2 = ");
  Serial.println(timer2);
  Serial.print("Timer3 = ");
  Serial.println(timer3);


  // inicializar todos los pins como salidas, del 2 al 11 son las válvulas

  for (int thisPin = 2; thisPin < 14; thisPin++) {
    pinMode(thisPin, OUTPUT);
  }
}

// la función loop corre en modo de lazo infinito

void loop() {

// inicio ciclo de soplado

  Serial.println("Soplando...");
  for (int thisPin = 2; thisPin < 12; thisPin++) {
    digitalWrite(thisPin, HIGH);
    digitalWrite(13, HIGH);
    Serial.print("V: ");
    Serial.println(thisPin - 1);
    delay(timer3);
    digitalWrite(thisPin, LOW);
    digitalWrite(13, LOW);
    delay(timer1);
  }

// fin de ciclo de soplado

Serial.println("Inicio pausa...");

for (int tiempo = 0; tiempo <= timer2; tiempo++) {
  Serial.println(tiempo);
  digitalWrite(13, HIGH);
  delay(50);
  digitalWrite(13, LOW);
  delay(950);
}

}


Finalmente compilamos y lo subimos al arduino y listo. Armamos nuestro sistema y lo probamos.

Una solución interesante y económica.


miércoles, octubre 05, 2016

Leyendo datos con pymodbus3

Uno de los protocolos más populares y viejos del mundo de la automatización industrial es Modbus. Es un protocolo sencillo que nos permite leer datos de una miríada de dispositivos industriales tales como controladores de procesos, PLC's y sensores y medidores de todo tipo. Modbus ha estado ya unas cuantas décadas y ha evolucionado en lo que yo llamo tres sabores principales: ASCII, RTU y TCP. Los dos primeros funcionan sobre conexiones seriales tipo RS-232, RS-422 o RS-485 y el último, el TCP, funciona usando Ethernet como medio de conexión.

Pymodbus3 es una biblioteca, o librería como también la llamamos, de Python que nos permite usar el protocolo a alto nivel sin entrar en los detalles de programación de bajo nivel.

Supongo que si están leyendo esto ya de alguna manera conocen el protocolo y saben algo de Python. Así que al grano. Vamos a hacer un pequeño programa que lea datos y los escriba a algún lugar, por ejemplo un archivo texto.

Lo primero es asegurarnos que tengamos Python instalado, por ejemplo python 3.4 para que sea compatible con pymodbus3. Luego instalamos pymodbus3 con pip de la manera usual.

Las primeras líneas del programa serían algo así:

from pymodbus3.client.sync import ModbusTcpClient as ModbusClient

client = ModbusClient('localhost', port=502)
client.connect()

El script supone que estoy usando el protocolo ModbusTCP, por lo que el cliente en cuestión estaría leyendo de un PLC, o servidor Modbus, ubicado en este caso en mi pc (localhost). ModbusTCP usa el puerto TCP 502, así que eso es lo que significa el segundo parámetro del constructor de la clase.

Para poder simular una conexión ModbusTCP uso mod_RSsim. Este simulador si lo instale en mi pc puede emular un PLC sin problemas y me conecto vía el puerto 502.

Luego de creado el cliente podemos leer de esta manera.

lectura = client.read_holding_registers(450, 10)

Esto guardaría en la variable lectura una lista de 10 valores a partir del holding register con dirección 450. Pymodbus3 tiene funciones para leer y escribir todo tipo de variables Modbus y podemos ver un ejemplo para un cliente asíncrono en la documentación.

Quedaría empaquetar el código de manera que podamos interactuar con el programa, guardar los datos en algún lado y añadir el manejo de excepciones por si hay algún problema de comunicaciones. Pero eso sería materia de otro post.



Python en automatización industrial, un caso concreto

Una de las cosas que hago para ganarme la vida es servir de consultor en automatización industrial. Justo estaba en esos menesteres hace poco cuando me topé con un problema de esos a que nos tiene acostumbrados la crisis económica de nuestros golpeados clientes. Nuestro cliente en cuestión sufrió una falla irrecuperable de un pequeño sistema scada que tenían conectado a una red de controladores PLC en su planta de energía. Sin el scada funcionando, sin recursos como para poner en funcionamiento el ahora muy costoso sistema de adquisición de datos se vieron en la necesidad de empezar a buscar alternativas que al menos pudieran devolverles algo de la funcionalidad perdida. Y aquí es donde la imaginación y tecnologías libres como la de python vienen a jugar un papel importante.

El problema se centraba en leer datos a través de una interfaz serial RS-232 usando el protocolo Modbus RTU, luego guardar esos datos, o más bien guardarlos solamente si alguno de esos datos cambiaba de estado, y finalmente tener alguna herramienta que pudiera analizar los datos guardados para graficar algunas cosas y hacer algunos cálculos de índices de mantenimiento que tenían que ver con las máquinas que controlaban los PLC.

Debido a que no eran muchos los datos a leer y a que era solamente una tabla de un solo PLC decidimos desarrollar unos scripts en python para rapidamente tener un prototipo funcional para mostrarlo al cliente.

Un rato en google y desarrollamos un ambiente de desarrollo en una laptop en windows de esta manera:
  1. instalamos python 3.4 (esta versión es la que mejor funciona con todo lo que uso en este proyecto)
  2. con pip le agregamos virtualenv para crear un ambiente virtual limpio, en mi caso tengo varias versiones de python instaladas y lo más sano es usar virtualenv.
  3. ya con virtualenv creamos el directorio de trabajo y activamos.
  4. instalamos pymodbus3 usando pip.
  5. instalamos también pymongo para la base de datos usando pip
  6. finalmente instalamos PyGObject for Windows que por cierto a la fecha solamente funciona con python 3.4, por eso es que uso esta versión y no la última.
La arquitectura de mi pequeño sistema es muy sencilla. No es más que un script que interroga al PLC usando pymodbus3 y que escribe a MongoDB si detecta algún cambio. En MongoDB lo que se guardarán son eventos, es decir documentos con la información del estado de la variable y la fecha y hora del evento. Siendo MongoDB una base de datos NoSQL facilita la interacción rápida con los eventos sin mucho esfuerzo.

La otra parte de la ecuación es una pequeña aplicación que me permita leer los eventos almacenados en MongoDB y que le permita a los operadores interactuar con los datos. Hay dos caminos para hacer dicha aplicación. Pudiera ser una aplicación con una interfaz web, lo cual requiere alguito más de esfuerzo en el desarrollo gráfico y todo eso, o pudiéramos usar una clásica aplicación de ventanas lo cual es más rápido. Nos decidimos por lo segundo por aquello de la rapidez.

De todos los entornos gráficos de ventanas para python que hay por ahí el que nos parece más sólido es el que usa Glade para desarrollar las ventanas y Gtk+ para cargarlas al script python. Hay en la red muchos tutoriales, aunque creo que el mejor es el Python Gtk+3 Tutorial. El tutorial es bastante claro sobre como usar Gtk+ primero y por último como usar Glade. Lo bueno es que podemos tener Glade abierto y hacer cambios en la ventana y correr el script y de inmediato ver que pasó. Glade solamente crea un archivo xml que lo lee el script para crear los objetos que le pasará a Gtk+ para que los dibuje en pantalla y maneje los eventos.

En resumen, Python ofrece un sistema rápido de desarrollo para problemas como el descrito. Las librerías de funciones son extensas y el soporte en la red por parte de los desarrolladores es bastante bueno. Los scripts desarrollados en este proyecto en particular son bastante sólidos, manejan todo tipo de excepciones que sabemos que pueden presentarse (como fallas de comunicación porque se rompió el cable que va al PLC) y pueden modificarse en la misma planta ya que el código es abierto y un buen programador debiera poder entenderlo sin mucho problema por su gran legibilidad.

Hasta aquí por hoy. Si tienen dudas pónganlas en los comentarios.