Functiodomo-Sistema de automatización del hogar (domótica) sin cables

Comunicación con Arduino a través de un servidor PHP.

En este artículo explico como nos comunicamos entre el ordenador principal y cada uno de los nodos Arduino mediante instrucciones escritas en PHP.

Como aparece más detallado en el artículo, un punto importante de nuestro método es que la selección de nodo activo no se hace mediante direcciones IP, sino que aprovechando que en las redes Zigbee, todas las órdenes pasan por todos los nodos, debido a su configuración tipo malla, la selección de a qué nodo se dirige una orden la hacemos mediante programación en la propia placa Arduino.

Esta técnica tiene como ventajas:

  • La programación es muy sencilla, tanto en PHP como en Arduino.
  • Los nodos son independientes de los chips Xbee que les comunican con el sistema central. Aunque lo recomendable es saber qué chip XBee acompaña a cada nodo Arduino, los chips Xbee son perfectamente intercambiables entre ellos, ya que la selección del nodo no la hace su dirección de red, sino la propia placa Arduino

También tiene sus desventajas, siendo la principal que esta técnica obliga a tener la placa Arduino siempre conectada, no permitiendo técnicas de ahorro de energía (manteniéndola apagada mientras no llegue una orden), aunque como en nuestro caso los nodos no van a estar alimentados por baterías, este factor no es tan crítico.

Como ejemplos de comunicación PHP-Arduino sobre red Xbee, nuestra programación es la siguiente:

  • para el servidor PHP:

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> 

 

 
<a href="../control_por_zonas/index_plata_zonas.html" title="Orden enviada">vuelta a control por zonas</a> 
</BODY> 
</HTML>

En cuanto a la programación de la placa Arduino, el código necesario es el siguiente:

ectura_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: 
+ 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 estos dos códigos, nos permirtirán activar el pin 13 cuando enviemos la orden "aM" (nodo "a"+orden "M") y desactivarlo cuando enviémos la orden "aN".

Todo este proceso de comunicación está basado en la información publicada en los siguientes enlaces:
Control de Arduino utilizando PHP:

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: