viernes, 18 de marzo de 2011

Arduino programación wireless con Xbee oficial. Sexta parte.

En el siguiente video vemos la implementación del programador wireless en acción:


La música es de Penguin Café Orchestra.

Hasta pronto.

lunes, 14 de marzo de 2011

Arduino programación wireless con Xbee oficial. Quinta parte.

8. Puesta en marcha

Una vez tenemos el sistema instalado. Es decir:
- Arduino Master con el Shield Xbee s1, conectado al PC a través del USB.
- La aplicación de sparkfun Screamer v20 corriendo en el PC
- Arduino Slave con el shield Xbee S1


Seguimos los siguientes pasos:
1. Quitamos el jumper "aereo" que habilita el reset por DTR en el Arduino Master
2. Seleccionamos el fichero a cargar en el Slave en la aplicacion Screamer y seleccionamos la opción de download. El programa entra en modo de espera.
3. Reseteamos el Arduino Master con el pulsador de reset del shield Xbee
4. El programa del Arduino Master corre hasta que se provoca el reset remoto y se inicia la transferencia del archivo al arrancar el bootloader remoto.

9. Posibles Mejoras
- Programa en Pynthon para la aplicación de programación de SparkFun, posibilidad de activarlo a través de un comando script.
- Completar la librería SoftSerial Xbee para comprobar la conformidad de la recepción de los mensajes
- Completar el sketch del Arduino Master de forma que inicie el proceso de grabación remota al recibir un comando o al conmutar un interruptor.
- ...

Este proyecto no pretende establecer la comunicación más fiable de la historia de las comunicaciones. Es  bastante mejorable. Pero os puede ser útil en proyectos con varios Arduinos donde os queréis ahorrar el tener que trastear constantemente con los cables. Un ejemplo de utilidad podría ser la programación remota de un robot, de forma que vayas debugando con nuevos programas sin necesidad de ni tan siquiera de tocarlo.


Hasta pronto.

domingo, 13 de marzo de 2011

Arduino programación wireless con Xbee oficial. Cuarta parte.

El código del sketch que debe correr en el Arduino Master para hacer la programación remota con el shield de Xbee es:


//MAKE AN ARDUINO WIRELESS PROGRAMMING WITH XBEE SHIELD LIBELIUM
//RemoteXbee v1.0
//RELYNXANDO Marz-11
//This example code is in the public domain.
#include <xbeefg.h>
#include <newsoftserial.h>
// SH + SL of your remote radio Slave Arduino XBeeAddress64(SH,SL)
// in my case SH=0x0013a200 and SL=0x4049CC62
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x4049CC62);
// Define NewSoftSerial TX/RX pins
// Connect Arduino pin 6 to TX of usb-serial device
uint8_t ssRX = 6;
// Connect Arduino pin 7 to RX of usb-serial device
uint8_t ssTX = 7;
xBeeFG XBeeNSS = xBeeFG( ssRX, ssTX );
// Software UART to communicate with the Xbee module
NewSoftSerial nss(ssRX, ssTX);

// Configure remote Xbee to API Mode (AP=2)
uint8_t APIModeCmd[] = {  'A', 'P' };
uint8_t APIModeValue[] = {  0x2 };
uint8_t TransModeValue[] = {  0x0 };

AtCommandRequest atRequest = AtCommandRequest(APIModeCmd, APIModeValue, sizeof(APIModeValue));
AtCommandResponse atResponse = AtCommandResponse();

// Set DIO7 (pin 12) to OUT HIGH
uint8_t d7Cmd[] = {  'D', '7' };
uint8_t d7ONValue[] = {  0x5 };
uint8_t d7OFFValue[] = {  0x4 };

// Set DIO5 (pin 15) to OUT HIGH
uint8_t d5Cmd[] = {  'D', '5' };
uint8_t d5ONValue[] = {  0x5 };
uint8_t d5OFFValue[] = {  0x4 };
uint8_t ATModeRemote[] = {  '+', '+', '+'};
uint8_t APIModeRemote[] = {  'A', 'T', 'A', 'P', '2'};

char payload[20];   

// unless you have set DH/DL for 64 bit this will be received as a RX16 packet
Tx64Request tx64 = Tx64Request(remoteAddress, (uint8_t*)payload, sizeof(payload)); 

// This will contain the status responses of that the XBee receives
TxStatusResponse txStatus = TxStatusResponse();                            

// Create a remote AT request with the IR command
RemoteAtCommandRequest remoteAtRequest = RemoteAtCommandRequest(remoteAddress, APIModeCmd, APIModeValue, sizeof(APIModeValue));

// Create a Remote AT response object
RemoteAtCommandResponse remoteAtResponse = RemoteAtCommandResponse();

void setup()
{
  Serial.begin(19200);
  Serial.println("REMOTE PROGRAMMING"); 
  delay(10);
  XBeeNSS.begin( 19200, ssRX, ssTX );
  delay(100);
  nss.begin(19200);
  delay(100);
}

void loop()
{
  //CONFIGURE XBEE1 AND XBEE2 AS MODE API
  //Configure local XBEE1 in API mode again with AT AP 2 command
  delay(150); 
  nss.print("+++");
  delay(1500);
  nss.println("ATAP2");
  delay(3000);
  //XBEE2 in AT mode 
  tx64 = Tx64Request( remoteAddress, ATModeRemote, sizeof( ATModeRemote ) );
  XBeeNSS.send( tx64 );
  delay(3000);
  //Xbee2 in API mode
  remoteAtRequest.setCommand(APIModeCmd);  
  remoteAtRequest.setCommandValue(APIModeValue);
  remoteAtRequest.setCommandValueLength(sizeof(APIModeValue));
  XBeeNSS.send(remoteAtRequest);
  delay(5000);
  //END CONFIGURATION XBEE1 AND XBEE2 AS MODE API
  //Reset remote XBEE2
  remoteAtRequest.setCommand(d7Cmd);  
  remoteAtRequest.setCommandValue(d7ONValue);
  remoteAtRequest.setCommandValueLength(sizeof(d7ONValue));
  XBeeNSS.send(remoteAtRequest);
  delay(2000);
  //Enable remote XBEE2 enter bootloader
  remoteAtRequest.setCommand(d7Cmd);  
  remoteAtRequest.setCommandValue(d7OFFValue);
  remoteAtRequest.setCommandValueLength(sizeof(d7OFFValue));
  XBeeNSS.send(remoteAtRequest);
  //Configure remote XBEE2 TO TRANSPARENT MODE to send file .hex in a transparent way
  remoteAtRequest.setCommand(APIModeCmd);  
  remoteAtRequest.setCommandValue(TransModeValue);
  remoteAtRequest.setCommandValueLength(sizeof(TransModeValue));
  XBeeNSS.send(remoteAtRequest);
  //Configure local XBEE1 TO TRANSPARENT MODE to send file .hex in a transparent way
  atRequest.setCommand(APIModeCmd);
  atRequest.setCommandValue(TransModeValue);
  atRequest.setCommandValueLength(sizeof(TransModeValue));  
  XBeeNSS.send(atRequest);
  delay(30);
  Serial.flush();
while(1){
      if (nss.available()) {
          Serial.print((char)nss.read());  
      }
      if (Serial.available()) {
          nss.print((char)Serial.read());  
      }
 }
  //end send Hex file
}

sábado, 12 de marzo de 2011

Arduino programación wireless con Xbee oficial. Tercera parte.

Tercera parte del post sobre cómo programar remotamente un Arduino con los Xbee oficiales.

7. Consideraciones slave bootloader
Hay que grabar el bootloader de Sparkfun, ya sea para el ATMEGA168 o el ATMEGA328 en el Arduino Slave, el que queremos reprogramar remotamente.
A diferencia del bootloader que proporciona SparkFun, en nuestro caso hay cierto delay entre el reset del Slave y el envio del programa. Es el tiempo necesario para pasar los módulos Xbee a modo AT y  enviar el primer caracter de programación (ASCII 0x05) para comunicarle al bootloader remoto que queremos reprogramar el microcontrolador.
Para evitar que este delay sea demasiado grande para que el bootloader entienda que  NO debe entrar en modo programación, modificamos ligeramente el bootloader de Sparkfun en el Arduino Slave alargando el tiempo de espera antes de iniciar el programa.

En el bootloader de Sparkfun está definida la variable MAX_WAIT_IN_CYCLES:
  
MAX_WAIT_IN_CYCLES = [(MAX_CHARACTER_WAIT)*8]*CPU_SPEED / BAUD
Por defecto:
MAX_CHARACTER_WAIT = 15
CPU_SPEED = 16MHz
BAUD= 19200 bps
Por tanto por defecto:
MAX_WAIT_IN_CYCLES = 100E3 ciclos , siendo 1/16MHz = 1ciclo, el tiempo maximo espera 6.25 mseg
Modificando el bootloader encuentro que el máximo valor de MAX_CHARACTER_WAIT que puedo utilizar sin afectar el funcionamientodel bootloader es 75. Con ese valor conseguimos un tiempo máximo de espera de 31.25 mseg. A la práctica resulta suficiente.

Así la modificación que recomiendo sobre el bootloader es:
  
// #define MAX_CHARACTER_WAIT    15 
#define MAX_CHARACTER_WAIT    75

Se compila el bootloader con avrdude, y se graba en el Arduino Slave. Para grabar el bootloader, si no disponéis de un grabador ISP, se puede utilizar un Arduino Duemilanove, las instrucciones de cómo hacerlo están en la web Burning the Bootloader without external AVR-Writer.

Si a alguien le interesa, le puedo enviar el bootloader compilado, enviadme un mail.

En el siguiente post pondré el código del sketch.

Hasta pronto.

viernes, 11 de marzo de 2011

Arduino programación wireless con Xbee oficial. Segunda parte.

Seguimos con los posts que intentarán crear un sistema para programar remotamente un Arduino a través de los shields oficiales Xbee. En el último post planteamos que ibamos a utilizar la aproximación al problema que ya había hecho Sparkfun.

3. Mecanismo de Reset

De Sparkfun no puedo aprovechar su mecanismo de reset remoto. Sparkfun activa la señal Ready to Send (RTS) a través del programa Screamer, justo antes de enviar el programa hex  por el USB hasta la UART del AVR del Arduino.
Esta señal de RTS en la implementación de Sparkfun se conecta a un pin del modulo Xbee que con una determinada configuración de los módulos, se transforma en el reset remoto.
Comunicándonos a través de Arduino no se puede aprovechar este procedimiento, es más, tenemos que modificar el Arduino Master para evitar que se nos resetee el Arduino cada vez que enviamos un fichero. Tenemos que cortar el puente de DRT del Arduino, y ponemos un jumper "aéreo" para poder habilitar o deshabilitar este puente cuando nos interese.



Corto la pista que hay en el jumper RESET_EN del Arduino Duemilanove "víctima" de las fechorías.
Atención, nos interesa poner el jumper aereo cuando querramos programar este Arduino master, y tendremos que quitar el jumper cuando querramos programar remotamente el Arduino Slave. Hay que tenerlo en cuenta.

4. Xbee oficial vs Reset remoto
En el caso del Xbee oficial, el pin DIO7 del módulo Xbee está conectado a la señal de Reset, de forma que para resetar el Arduino Slave, hay que activar ese pin de forma remota. ¿Cómo podemos hacer eso?, mediante los comandos API del módulo Xbee y más concretamente, el "Remote AT Command Request", los comandos remotos AT. Enviamos un comando AT desde el Master para que se ejecute en el Slave.
Por tanto, el programa que utilicemos para hacer la programación remota tendrá que comenzar configurando tanto el Xbee del Master y del Slave en modo API.
Pero eso lo veremos en detalle más adelante, antes hay otro asunto que tratar.

5. Softserial
¿Cómo podemos enviar por un canal serie al modulo Xbee del Master el programa hex, al mismo tiempo que lo estamos recibiendo?, sólo hay un canal serie, el que viene del USB. La solución es utilizando una UART de software, un software-serial.
La librería que utilizo para implementar esta UART soft es la librería Newsoftserial.
La recepción del softserial (ssRX) la asigno al pin digital 6, y la transmisión (ssTX) al pin digital 7. Basta con tres comandos en el programa para la inicialización:

#include
uint8_t ssRX = 6;
uint8_t ssTX = 7;
NewSoftSerial nss(ssRX, ssTX);


En la función setup del sketch configuraremos la soft UART de la forma:
XBeeNSS.begin( 19200, ssRX, ssTX );

6. Xbee en modo API
Recordad que queremos hacer ese comando remoto para activar el pin DIO7 del modulo Xbee Slave y  de esa forma resetearlo para que se inicie el bootloader. La secuencia será la siguiente:

La softserial comunicación nos obliga a llevar dos cables de las UART soft desde el conector a los jumpers, tal como ilustra la siguiente foto:
 
En siguientes posts sigo explicando la implementación.

Hasta pronto.

jueves, 10 de marzo de 2011

Arduino programación wireless con Xbee oficial. Primera parte.

El objetivo de esta serie de posts es presentar un sketch para programar remotamente un Arduino utilizando los shields Xbee "oficiales".
En su momento me sorprendió no encontrar en la web una solución para esta funcionalidad. La encontré con los Xbee shields de Adafruit y de SparkFun, pero no para los Xbee shield oficial de Arduino. Finalmente desistí de seguir buscando, y me puse manos a la obra.
El proyecto consiste en lo siguiente:

1. Objetivo
Tenemos dos Arduinos con shields Xbee oficiales de Libelium, con módulos del tipo S1. A uno lo llamo Master y al otro Slave. El objetivo es programar desde el Master, remotamente, el Arduino Slave.

2. Herramientas disponibles
Esta funcionalidad está ampliamente comentada en la web para los shields de Adafruit y de Sparkfun. En ambas implementaciones utilizan la señal de Ready to Send (RTS) para resetear remotamente el Arduino Slave y cargar durante el arranque de su bootloader la aplicación por el puerto serie. De esta forma estamos simulando el serial bootloader pero sustituyendo el puerto serie-USB convencional del Arduino, por un puerto serie "virtual" a través del modulo Xbee.
A grandes trazos la solución de Adafruit tiene una serie de potenciales problemas:
- tenemos que tener el módulo Xbee que proporciona Adafruit o Sparkfun, que incorpora la posibilidad de conectar un I/O del modulo Xbee al reset de Arduino;
- la comunicación vía radio no es robusta, ruidos, mala recepción, ... puede provocar que finalmente no grabemos la aplicación correctamente en el Arduino Slave.

Sparkfun lo mejoró creando un bootloader que implementaba un control de errores en la comunicación.  A través de un programa software en PC se envía el programa binario en paquetes, y el bootloader del Slave, comprueba que el CRC es correcto. Si el paquete recibido no tiene el CRC correcto solicita que se le reenvie el paquete de nuevo. De esta forma la comunicación se hace más robusta.

Me decanto por la opción de Sparkfun, aprovechando el software (Screamer) para fragmentar el fichero hex a enviar. La extensión de la compilación de un programa tiene típicamente la extensión hex. Es el fichero binario, que se graba en la memoria Flash del microcontrolador.  No es fácil encontrar el fichero hex después de la compilación en el entorno de Arduino. Las instrucciones para encontrarlo están aquí.

Utilizo el bootloader diseñado por Sparkfun para el Arduino Slave, incorporando de esa forma, el cálculo del CRC y los mensajes de conformidad.

En siguientes posts sigo con la historia.

Hasta pronto.