Our Blog / Noticias de functiodomo

Vamos a explicar un apartado que por lo que se ve da muchos problemas de cabeza, como es la solución que hemos adoptado en el sistema functiodomo para comunicarnos con las placas Arduino a mediante órdenes escritas en PHP.

topología de redes

Antes de nada hay que explicar que como ya hemos indicado en algún artículo anterior, la transmisión de los datos en nuestro sistema la realizamos sobre una red Zigbee. Es muy importante saber que esta red es de tipo mallado, estos es, todos los datos que se transmiten por esa red pasan por TODOS los nodos de la misma. La comunicación entre cualquier nodo y el router se hace enviando el paquete de datos desde el router al nodo más cercano, transmitiéndolo éste a todos los nodos de su alrededor, y volviendo a repetir cada uno de estos nuevos nodos la misma operación, así hasta llegar al nodo destino.

Otros tipos de redes con topología infraestructura, como pueden ser las redes WIFI necesitan que cada uno de los nodos tenga “línea directa” con el router principal.

Para una mejor explicación de estos tipos de red recomiendo la lectura del siguiente enlace:

http://es.wikipedia.org/wiki/Red_inalámbrica_mallada

Ésta diferencia en el método de realizar la comunicación conlleva las siguiente consecuencias:

  • En las redes con topología infraestructura necesitamos en el paquete de datos a transmitir 2 elementos: los datos a transmitir propiamente (la instrucción) y los datos del nodo al que se lo vamos a transmitir (la dirección de red).
  • En las redes malladas (además de la metodología anterior) como todos los paquetes llegan a todos los nodos, podemos transmitir paquetes SÓLO con los datos (la instrucción), pues dentro de la red seguro que van a llegar al nodo que nos interese.
  • La selección del nodo que recibe los datos la podemos programar en nuestra placa Arduino, siendo la placa Arduino la que determine si la orden enviada le afecta a ella como nodo o corresponde a otra.
  • Este comportamiento es equivalente a tener una comunicación a través serie con el ordenador, pero teniendo todas las placas Arduino (nodos) conectadas en “paralelo”.

Lamento haber sido tan extenso en esta introducción, pero son importantes entender los conceptos anteriores para poder explicar cómo realizamos la comunicación mediante ordenes escritas en PHP.

Ahora viene el código que utilizamos en el lado del servidor (recuerdo servidor LAMP, ésto Linux; en teoría debe funcionar igual sobre Windows, pero sinceramente no lo hemos probado):

enviar_instrucción_M_al_nodo_a.php

<HTML> 
<BODY>
<?php
// apertura del fichero de escritura a través del puerto serie ttyUSB0
$fp =fopen("/dev/ttyUSB0", "w");
// escritura de la instrucción aM
fwrite($fp, aM);
// cierre del fichero
fclose($fp);
?>
<p>Envío de la instrucción M a la placa a</p>
<br/>
<br/>
<a href="../control_por_zonas/index_plata_zonas.html" title="Orden enviada">vuelta a control por zonas</a>
</BODY>
</HTML>

Detalles importantes:

  • El puerto serie tiene que tener los permisos de usuario habilitados para que el servidor Apache pueda utilizarlo. Yo utilizo en la instrucción en la línea de comandos: $ chmod 666 /dev/ttyUSB0
  • Simplemente, conectando la placa Arduino en el puerto USB del ordenador, con el programa anterior ya recibe a través del puerto serie la instrucción “aM”.
  • Si desconectamos el cable USB y lo volvemos a conectar, puede ser que nos cambie el puerto USB a través del que se comunica Arduino (que pase del USB0 al USB1). Esto se puede comprobar en el entorno de programación de Arduino.
  • Para la comunicación inalámbrica, en el puerto serie conectamos el router Zigbee que es tan sencillo como una placa Arduino sin el chip ATMEGA328 con el Xbee shield y su correspondiente chip Zigbee programado como router.
  • En el caso de las órdenes anteriores, el código necesario en Arduino para leer la orden y realizar una acción es tan sencillo como sigue:

lectura_ordenes_PHP.pde

/* Modificación del programa SwitchCase2 de la librería de ejemplos de Arduino 
Programa original creado por Tom Igoe el 1 de julio de 2009 
Programa mofificado por José Antonio Castillo Rodríguez el 15 de abril de 2010 
A continuación el texto informativo original de Tom Igoe: 
-- Switch statement with serial input 
-- 
-- Demonstrates the use of a switch statement. The switch 
-- statement allows you to choose from among a set of discrete values 
-- of a variable. It's like a series of if statements. 
-- 
-- To see this sketch in action, open the Serial monitor and send any character. 
-- The characters a, b, c, d, and e, will turn on LEDs. Any other character will turn 
-- the LEDs off. 
-- 
-- The circuit: 
-- * 5 LEDs attached to digital pins 2 through 6 through 220-ohm resistors 
-- 
-- created 1 Jul 2009 
-- by Tom Igoe 
-- 
-- http://www.arduino.cc/en/Tutorial/SwitchCase2 
-- 
Modificaciones realizadas por José Antonio Castillo Rodríguez: 
+ cambio de los pines actuables de 5 a 2 (los números 2 y 3 para control de relés) 
+ pin actuable para control de estado manual modificables por variable (asignaPinAlimentacion) 
+ pin actuable para alimentación sensor modificables por variable (alimenSensor) 
+ 
+ cambio en los caracteres de control; nomenclatura de acciones: 
+ M -> activa el pin que alimenta el detector de estado manual; N -> desactiva el pin que alimenta el detector de estado manual 
+ OTRO VALOR -> envía una señal de error a través del puerto serie 
+ 
+ "a","b","c"... selecciona la placa como activa para poder recibir la siguiente orden; valor de activación definido por variable (selecPlaca) 
+ 
+ el pin de lectura del cambio de estado manual esta definido por variable (remotoPin) 
+ 
*/ 
// VARIABLE DE SELECCIÓN DE PLACA 
int inByte = 0; // almacena la lectura del puerto serie 
int selecPlaca = 'a'; // CTE-valor ante el CUAL se activa la placa en modo escucha 
boolean placaActiva = false; // indica si la placa está en modo escucha o no 
// VARIABLES RELATIVAS AL PIN 13 DE ARDUINO-UTILIZADO PARA LA COMPROBACIÓN DEL ESTADO MANUAL 
int asignaPinAlimentacion = 13; // CTE-indica el pin de la placa que alimenta el comprobador de estado manual 
boolean estadoPinAlimentacion = true; // encendido/apagado del pin que alimenta el comprobador de estado manual 
int remotoPin = 12; // CTE-selecciona el pin de entrada para comprobar cambios en el modo manual 
int remotoCambio = 0; // inicialización de la variable para leer en pin del cambio de estado manual 
boolean estadoManual = false; // indica el estado del control manual (false-> apagado manual; true-> encendido manual) 
boolean estadoManualPrevio = false; // almacena el estado del control manual en el ciclo anterior (false-> apagado manual; true-> encendido manual) 
void setup() { 
// initialize serial communication: 
Serial.begin(9600); 
// inicialización de los pines 
pinMode(asignaPinAlimentacion, OUTPUT); 
pinMode(remotoPin, INPUT); 
} 
void loop() { 
// comenzamos con el pin 13 encendido 
if (estadoPinAlimentacion == true) { 
digitalWrite(asignaPinAlimentacion, HIGH); 
} 
// lectura de la señal serie 
if (Serial.available() > 0) { 
int inByte = Serial.read(); 
if (placaActiva == true) { // si la placa está en modo activo pasa a actuar dependiendo de la lectura del valor de inByte 
switch (inByte) { 
// desconectar el pin 13 que alimenta al analógico 
// "N" desactiva el pin, "M" lo vuelve a activar 
case 'N': 
digitalWrite(asignaPinAlimentacion, LOW); 
estadoPinAlimentacion = false; 
// hay que enviar por serie el código "'placa'13OFF" 
Serial.print(selecPlaca, BYTE); 
Serial.print('1', BYTE); 
Serial.print('3', BYTE); 
Serial.print('O', BYTE); 
Serial.print('F', BYTE); 
Serial.print('F', BYTE); 
Serial.print(","); 
break; 
case 'M': 
digitalWrite(asignaPinAlimentacion, HIGH); 
estadoPinAlimentacion = true; 
// hay que enviar por serie el código "'placa'13ON" 
Serial.print(selecPlaca, BYTE); 
Serial.print('1', BYTE); 
Serial.print('3', BYTE); 
Serial.print('O', BYTE); 
Serial.print('N', BYTE); 
Serial.print(","); 
break; 
default: //cualquier otro valor leido envía señal de error 
// hay que enviar por serie el código "'placa'13err" 
Serial.print(selecPlaca, BYTE); 
Serial.print('1', BYTE); 
Serial.print('3', BYTE); 
Serial.print('e', BYTE); 
Serial.print('r', BYTE); 
Serial.print('r', BYTE); 
Serial.print(","); 
} 
} 
// caso que la placa esté en modo activo, se vuelve a modo escucha tras 
// haber ejecutado la orden correspondiente 
if (placaActiva == true) { 
placaActiva = false; 
} 
//******** SELECCIÓN DE LA PLACA *************************** 
//********************************************************************* 
// si la variable inByte se corresponde con la letra de la placa (la asignada a la variable selecPlaca en este caso) 
// la placa se pone en modo activo 
if (inByte == selecPlaca) { 
placaActiva = true; 
} 
} 
}

 

  • Con esta metodología hay que hacer notar que las placas Arduino deben estar siempre activas, pues son ellas las que hacen las selección del nodo a ejecutar las ordenes, pero en el caso de la domótica, aunque energéticamente sea menos eficiente, no es un problema mayor pues las placas no están alimentadas por batería.
  • El código escrito en Aduino es transparente al medio a través del cual se transmite la señal (aire, cable), siempre y cuando esta pueda llegar a través del puerto serie.

 

Por último comentar que como supongo que algunas cosas no estarán suficientemente bien explicadas, añado las páginas web de donde obtuvimos toda la información para comunicar las placas:

Control de Arduino utilizando PHP:

http://www.arduinoprojects.com/?q=node/10

http://www.mydarkmaterials.co.uk/2008/11/30/interfacing-php-with-the-arduino/

Configuración de Zigbee:

http://ladyada.net/make/xbee/arduino.html

Software de configuración de los chips Xbee:

http://www.digi.com/support/productdetail?pid=3352&osvid=0&type=utilities

Algunos ejemplos más que he encontrado sobre conexión de PHP y Arduino:

http://mcielectronics.com/blog/?p=495

http://blog.bsoares.com.br/php/controlling-arduino-with-php

 

 

Creative Commons License

Comunicación con Arduino a través de un servidor PHP. by Functio & Ars S.L. is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 3.0 España License

José Antonio Castillo Rodríguez

Acerca de: José Antonio Castillo Rodríguez

José Antonio Castillo Rodríguez I Responsable de la planificación, desarrollo y cálculo de proyectos relacionados con el sector de los equipos electromecánicos. Comercialización y formación técnica del sistema de domótica Functiodomo, desarrollado íntegramente por mí. Socio fundador de la empresa Functio & Ars S.L.

2 Comments

  1. Que tal, solo una pregunta.. en caso de poner un sensor de temperatura como hacerle para que PHP tome un valor de Serial.println(valor); y lo meta en $valor array(); para luego imprimirlo con echo $valor[0]; ?

    • José Antonio Castillo Rodríguez

      En este caso nosotros usamos dos métodos:

      1. El más directo es enviar una orden mediante PHP similar a la que aparece pero cuyo objeto sea que Arduino devuelva el valor de un pin analógico (como la parte en la que envía una señal de error (a13err) y lo leemos con una rutina del tipo:

      $fp =fopen("/dev/ttyUSB0", "r");
      $contenido=fread($fp, 1);
      fclose($fp);
      //proceso de escritura en un archivo local o base de datos

      El problema que presenta este método es que sólo leemos el valor de un sensor de un nodo tras una “pregunta” nuestra.

      2. Para poder conocer el valor de un PIN de Arduino en el momento en el que éste tenga una variación significativa (esa variación la determinamos nosotros con la programación en la placa Arduino), podemos utilizar el mismo código de lectura pero aplicado a un demonio/servicio, que en nuestro caso está escrito en PHP, pero que puede estar escrito en cualquier lenguaje que sea capaz de leer las instrucciones que llegan por el puerto serie.

      De todos modos, a la parte de lectura de sensores quiero dedicarle otro artículo un poco más adelante.

So, what do you think ?

You must be logged in to post a comment.