Programación inalámbrica de nodos con MySensors

Una vez terminado de desarrollar los nodos y ser instalados en su sitio final puede ser que con el tiempo necesitemos actualizar el código grabado en el microcontrolador, el sketch, ya sea para añadir más funcionalidades o simplemente porque había un error o mal comportamiento que se nos paso por alto y que hay que arreglar.

Si nos encontramos en esa situación puede darse dos casos, o bien nos toca desmontar el nodo del lugar en el que este instalado, lo cual puede darnos bastante trabajo si estaba empotrado o escondido, para luego conectarlo por USB y programarlo, o bien le actualizamos el código de forma inalámbrica si desde un principio lo preparamos para soportar actualizaciones FOTA.

Para soportar este tipo de programación a distancia es necesario que tanto el hardware como el software este preparado para ello, a continuación explico como se haría para los nodos de interruptor que he fabricado aunque esto podría aplicarse para otros proyectos.

Configurar fuses del microcontrolador

Mediante un programador ISP lo primero que debemos hacer es comprobar que los fuses del microcontrolador estén correctamente configurados, si usamos un microcontrolador virgen lo normal es que venga configurado para funcionar a 1Mhz con el oscilador interno, por lo que deberíamos de configurarlo para que funcione a 8Mhz con oscilador interno o externo, o a 16Mhz.

Aquí explique cómo se graban los fuses, en cuanto a la configuración para 8Mhz con oscilador interno y externo son las siguientes respectivamente:

Grabar bootloader

Hay disponibles gran variedad de bootloaders para Arduino, en el caso de los nodos para MySensors se recomienda usar MYSBootloade o Dualoptiboot, resumiendo las diferencias de uno y de otro son las siguientes:

MYSBootload:
En caso de que el proceso de grabado del nuevo sketch se interrumpa se puede recuperar el nodo volviéndoselo a enviar. Sin embargo es necesario cambiar el código de la antena RF que usemos.

Dualoptiboot:
No requiere modificar el código de la antena, pero necesita un chip de memoria flash externo y si se interrumpe el grabado el nodo queda inutilizado hasta que volvamos a grabarlo por USB.

Para profundizar un poco mas sobre este bootloader que es el que conozco, la forma en que funciona es la siguiente: El software encargado de actualizar el sketch, por ejemplo MYSController, envía el nuevo sketch en formato .HEX al nodo en cuestión, entonces el sketch que tiene grabado actualmente lee el nuevo código que le están enviando y lo va grabado según llega en el chip de memoria flash externo, cuando finaliza la recepción de todos los datos el microcontrolador se reinicia automáticamente, es entonces cuando el bootloader comprueba el chip externo y al haber un nuevo sketch lo que hace es leerlo y grabarlo en la memoria interna del microcontrolador, luego ejecuta el código y el nodo sigue funcionado con el nuevo código.
Esto obliga a que el sketch del microcontrolador no tenga errores (bucles o pausas infinitas, desbordamientos de memoria, etc.) y tenga activado las opciones de actualización inalámbrica, ya que debido a que es él quien lee del RF y graba a la flash externa la información, si se corrompe nadie mas podrá hacerlo.

En mi caso me he decantado por Dualoptiboot, para grabarlo en el microcontrolador la forma mas sencilla es que añadamos al IDE de Arduino un nuevo tipo de placa el cual lo incluye, así solo tendremos que seleccionarla y darle a grabar, aquí explican como se añade la nueva placa Sensebender Micro.

El chip de memoria flash hace uso del bus ISP mas un cable extra como Cable Select o SS, si en vuestro caso habéis usado el pin D8 como en la placa Sensebender Micro podréis usar el bootlader que incluye… sin embargo si como en mi caso habéis personalizado el pin SS por otro distinto sera necesario crear un nuevo bootloader con el pin correcto para después compilarlo de nuevo, es la única forma de decirle al bootloader con qué pin debe comunicarse con el chip flash externo.

Compilar Dualoptiboot con código personalizado

Es un proceso algo tedioso pero una vez tengamos todo configurado compilarlo tantas veces como necesitamos no nos costara nada.

1) Descargamos Atmel Studio desde aquí y lo instalamos en el ordenador, es un IDE de programación bastante pesado ya que se basa en Visual Studio.

2) Descargamos este proyecto de Atmel Studio que contiene el bootloader Dualoptiboot que usaremos como base para personalizarlo. (Es el bootloader del Gateway que compre 😉 )

3) Desde Atmel Studio abrimos el proyecto y tenemos que ir a sus propiedades para configurar algunas cosas antes de tocar código. A estas propiedades se puede ir con el atajo de teclado Alt+F7, veremos que aparecen 3 campos que tendremos que configurar de la siguiente forma:

Make file Name
Es el directorio del bootloader Dualoptiboot, veremos que dentro tiene un fichero que se llama Makefile, tendremos que indicar la ruta en el que se encuentra incluido el nombre del fichero.

Build Commandline
Los los parametros que se añadirán al comando make que crea el nuevo bootloader con extensión .HEX, en mi caso aplico el valor  atmega328 F_CPU=8000000L para especificar el microcontrolador para el que se ha de compilar el código y la frecuencia del cristal a usar, en mi caso 8Mhz, si usamos 16Mhz debemos utilizar el valor 16000000L

Clean Commandline
Esto hay que dejarlo con el valor clean

4) Ahora abrimos desde Atmel Studio el fichero optiboot.c y deberemos editar las lineas siguientes:

Será necesario modificar las constantes FLASHSS_DDRFLASHSS_PORTFLASHSS por los valores correspondientes al pin que estemos usando como pin SS para la memoria flash, en mi caso el pin A0. En la documentación de Arduino especifican los valores que se ha de usar para cada pin, ya que no se da valor de igual forma que cuando programamos un sketch.

Para terminar con las modificaciones del código sera necesario cambiar el valor 4 por el correspondiente al que hayamos usado, en mi caso DDRC.

5) Por ultimo deberemos de guardar y pulsar en el botón de ejecutar, o F5, para que se compile el nuevo bootloader que creara en la carpeta del proyecto, un fichero con el nombre:  optiboot_atmega328.hex

Grabar bootloader personalizado

De nuevo, la forma mas sencilla de hacerlo es instalando la placa Sensebender Micro y después sustituir el bootloader que incluye por el nuestro, la ruta donde se encuentran los ficheros de Sensebender Micro se puede obtener desde el IDE yendo al menú: Archivo > Preferencias, y en la parte inferior veremos una ruta de nuestro ordenador donde esta guardado el fichero de preferencias del IDE y lo que hayamos instalado. (atentos al fichero  preferences.txt que sera necesario modificar en el ultimo paso)

Una vez en ese directorio deberemos de navegar hasta: packages\MySensors\hardware\avr\1.0.1\bootloaders\DualOptiboot y remplazar el bootloader por el nuestro (usando el mismo nombre). Después ya solo nos quedara grabarlo con el programador ISP.

Otra forma de hacerlo es modificando el fichero  boards.txt  de Arduino que se encuentra en el directorio: [Directorio principal de tu IDE Arduino]\hardware\arduino\avr\boards.txt, yo siempre prefiero editar ese fichero ya que no me gusta tener placas de mas en el desplegable, por eso comento o borro las lineas de las placas de Arduino que no tengo ni voy a usar, este es mi fichero y al final se ve el bloque que he añadido con la nueva placa «MySensors Node»:

Por ultimo sera necesario mover la carpeta del proyecto de Atmel Studio al directorio: [Directorio principal de tu IDE Arduino]\hardware\arduino\avr\bootloaders\DualOptiboot, quedando así:

El bootloader que he compilado desde ATmel Studio lo he renombrado a  DualOptiboot_atmega328_8Mhz.hex  como se ve en la imagen y que es el nombre que se indica en el fichero boards.txt

Ahora si abrimos el IDE veremos que aparece la nueva placa, la cual podremos seleccionar y grabar el bootloader.

Grabar sketch por USB

Antes de poder grabar el código a distancia sera necesario grabarlo por USB para que las próximas veces sea capaz de leerlo por RF, para ello en nuestro código deberemos de haber definido las constantes:

Además de hacer uso de la librería MySensors, idealmente lo mejor seria no programarlo por FOTA hasta que nos funcione todo por USB, este es el código del interruptor por si alguien quiere usarlo como plantilla.

Grabar sketch por FOTA / inalambricamente

El fichero que debemos de enviar por RF debe ser un fichero .HEX que contenga nuestro código ya compilado, esto lo hace el propio IDE de Arduino pero como no sabemos en qué directorio lo realiza lo primero sera indicarle que lo haga en un directorio al cual tengamos acceso, esto se hace en el fichero de preferencias (el explicado en el apartado Grabar bootloader personalizado), deberemos de añadir la siguiente linea al final del fichero (este cambio hay que hacerlo con el IDE cerrado):

En realidad puede ser cualquier directorio mientras se lo indiquemos correctamente, a partir de este momento cada vez que pulsemos en comprobar código o grabar en el IDE los ficheros compilados se guardaran en ese directorio (solo uno ya que borra todo el contenido anterior).

Con el fichero .HEX generado lo copiamos y vamos al directorio dónde tengamos el programa MYSController , ahí veremos un directorio llamado Firmware, donde deberemos pegar el fichero, y ademas editar el fichero firmware_config.csv icluyendo una nueva linea para el firmware/sketch nuevo.

Y ya por fin solo nos quedara desde MYSController  seleccionar el nodo, el firmware/sketch deseado y enviárselo por RF:

Escriba aquí su comentario