Quién no ha soñado alguna vez con llamar al sistema de riego de su jardín para encenderlo? Bueno, probablemente casi nadie 🙂
La cosa es que me entró esa idea en la cabeza. No se si sea algo práctico realmente, pero aquí va un artículo que relata con cierto detalle el experimento que hice.
Es importante explicar, antes de continuar, que existen algunas cosas que voy a asumir a partir de ahora, y es que el lector está familiarizado con Elastix, Asterisk, AGI, PHP y Arduino. Además asumiré que también tiene conocimientos básicos de electrónica.
Para aclarar mejor cómo funcionará el sistema dibujé la siguiente figura donde se ilustran los componentes que lo conforman.
Como ilustra la figura anterior hay dos componentes principales que necesitaremos, y son:
- el servidor Elastix, y
- la interfaz con la válvula de riego (o interfaz de riego)
Servidor PBX VoIP
Para el servidor Elastix instalé la versión 2.2 RC1. Este servidor es el que me servirá de PBX pues lo conectaré con el mundo exterior mediante una línea telefónica. De este modo puedo llamar por teléfono al servidor Elastix y activar el riego.
Como se puede observar en la figura aterior, en este servidor residirán dos programitas que desarrollé: Un script AGI y un driver de alto nivel (para que se comunique con la interfaz de riego vía USB). Ambos los escribiré en PHP debido a que es un lenguaje muy popular y existe bastante documentación que se puede consultar vía Web; de este modo la explicación es más entendible.
Alguno se puede preguntar por qué no controlo al Arduino directamente desde el script AGI. La respuesta es que preferí tener el driver por separado porque también me servirá para controlar el Arduino desde la interfaz Web que desarrollaré en un futuro próximo. Eso es lo que significa el rectángulo que dice \”Interfaz Web\” en la figura anterior.
Interfaz de riego
La interfaz de riego es un circuito que por un lado se conecta al servidor Elastix a través de un puerto USB y por el otro se conecta a la válvula de riego. Hay muchas maneras maneras de realizar esta circuitería. En mi caso me decidí por usar una placa Arduino conectada a un relé. Básicamente porque tenía una placa Arduino ociosa y decidí darle algún uso interesante. Esta placa se encuentra conectada a un relé a través de una circuitería sencilla.
En la siguiente figura se muestra la interfaz de riego cuando la planifiqué por primera vez en protoboard (breadboard).
En la práctica terminé reemplazando el circuito de relé con uno pre-construido que compré para Arduino (con entrada opto-aislada y doble relé) y que en Internet hay un montón a precios razonables.
Lo único que no me gustó mucho del circuito que compré es que tiene lógica negada. Es decir, que cuando la entrada es un HIGH el relé se encuentra apagado, mientras que cuando es un LOW se encuentra encendido. Por eso verán más adelante que el código para el Arduino toma en consideración esta lógica.
La válvula de riego
En mi caso se trata de una válvula marca Rainbird controlada con 24 voltios AC. Nada del otro mundo; tiene dos cables y si los energizamos con 24 VAC la válvula se enciende y el agua pasa a los aspersores.
El protocolo de comunicaciones entre Elastix y la interfaz de riego
El protocolo que utilizaré será lo más sencillo posible. De esta manera le será más fácil al lector entender el código. El protocolo consiste de un solo comando compuesto por un byte. Este byte será interpretado como un número entero por el Arduino y representará el número de minutos que se desea activar el riego. Si deseo interrumpir el riego envío el número 128.
Modificación del plan de marcado de Asterisk
En mi caso particular he configurado el siguiente contexto en el archivo /etc/asterisk/extensions_custom.conf
[sprinkler] exten => *2222,1,Answer exten => *2222,n,AGI(sprinkler.agi) exten => *2222,n,Hangup()
Esto quiere decir que cuando alguien marque el número *2222 le contestará mi script AGI, que por cierto se llama sprinkler.agi.
El script AGI
Aquí también los dejo con el código de mi script AGI. No se olviden de darle los permisos correctos.
#!/usr/bin/php -q <?php require_once "phpagi.php"; $agi = new AGI(); $arr_minutos_riego = $agi->get_data('custom/minutosactivos', 20000, 3); $minutos_riego = $arr_minutos_riego['result']; $comm = "sudo /opt/sprinkler/driver " . $minutos_riego; exec($comm, $sal); $agi->stream_file('custom/riegoconfigurado'); ?>
El script anterior lo podemos dividir en dos partes:
- Primero le pregunta al llamante por el número de minutos que desea que el sistema de riego permanezca encendido. Esto lo hace mediante la función get_data
- Luego invoca al driver y le pasa como parámetro el número de minutos antes obtenido. Esto lo logra /opt/sprinkler/driver
Cabe resaltar que el script anterior utiliza dos archivos de audio que el lector puede grabar a su gusto. Estos archivos los he llamado minutosactivos.wav y riegoconfigurado.wav. En el primer archivo grabé un mensaje parecido al siguiente:
“Por favor, ingrese el número de minutos que desea regar”
Y en el segundo grabé un sencillo mensaje de agradecimiento:
“Gracias por usar el sistema de riego Elastix”
Cabe mencionar que he preferido mantener el script AGI lo más sencillo posible para propósitos didácticos, pero el lector lo puede añadir complejidad y por ejemplo, validar la entrada del usuario, o pedirle que confirme el número de minutos, entre otras cosas.
Driver para comunicación con la interfaz de riego
Bueno, ahora sí veamos de qué está hecho el driver de alto nivel que controla el Arduino vía USB.
#!/usr/bin/php -q <?php $arg_segundos = trim($_SERVER[\'argv\'][1]); $data = chr((int)$arg_segundos); $fp=fopen("/dev/ttyUSB0", "r+"); $r = fwrite($fp, $data); fclose($fp); ?>
Nuevamente, he preferido mantener el código anterior al mínimo. Dejo al lector la tarea de añadir validaciones. Por ejemplo, estoy asumiento que el dispositivo ha sido asociado con /dev/ttyUSB0, pero eso puede variar de sistema en sistema.
Código para el Arduino
Ahora sí, el código para el Arduino. Este código se debe cargar en el Arduino para que haga lo que necesitamos.
#include <Time.h> int relPin = 2; int usbnumber = 0; int active = 0; time_t timeend = 0; void setup() { pinMode(relPin, OUTPUT); digitalWrite(relPin, HIGH); Serial.begin(9600); } void loop() { // Aquí se lee del puerto USB if (Serial.available() > 0) { usbnumber = Serial.read(); } // 128 es el comando para apagar (interrumpir) la salida del relé if(usbnumber==128) { active=0; digitalWrite(relPin, HIGH); } if(active==0) { // Si el riego estaba inactivo y se recibió un número mayor a cero if (usbnumber > 0) { active = 1; digitalWrite(relPin, LOW); timeend = now() + usbnumber*60; } usbnumber = -128; } else { // Si se alcanzo el tiempo previsto apago el relé if(now()>=timeend) { active = 0; digitalWrite(relPin, HIGH); } } }
Conclusión
Muy aparte de la utilidad para regar un jardín, espero que este proyecto encuentre muchas otras aplicaciones. A final de cuentas se trata de un relé que se activa por un tiempo determinado. Si alguien lo construye o le encuentra alguna otra aplicación práctica, será gratificante ver su comentario por aquí.