Bloque sensor: Software final

Una vez verificado el funcionamiento de los módulos diseñados, he procedido a diseñar el software del módulo sensor.

Tal y como se ha definido, el funcionamiento a grandes trazos se muestra en el siguiente diagrama de flujo.

Es decir, ante una señal de reset o ante el encendido del microcontrolador el microcontrolador realiza una inicialización del sistema.

Inicialización

Esta inicialización, en primer lugar, inicializa el microcontrolador; establece la frecuencia de funcionamiento del reloj interno, las interrupciones y el estado y la dirección de las líneas, haciendo especial hincapié en el bajo consumo.

Una vez inicializado el microcontrolador, se inicializa el sensor a su configuración por defecto de medidas de 14bits para la temperatura y 12bits para la humedad relativa y no recargar la memoria de calibración. No obstante, antes de configurar el sensor se realiza una medida para cargar al menos una vez la memoria de calibración.

El siguiente dispositivo a inicializar es el transceptor. El transceptor se configura con los 15bytes de configuración inicial. Esta palabra de configuración establece lo comentado acerca de la comunicación.

Barrido de canales

Una vez inicializado el sistema, se realiza un barrido de canales hasta lograr la conexión.

El transceptor se ha inicializado con el canal 0. Para implementar la conexión en "caliente", al resetear o encender el módulo sensor, éste realiza un barrido de canales buscando establecer conexión con el módulo maestro. Este barrido se ha implementado como muestra el diagrama de flujo siguiente.

Si no se ha establecido conexión con el módulo maestro, el dispositivo envía el comando de inicio de conexión a la dirección del maestro por el canal inicial. Ante este comando el maestro debe responder con el paquete de respuesta, por lo que se entra en modo recepción durante un tiempo ajustado de respuesta del maestro.

Si pasado dicho tiempo no se ha recibido el paquete de respuesta o se ha recibido un paquete no válido, se comprueba si se está trabajando en el canal máximo, es decir, el canal 124. De no ser así, se incrementa el canal, se configura el transceptor y se repite el proceso. Si se está operando en el canal máximo, se comprueba si se está trabajando también a la máxima potencia, esto es 0dBm. De no ser así, se configura el transceptor con el canal inicial 0, se incrementa la potencia y se repite el proceso. Si se está operando a la máxima potencia, significa que tras realizar los barridos de canales para todo el rango de potencias no se ha logrado establecer comunicación, es decir el sensor se encuentra fuera de rango o no hay ningún nodo maestro a la escucha. Esto lo indica al usuario mediante el LED de estado y detiene el barrido hasta una señal de reset.

En caso de recibir el paquete de respuesta, se establece conexión y se continúa con el funcionamiento normal del sistema.

Medidas y envío

Una vez establecida la conexión, se procede a realizar las medidas. Primero se realiza la medida de humedad relativa y después la de temperatura. Estas medidas se realizan mediante la función de S_measure implementada en el módulo sensor.c/.h .

Una vez se dispone de los datos de las medidas. Éstos se envían, sin procesar, como un único paquete al nodo maestro. Tal y como se ha definido la comunicación, cuando el nodo maestro recibe un paquete de medidas, éste puede enviar algún comando al sensor. Entonces, una vez enviado el paquete, se configura en modo recepción el transceptor durante un tiempo ajustado.

Recepción y procesado

Si durante el tiempo de recepción se recibe un comando del maestro, el comando debe ser procesado.

El procesado se encarga de interpretar el comando recibido y actuar en consecuencia. El funcionamiento del procesado se muestra en el siguiente diagrama de flujo.

En primer lugar se procede a la verificación del dato. Tal y como se ha comentado, la estructura del comando hace que sea facilmente verificable, es decir, es fácil discernir entre un comando incorrecto y uno correcto. De este modo, al realizar la verificación antes de evaluar el comando, se evita seguir con el procesado ahorrándose tiempo y reduciendo el consumo.

Si el comando es correcto, se procede a su evaluación. Se busca que coincida con

Si durante el tiempo de recepción no se ha recibido ningún comando del maestro, se espera a la medida siguiente.

Tiempo entre medidas

El watchdog del microcontrolador, al disponer de la combinación de dos prescalers, permite un rango muy ámplio de tiempo de desbordamiento, en conreto permite desde 1.24ms a 325.36s. Estos tiempos son incómodos al no ser enteros, por lo que se utilizará el tiempo más exacto como base de tiempos. Para cierta configuración de ambos prescalers, se puede lograr un tiempo de 5,08366 segundos el cual es muy interesante como base de tiempos ya que se pueden lograr valores redondos como 60s (12x5), 120s (24x5).

El número que multiplica a la base, múltiplo de la base de tiempos, es de tipo byte por lo que se puede obtener un tiempo entre medidas de hasta 1270 segundos que son aproximadamente 21 minutos, claramente suficiente.

La forma de realizar el tiempo entre medidas se describe en el diagrama siguiente.

Se utiliza una variable, t_count, para contabilizar el número de desbordamientos producidos. Esta variable se inicializa a cero antes de activar el watchdog. El watchdog se configura con un tiempo de desbordamiento de 5.08 segundos (prescaler del registro OPTION 001 y el del watchdog WDTCON 1011) y se activa el watchdog.

Una vez activado el watchdog, se entra en modo de bajo consumo esperando el desbordamiento del watchdog. Una vez esto ocurre, se resetea el contador del watchdog, se incrementa la variable t_count, pues se ha producido un desbordamiento, y si esta variable, el número de desbordamientos producidos, es menor o igual al múltiplo de la base de tiempos establecido, es porque no se ha alcanzado el número de desbordamientos deseados por lo que se vuelve a entrar en modo de bajo consumo. Si se ha alcanzado el número de desbordamientos deseados, la variable t_count es mayor que el múltiplo establecido, se desactiva el watchdog y se continúa con el programa principal.

Bloque sensor: Diseño Software para bajo consumo.

El microcontrolador tiene líneas que pueden configurarse como entradas analógicas o como entradas/salidas digitales. Hay que tener en cuenta las señales que se aplican a estos pines ya que pueden suponer un consumo de corriente elevado.

Una línea de entrada digital consume la mayor cantidad de corriente cuando la tensión de entrada está entre la tensión de alimentación y la referencia. Esto es debido a que si la tensión de entrada está próxima al punto medio entre la alimentación y la referencia, los transistores que forman el buffer de entrada se polarizan en la región lineal lo que introduce un consumo de corriente considerable. Esto se puede evitar si cada línea puede configurarse como una entrada analógica, ya que este buffer se desconecta reduciendo así la corriente de la línea. Esto es debido a que las entradas analógicas tienen una impedancia de entrada muy elevada por lo que su consumo es mínimo.

Es por esto que si una línea no se utiliza, puede dejarse desconectada y configurada como línea de salida con un nivel lógico definido o se puede configurar como una entrada fija, externamente, a un nivel lógico definido.

También se debe tener en cuenta a la hora de inicializar un puerto, que tras un Power-on Reset, reset al alimentar al dispositivo, algunos registros como los PORT, los registros que contienen el valor de la línea, tienen un valor desconocido. Si los registros TRIS, los registros que configuran la dirección de la línea, se configuran antes que los PORT, es posible que se generen pulsos de corriente durante la inicialización del puerto. Por ejemplo, una forma segura de inicializar un puerto es primero borrar el contenido del registro PORT y luego configurar las líneas del puerto como salidas.

Referencias

Microchip Low Power solutions: Tips'n'Tricks.

Bloque sensor: Software, módulos principales

Seleccionadas las herramientas, he procedido a realizar el programa del sensor.

Antes de programar la funcionalidad completa del módulo sensor, se ha realizado la programación de los módulos de comunicación con el transceptor y con el sensor. De este modo, se puede verificar su funcionamiento independientemente. Así se reducen los problemas de depurado.

Comunicación con el transceptor

Tal y como se comentó en la entrada del transceptor, el protocolo de comunicación utiliza una línea de reloj y otra de datos, a parte de las líneas de configuración. Donde la frecuencia de la línea de reloj no podía ser superior a 1Mbps, es decir la duración mínima de cada bit debe ser de 1µs. Para reducir el tiempo de comunicación durante el cual el microcontrolador y el transceptor están activos, es decir suponen un consumo de corriente, se intentará operar a la frecuencia máxima.

Revisando la entrada del transceptor, se deduce que este módulo necesitará de, como mínimo, las siguientes funciones:

  • Enviar un paquete de datos a una dirección.
  • Entrar en modo recepción durante un tiempo y obtener el paquete recibido si es el caso.
  • Configurar el transceptor. Ya sea configurar la palabra completa (15bytes) o sólo una parte.

Donde se observa que a la función de enviar se le manda un paquete de datos y la de recibir lo devuelve. Este paquete que se enviará consiste en una serie de bytes que contienen la dirección y el dato. Para realizar un código más inteligible, se ha realizado una estructura que contiene un vector de bytes para la dirección y otro para los datos:

 
struct package
{
        unsigned char address[LEN_ADDR];
        unsigned char data[LEN_DATA];
};

Donde LEN_ADDR y LEN_DATA son macros que contienen la longitud de la dirección y de los datos respectivamente.

Tal y como se observa en la figura siguiente, el módulo dispone de tres funciones de uso interno o privadas (con fondo gris) cuya función se muestra a continuación. Son de alcance privado porque implementan una funcionalidad que se utiliza en más de una ocasión.

  • void RF_putByte(unsigned char databyte)

    Esta función le pasa bit a bit el byte al transceptor. Para ello, se le aplica al byte una máscara de un bit que se va desplazando.

  • void RF_configTx(void) y void RF_configRx(void)

    Estos métodos configuran al transceptor con un único bit el cual fija el modo de operación; en transmisión o en recepción.

Entonces, a la función enviar (RF_send) se le pasa la estructura package que contiene la dirección y los datos a enviar. Esta función configura el transceptor en modo transmisión (usa el método RF_configTx) y le pasa los datos del paquete al transceptor (mediante la función RF_putByte).

La función recibir (RF_receive) se le pasa un puntero con la estructura package donde almacenará los datos recibidos y un byte el cual fija el tiempo durante el cual el transceptor estará recibiendo. Durante este tiempo el microcontrolador está en modo de bajo consumo y es despertado por el perro guardián. Entonces el byte que hace configurable el tiempo fija el valor del prescaler del perro guardián. Al igual que para la función enviar, esta función hace uso de las funciones RF_putByte y RF_configRx.

Para configurar el transceptor está la función RF_configure, a la cual se le pasa un vector de bytes con los bytes de configuración y un byte que indica la longitud del vector. De este modo, se pueden configurar el número de bytes que se desee, 15 como máximo, teniendo en cuenta que el primer byte, posición 0 del vector, deberá ser el más significativo. Esta función hace uso de la función RF_putByte.

Para configurar de forma más cómoda los 15bytes del transceptor, se han creado una serie de macros o etiquetas que se encuentran en el fichero de cabecera transceiver.h. Se muestra un ejemplo a continuación.

 
const unsigned char transceiver_config[15]={DATA2_W,DATA1_W,ADDR2_4,ADDR2_3,ADDR2_2,ADDR2_1,
ADDR2_0,ADDR1_4,ADDR1_3,ADDR1_2,MY_ADDRESS_H,MY_ADDRESS_L,ADDR_W_16b|CRC_16b|CRC_EN_ENABLE,
RX2_EN_DISABLE|CM_SHOCKBURST|RFDR_SB_250KB|XO_F16MHZ|RF_PWR_20,RF_CH|RXEN_TX};

Comunicación con el sensor

La comunicación con el sensor se realiza mediante dos líneas, una de reloj y otra de datos. Como se ha visto, el sensor dispone de un registro de estado de un byte, que puede ser leído y escrito, y de una serie de comandos que permiten escritura/lectura de el registro de estado, realizar una medida de temperatura/humedad relativa y realizar un reset "suave".

Las funciones implementadas se muestran en la figura siguiente. Las de fondo gris son de uso interno o privadas. Su funcionalidad es la siguiente:

  • void S_putByte(const unsigned char databyte)

    Esta función gestiona la línea de datos y la de reloj enviándole al sensor el byte bit a bit. Para ello hace uso de una máscara con la que se obtiene el contenido del byte bit a bit.

  • unsigned char S_getByte(const unsigned char ack)

    Realiza el proceso inverso de la función anterior. Se comprueba la línea de datos y se va desplazando una máscara de un bit cada flanco de la línea de reloj. De este modo, cuando la línea de datos tenga el nivel lógico 1, su posición en el byte a obtener viene indicada por la máscara. El parámetro ack indica si se debe confirmar o no la recepción del byte. Mediante este parámetro se puede controlar el leer o no el CRC al confirmar o no la recepción del dato completo.

  • void S_transStart(void)

    Es un método que realiza la secuencia de inicio de transmisión. Esta secuencia se realiza cada vez que se desea comunicarse con el sensor.

De la figura se observa que existen dos métodos accesibles por el programador, el método S_resetConnection y S_softReset. Ambos realizan un reset del sensor con la diferencia de que el método S_resetConnection resetea únicamente la comunicación, y el método S_softReset resetea la comunicación y el registro de estado.

En cuanto a las funciones, la función S_read_status obtiene el registro de estado del sensor ( un byte). La función S_write_status envía al sensor el registro de estado que se le indica. Para facilitar la escritura del registro de estado, el fichero de cabecera sensor.h dispone de diversas macros. A continuación se muestra un ejemplo de su uso.

 
S_write_status(HEATER_OFF|OTP_NO_RELOAD|T14b_HR12b);    //Sensor wont reload OTP mem

La función más importante es S_measure, la encargada de realizar las medidas. Se le pasan como argumentos un puntero a una estructura del tipo measures, que se describe a continuación, y un parámetro que indica el tipo de medida; de humedad relativa o de temperatura. Para este último argumento se han definido dos macros, TEMP y RHUM, los cuales facilitan su uso. Respecto a la estructura del tipo measures se trata de una estructura que contiene un vector de dos bytes. Esto se ha realizado de este modo, para hacer más eficiente la función al operar con un puntero. A continuación se muestra la definición de la estructura measures.

 
struct measures
{
        unsigned char data[2]; //2 bytes because the maximum measure resolution is 14bits
};

Tal y como se comentó en la entrada del sensor, éste tarda un tiempo considerable en realizar las medidas. Es por esto que ese tiempo, para reducir el consumo, el microcontrolador se encuentra en modo de bajo consumo. Para sacar del modo de bajo consumo al microcontrolador una vez la medida esté disponible, se utiliza la interrupción ante un cambio de nivel (InterruptOnChange) que implementan las líneas del puerto A del microcontrolador. Este cambio de nivel es realizado por el sensor sobre la línea de datos; cuando la medida ha finalizado, pone la línea de datos a nivel bajo tal y como se comentó en la entrada del sensor.

Comunicación: Tipos y necesidades

Tal y como se mostró en la entrada de descripción del proyecto, el sistema precisa de dos tipos de comunicaciones bidireccionales, una inalámbrica y otra por cable. Al ser bidireccionales, cada tipo de comunicación se puede dividir en dos comunicaciones unidireccionales entre dos implicados. Es decir:

  • Comunicación inalámbrica: Sensor ↔ Maestro

    • Sensor → Maestro

    • Maestro → Sensor

  • Comunicación por cable: Maestro ↔ PC

    • Maestro → PC

    • PC → Maestro

De este modo cada parte de la división se puede simplificar como una comunicación unidireccional que suple unas necesidades de comunicación:

  • Comunicación inalámbrica: Sensor ↔ Maestro

    • Sensor → Maestro

      • Medidas de Humedad relativa y de Tª. Contiene las medidas realizadas sin procesar, es decir en "ticks".
      • Palabra de configuración del sensor. El maestro lo utilizará para verificar cambios realizados sobre la configuración del sensor.
      • Penúltima palabra de configuración del transceptor. Contiene la potencia de transmisión. El maestro lo utilizará para verificar cambios.
      • Inicio de transmisión. Contiene la dirección del sensor, la configuración del transceptor y del sensor. De este modo el maestro conoce el sensor y le asigna una ID.
      • Dato recibido correctamente.
      • Batería baja.
      • Errores.

    • Maestro → Sensor

      • Respuesta al comando inicio de transmisión.
      • Cambia la potencia de transmisión.
      • Cambia la configuración del sensor.
      • Cambia de canal.
      • Ajuste del tiempo entre medidas.
      • ¿Cuál es tu potencia de transmisión?.
      • ¿Cuál es la configuración del sensor?.
      • Duerme durante X tiempo.
      • Entra en modo test.
      • Apágate.

  • Comunicación por cable: Maestro ↔ PC

    • Maestro → PC

      • He recibido la siguiente medida de tal sensor.
      • Tal sensor tiene la siguiente configuración del sensor.
      • Tal sensor tiene la siguiente configuración del transceptor.
      • Tal sensor indica batería baja.
      • Esta es la dirección de tal sensor.
      • Se ha conectado un nuevo sensor.

    • PC → Maestro

      • Dime la configuración del sensor de tal sensor.
      • Dime la configuración del transceptor de tal sensor.
      • Dime la dirección de tal sensor.
      • Duerme al sensor tal durante tanto tiempo.
      • Ajusta el tiempo entre medidas del sensor tal a este valor.
      • Cambia el canal de los sensores en lista.
      • Cambia la potencia de transmisión de tal sensor.
      • Apaga tal sensor.
      • Modo test.

Estas necesidades forman el protocolo ya que el protocolo debe ser capaz de suplirlas todas.

Funcionamiento global

Antes de empezar a programar he pensado que es conveniente definir completamente la comunicación inalámbrica ya que es el punto central del proyecto y al ser nexo entre maestro y esclavo condiciona totalmente el funcionamiento de estos. Es por esto que esta entrada define en esencia el funcionamiento tanto del sensor como del transceptor y en algunos casos detalles del software de representación de datos.

Comunicación inalámbrica

Para reducir el consumo la comunicación debe evitar largos periodos de "polling" en el canal. Es por esto que se ha decidido que la comunicación se realizará acorde al funcionamiento del sensor.

El funcionamiento básico consiste en que el sensor realiza una medida cada periodo configurable (este periodo es muy prolongado respecto a la velocidad de funcionamiento de los microcontroladores por lo que la mayor parte de ese tiempo el microcontrolador se encuentra en modo de bajo consumo) ,envía el dato medido y entra en modo de bajo consumo esperando a realizar otra medida. Lógicamente este funcionamiento descrito muestra un tipo de comunicación unidireccional, el sensor no puede recibir datos. Por supuesto se necesita una comunicación bidireccional por lo que se debe añadir al funcionamiento del sensor la acción de ver si le han enviado algo, recibirlo y procesarlo.

No es eficiente dedicar el tiempo entre medidas al "muestreo" (polling) del canal debido al elevado consumo que introduciría. Es por esto que se ha decidido que el polling del canal se realizará durante un instante de tiempo cuya duración sea la necesaria para que el tiempo de procesado y respuesta del maestro permita la recepción del paquete. Para advertir al maestro de cuándo podrá realizar el envío de los datos, el polling se realizará tras enviar las medidas el sensor, es decir, el sensor enviará las medidas y dejara un tiempo ajustado para recibir datos.

De este modo, la dinámica de la comunicación consistirá en el envío de las medidas al maestro por parte del sensor; el sensor se mantendrá un tiempo a la escucha, tiempo que el maestro aprovechará para enviar los comandos oportunos al sensor. Una vez el sensor recibe los datos, inmediatamente deja de estar a la escucha, procesa los datos y entra en modo de bajo consumo esperando la medida siguiente. Esto se aprecia en la tabla siguiente.

Mapa de funcionamiento y consumo.
Estado t medida HR t medida Tª envio datos t en el aire t espera recepción espera medida
Micro duerme lee duerme lee envía duerme pon RX duerme
Transceptor duerme carga datos transmite duerme recibe apagado
Sensor mide mide duerme

Esta tabla muestra gráficamente la función de cada dispositivo del sensor en cada estado resaltando las funciones a razón del consumo que suponen. El consumo se muestra en forma de gradiente, siendo el azul el de menor consumo y el rojo más oscuro el de mayor.

Tal y como se aprecia, para reducir el consumo estático del nodo, se ha decidido desconectar el transceptor durante el tiempo entre medidas ya que su consumo estático, en modo reposo 12µA, es elevado en proporción al resto.

Iniciar la conexión inalámbrica:

Se debe permitir la conexión en caliente por lo que el proceso de conexión de un nuevo sensor a la red se muestra a continuación.

El maestro está escuchando (polling) contínuamente por el canal en el que esté trabajando. El sensor se sitúa junto al maestro y se enciende. Una vez encendido, el sensor envía el paquete de "conexión inicial" el cual contiene su dirección y la configuración de su sensor y de su transceptor.

Cuando el maestro recibe dicho paquete, actúa asignando a la dirección recibida, la del sensor, un número de identificación (ID) de menor tamaño que la dirección y posteriormente se la envía al sensor. A partir de ahora la comunicación del sensor con el maestro contendrá la ID que le indicará al maestro quién le está enviando el paquete. En el caso en el que el sensor no reciba respuesta del maestro, cambiará de canal y lo volverá a intentar. Si esto tampoco funcionase, se podría intentar hacer un cambio de potencia y volver a realizar el barrido de canales. Si todo esto falla, el sensor entrará en reposo y lo indicará con su indicador luminoso LED.

Una vez el maestro ha recibido el dato MY_NAME_IS del sensor y le ha respondido, manda la configuración, la dirección y la ID asignada al sensor al PC para ser procesada y mostrada por el software de representación.

Cuando el software de representación recibe los datos del sensor enviados por el maestro, este crea una nueva clase que contiene los paneles que se mostrarán para cada sensor pasándole los datos recibidos al constructor. Esto produce una ventana la cual contiene una gráfica donde se muestran los datos de HR y Tª y una serie de etiquetas y botones que permiten mostrar los datos del sensor y configurar el sensor.

Configurar el sensor:

Una vez establecida la conexión, para configurar el sensor el usuario interactúa mediante el software de representación. El software envía un comando que contiene la ID del sensor a modificar al maestro, el cual almacena en el "buffer FIFO" de la ID el comando a enviar para que el sensor actúe como se ha pedido. El "buffer" consiste en un array donde se van almacenando los comandos que se le quieren enviar a una ID (sensor) determinada; esto es así debido a la naturaleza de la comunicación.

Cuando un dato del sensor es recibido por el maestro, el maestro mira si el buffer correspondiente está vacío, en caso contrario, manda todos los comandos posibles (cada paquete puede contener hasta dos comandos) contenidos en el buffer.

Cuando el sensor recibe el dato, actúa en consecuencia y envía un paquete de respuesta el cual es interpretado por el maestro como cambio realizado correctamente y es comunicado al software de representación.

Una vez el sensor ha contestado, continúa con el funcionamiento normal. Esto supone una modificación del tiempo entre lecturas.

Bloque sensor: Software

Seleccionado el microcontrolador que se empleará en el bloque sensor, resta comenzar a programarlo. Para ello es preciso seleccionar algunos aspectos de la programación del microcontrolador:

Entorno de desarrollo y lenguaje de programación

Como se comentó, el lenguaje de programación que se utilizará es C ya que permite una comprensión del código mejor que ensamblador y una migración del código relativamente fácil para otras familias de microcontroladores y muy fácil para otros modelos de PIC.

Microchip no facilita ningún compilador de C para la familia PIC16 por lo que se debe recurrir a compiladores comerciales o libres. Existen diversos compiladores de C y entornos de desarrollo, a destacar:

  • CCS: Disponen de una versión de demo por 30 días además limitado. Como ventaja, incluye diversas bibliotecas que facilitan la programación pero el C que implementa no cumple completamente con el estándar ANSIC.
  • HI-TECH PICC: Dispone de una versión gratuita (LITE) la cual puede programar sin restricciones todos los microcontroladores de las familias PIC10/12/16. También disponen de una versión de evaluación sin restricciones de 45 días de su versión PRO la cual se diferencia de la LITE en que incluye un optimizador de código que, según dicen, mejora el código un 50%. Este compilador incluye un entorno de programación (IDE) gratuito basado en Eclipse, por lo que tanto el compilador como el entorno son multiplataforma.
  • Como alternativa libre, existe un porting a la familia PIC16 del compilador libre GCC hecho por Pedro José Ramírez Gutiérrez, estudiante de la Universidad de Málaga.

Pese a existir otros compiladores, no disponen de versiones de evaulación ilimitadas como PICC-PRO o gratuitas como PICC-LITE ni mucho menos libres. Es por esto que de entre las alternativas expuestas, el compilador PICC y el porting son las mejores soluciones.

Mi experiencia programando PIC es nula por lo que el entorno de desarrollo del que dispone el compilador PICC ayudará, ya que, entre otras cosas, permite simular el código. Entonces, se utilizará para el proyecto la versión de evaluación del compilador PICC-PRO dado que 45 días son más que suficientes para realizar el código. No obstante, una vez realizado el código y ganada expieriencia en la programación de PIC, se intentará migrar al porting de GCC dada su gran ventaja que es la libertad.

Programador

Dado que no se dispone de un programador de PIC, se deberá realizar uno o adquirirlo. Como se utilizará para el módulo maestro un PIC de la familia 18, el programador deberá ser capaz de programar ambos. El programador económico de Microchip (37.9€ en Farnell) PicKit2, soporta las familias PIC10/12/16/18/24 dsPIC30/33/32. Microchip facilita el esquemático y el firmware (en binario) del programador pero la compra de los componentes tiene aproximadamente el mismo coste que el programador por lo que se adquirirá.

El programador se muestra en la imagen de la derecha. Utiliza la programación en circuito (ICSP) utilizando dos líneas y el reset, permitiendo también el depurado en circuito (ICD) para los microcontroladores que lo permitan. Mediante el software que incluye se puede utilizar el programador como analizador lógico para bajas tasas de bits y como puerto serie.

Para programar un dispositivo, las líneas que se deben conectar al microcontrolador se muestran en el esquema siguiente:

Referencias

Microchip PICkit 2 Programmer/Debugger User's Guide.

Estudio preliminar: El software de control en el PC

Se realizará una aplicación para configurar los nodos de la red y para mostrar los valores de cada nodo. Esta aplicación debe ser preferentemente gráfica y debe ser capaz, como mínimo, de permitir al usuario acceder a toda la información de la red de medida, temperatura y humedad relativa en cada uno de los puntos de medición, así como modificar el período de actualización de los datos o ver un histórico de medidas.

En primer lugar, es importante seleccionar el lenguaje de programación con el que se realizará. Existe multitud de lenguajes de programación que permiten programación de entornos gráficos. Son los lenguajes orientados a objetos los que permiten programación de entornos gráficos, tales como C++, C#, Java, Phyton, MSVisualBasic, etc. Sin embargo, hay lenguajes no orientados a objetos que también lo permiten como por ejemplo C haciendo uso de la librería GTK y libglade.

Dado que normalmente se utilizan APIs intermedias entre el sistema operativo y la aplicación para facilitar la programación gráfica, como por ejemplo las API de BorlandC++, la aplicación resultante queda ligada a un único sistema operativo. No obstante, los lenguajes de programación interpretados como Java y Phyton, mantienen una relativa independencia con sistema operativo. Sin embargo, los lenguajes interpretados son típicamente más "lentos". Puesto que la velocidad en esta la aplicación no es crítica, se optará por un lenguaje interpretado dada la ventaja de ser multiplataforma.

De los lenguajes interpretados se ha optado por el lenguaje de programación Java por poseer mejores herramientas para su desarrollo.

El lenguaje de programación Java fue desarrollado por Sun Microsystems a principio de los 90. En el lenguaje de programación Java, el código fuente, de extensión .java, se compila, mediante el compilador de java (javac), obteniéndose un fichero de extensión .class. Estos ficheros no contienen código nativo de la plataforma del compilador; en su lugar contienen bytecodes, el lenguaje máquina de la máquina virtual Java (Java VM).

Es esta máquina virtual la encargada de convertir el lenguaje bytecodes a el lenguaje máquina específico de la arquitectura en la que sea ejecutado, por tanto la máquina virtual es específica de la arquitectura, tal y como muestra la figura siguiente.

Como la máquina virtual está disponible para diferentes sistemas y arquitecturas, el mismo fichero compilado .class, puede ser ejecutado en distintas arquitecturas.

Personalmente, desconozco el lenguaje de programación Java. No obstante tengo nociones básicas de programación orientada a objetos por lo que no espero que me sea complicado aprender a programar Java. Una de las ventajas de Java es su documentación, Sun tiene unos tutoriales muy completos (ver referencias) y existe multitud de bibliografía sobre el lenguaje. Además NetBeans, un entorno multiplataforma iniciado por Sun y ahora libre es muy cómodo y completo para la programación, soporta completamente todas las versiones de Java (Java SE, Java EE, Java ME), y dispone de diversas herramientas como un constructor de interfaces gráficas o soporte para el depurado línea a línea.

Referencias

Sun Microsystems The Java Tutorials.

Selección de componentes: Microcontrolador (μC) del bloque maestro

Antes de seleccionar el microcontrolador que se utilizará en el nodo maestro, se debe seleccionar el modo en el que este se comunicará con el ordenador.

Comunicación con el PC

Para la comunicación del nodo maestro con el PC se han barajado distintas alternativas. Actualmente, los ordenadores disponen principalmente de dos formas accesibles de comunicación; estas son el puerto serie y el puerto USB.

El puerto serie o RS-232, se caracteriza por ser el más sencillo de utilizar. Permite un rango bastante ámplio de velocidades, de 2400bps a 115200bps, y se encuentra implementado en multitud de microcontroladores con un coste bajo. No obstante, hoy en día está siendo desplazado por el USB y está cayendo en desuso; actualmente está limitado a ordenadores de escritorio, habiendo desaparecido prácticamente de los ordenadores portátiles. Esta situación desaconseja su uso.

El puerto USB (Universal serial bus) es un estándar para las comunicaciones serie. Inicialmente ideado para reemplazar a los puertos serie y paralelo, su uso ha ido creciendo hasta haberse convertido hoy en día en el estandar de comunicación entre el PC y cualquier otro dispositivo. Este puerto es fácil de usar para el usuario ( PnP o Plug and Play), es fácilmente expandible ( como se muestra más adelante) y permite la alimentación del dispositivo mediante el bus eliminando así la alimentación externa. En cuanto a la velocidad, la especificación USB 2.01 contempla tres modos de operación: Low Speed (LS) a 1.5Mb/s, Full Speed (FS) a 12Mb/s y High Speed (HS) 480Mb/s. Dada esta versatilidad, su topología es mucho más complicada que la de un puerto serie o paralelo. Su uso es mucho más complicado para el diseñador que el uso del puerto serie ya que debe implementar una serie de drivers propios o los definidos por alguna clase estándar. Una clase provee las especificaciones de un grupo de drivers comunes a distintos periféricos, es decir cómo se comunica el periférico con el maestro o host. El estándar contempla diversas clases entre las cuales se encuentra la clase CDC, Communications Device Class, que permite, entre otras cosas, emular un puerto serie, es decir físicamente es un puerto USB pero de cara al sistema operativo se comporta como un puerto serie. No obstante, la implementación de esta clase no es sencilla y precisa de conocimientos avanzados del estándar.

Por lo tanto el uso del USB supone las siguientes ventajas para el proyecto:

  • El nodo maestro no necesita de una fuente de alimentación externa pues se puede alimentar mediante el bus USB. El bus USB proporciona, según el estándar, una tensión de 5V y una corriente comprendida entre 100mA y 500mA dependiendo del host y del número de dispositivos conectados.
  • Facilita la conexión y el uso del nodo maestro por el usuario.
  • Permite el uso del nodo maestro en ordenadores portátiles de nueva generación.

Según lo expuesto, se concluye que el uso del puerto USB es recomendable frente al del puerto serie. Es por esto que se utilizará una comunicación USB entre el maestro y el PC. Esta comunicación utilizará la clase CDC para virtualizar un puerto serie lo que implica un desarrollo sencillo al disponer los sistemas operativos actuales del driver y un software para el PC sencillo pues deberá comunicarse con un puerto serie.

Se pueden encontrar en el mercado dispositivos que contienen dos transceptores, uno USB y otro RS-232. El dispositivo implementa la clase CDC simplificando así la conexión entre el microcontrolador y el ordenador a una conexión RS-232. También existen microcontroladores con un transceptor USB integrado. Estos últimos suponen un menor costo pero la implementación de la clase CDC la debe realizar el programador.

El componente que se utilizará es un microcontrolador de Microchip de la gama PIC18 con un transceptor USB integrado puesto que Microchip proporciona las implementaciones de las clases estándar HID (Human Interface Device) utilizada principalmente para ratones y teclados, CDC (Communications Device Class) y MSD (Mass Storage Device) utilizada para memorias o discos duros externos. Esta implementación está soportada por los microcontroladores PIC18F2455/2550/4455/4550. Las diferencias entre estos se muestra a continuación.

Dado que las necesidades del proyecto no son elevadas, la solución de compromiso es el microcontrolador PIC18F2455 dado que dispone del menor número de lineas de entrada/salida y del menor número de memoria Flash.

Para hacer uso de la implementación de Microchip de la clase CDC no se precisan demasiados conocimientos sobre el USB, no obstante, se puede encontrar información en el estándar o en páginas en castellano.

Notas
1

La especificación USB 1.1 unicamente contempla los modos LS y FS.

Referencias

Microchip AN956 Migrating Applications to USB from RS-232 UART with Minimal Impact on PC Software.

Microchip USB design center.

Microchip PIC 18F2455/2550/4455/4550 Datasheet.

USB.org USB 2.0 Specification.

Craig Peacock USB in a NutShell.

Selección de componentes: Batería.

Principalmente las baterías se pueden dividir en dos grupos, las recargables y las no recargables.

Las baterías no recargables, también conocidas como primarias, son aquellas que se desechan cuando se agotan. Las baterías recargables, también conocidas como secundarias, son aquellas que pueden ser recargadas una vez se han agotado. En general, su principal característica es la máxima corriente de descarga, que es mayor para las recargables, y el ciclo de funcionamiento, siendo mayor en las recargables.

De este modo, se utilizan las baterías recargables en aplicaciones que precisan extraer corriente relativamente elevada durante largos periodos de tiempo. No obstante, debido a su elevado precio, se utilizan cuando el coste de reemplazamiento en el caso de utilizar baterías no recargables es inviable.

Parámetros característicos

Las baterías no recargables se dividen a su vez en varios grupos dependiendo de su composición química, de este modo existen baterías de litio, alcalinas, de óxido de plata, óxido de níquel, de zinc-carbón, zinc-aire y muchas otras. Para poder realizar una comparativa es necesario conocer una serie de parámetros acerca de las baterías.

Capacidad de corriente

La capacidad de corriente es la cantidad de corriente entregada por una batería bajo unas determinadas condiciones. Se expresa como el producto de la corriente de descarga y el tiempo de descarga por lo que viene dado por Ah o más comúnmente en mAh. Por lo tanto se expresa como la cantidad de corriente que se puede extraer de la batería antes de que se descargue.

Entonces, para determinar la duración de la batería ante una corriente de descarga constante, basta con dividir la capacidad de corriente por la corriente de descarga aplicada, obteniéndose así las horas de duración de la batería.

Máxima corriente de descarga y tensión de operación

La tensión de operación en las baterías depende de la composición química de las mismas. En la práctica, esta tensión varía conforme se descarga y depende de la carga aplicada a la batería, es decir la corriente de descarga a la que es sometida la batería. Cuando la resistencia de carga disminuye, aumenta la corriente de descarga, la tensión de operación y la capacidad de la batería disminuyen. Estas variaciones dependen de la composición química de la batería y de la temperatura de operación (tienden a ser menores a menor temperatura).

La gráfica siguiente proporcionada por el fabricante Maxell muestra todos sus productos en función de la tensión de operación frente a la capacidad de corriente. Pese a que muestra sólo sus productos, se puede tomar como referencia.

Donde:

  • LR:Alcalina (tamaño micro).
  • SR:Óxido de plata.
  • TC:Titanio-Carbón-Litio recargable.
  • ML:Litio-Dióxido de Manganeso recargable.
  • ER:Litio-Thionyl-Chloride.
  • CR:Litio-Dióxido de Manganeso.
  • ICSP:Litio-ion recargable
Descarga de una batería

Una batería se puede descargar de diferentes formas dependiendo del tipo de carga, que tendrá un efecto directo en la vida de la batería. Los modos típicos de descarga son:

  • Resistencia constante. Es cuando la carga mantiene una resistencia constante a lo largo del ciclo de descarga. Al ser una carga resistiva, conforme se va descargando la batería, la corriente y la tensión decaen. Por lo tanto, la batería se descargará de forma rápida lo que implica una vida corta.

  • Corriente constante: Cuando la carga extrae la misma corriente durante la descarga. En este modo la vida de la batería es mayor que para la resistencia constante ya que se extrae siempre la misma corriente independientemente de la caída de la tensión de operación.

  • Potencia constante: La corriente de descarga aumenta mientras la tensión de operación decrece. Es el modo más eficiente ya que la batería se puede descargar más allá de su tensión final (tensión a la cual se supone que se ha agotado la batería) dado que se aumenta el consumo de corriente para compensar.

Generalmente, el fabricante facilita la característica de descarga para una resistencia constante.

Tamaño
(referencia http://data.energizer.com/SearchResult.aspx)

Las baterías presentan distintas formas y tamaños dependiendo de su composición química y de su capacidad de corriente. Principalmente, las baterías no recargables se presentan en tres encapsulados distintos; cilíndrico, de botón y rectangular.

En general, las baterías más voluminosas poseen una mayor capacidad de corriente. De este modo, los encapsulados más voluminosos son el cilíndrico (AA 50x14.5 y AAA 44.5x10) y el rectangular (9V 48.5x26.5) y las baterías de botón son mucho menos voluminosas (CR2025 2.5x20 y CR2450 5x24). Del mismo modo, la capacidad de corriente típica de una batería cilíndrica AA alcalina es de 2850mAh y de una AAA alcalina es de 1250mAh mientras que para las baterías de botón, la capacidad de corriente típica de una batería CR2025 es de 160mAh y para una CR2450 es de 620mAh. Hay que destacar que las baterías de botón son mayoritariamente de litio, cuya principal característica es que su tensión de operación es de 3V a diferencia del resto de composiciones químicas cuya tensión es de 1.5V.

Selección del tipo de batería

Las necesidades del proyecto respecto a los parámetros anteriores se muestran a continuación.

El sensor descargará la batería mediante una corriente constante ya que, para descargarla mediante una potencia constante, se precisaría de un regulador conmutado (DC-DC) el cual ajuste la corriente conforme caiga la tensión y este supondría un consumo superior al del sistema en reposo disminuyendo la autonomía.

Los resultados de la estimación de consumo muestran una corriente promedio del orden de 60µA en el peor de los escenarios. Es por esto que para que los dispositivos tengan, en el peor de los escenarios, una autonomía de como mínimo medio año, la capacidad de corriente necesaria vendrá dada por:

En cuanto a la tensión de operación, el dispositivo que precisa de la mayor mínima tensión de operación es el sensor, capaz de operar en un rango comprendido entre 2.4V y 5.5V. Es por esto que la tensión mínima de operación del nodo sensor es de 2.4V.

Por lo que respecta a la máxima corriente de descarga, se debe tener en cuenta que se precisan de breves pulsos de corriente del orden de 10mA. No obstante, la duración de estos pulsos es muy breve, centenares de microsegundos, por lo que la corriente promedio puede considerarse la de descarga.

También se debe tener en cuenta que se busca el menor tamaño posible y las dimensiones de la batería son las más significantes respecto el resto de componentes. No obstante, este no es un parámetro crítico, primando la capacidad de corriente (autonomía).

Conocidos los parámetros, la tabla siguiente muestra las principales características de las distintas baterías según su composición química.

Tal y como se ha estimado, el consumo de corriente es de unos 40µA en el peor de los escenarios por lo que la capacidad de corriente necesaria para asegurar un funcionamiento durante al menos medio año, en el peor de los escenarios, es de unos 173mA. Se observa que cualquier familia contempla la capacidad necesaria dentro del rango soportado. Es por esto que este parámetro no permite discriminar entre un tipo de batería u otro.

Atendiendo a la tensión de operación, la elección lógica son las baterías de litio ya que su tensión de operación es de 3V por lo que sólo se precisaría una batería. En el caso de utilizar otro tipo de batería como la alcalina, sería necesaria la asociación en serie de dos de ellas, con el consiguiente aumento de tamaño y coste que esto supone.

Considerando la corriente de descarga, Maxell facilita la tabla siguiente, en la que se muestran los distintos tipos de batería con las máximas corrientes de descarga que soportan (en verde).

En las tablas de la estimación del consumo se observa como la corriente de pico máxima es de unos 18mA. Esta corriente se mantiene durante un breve instante de tiempo por lo que en promedio es mucho menor. Es por esto que una batería comprendida entre 1mA y 10mA debería ser suficiente aunque someter a este estrés a la batería puede mermar su capacidad de corriente y su vida útil.

En cuanto al tamaño, las baterías más pequeñas son las de tipo botón. Las baterías CR de litio están en formato botón y como se ha comentado, al ser de litio, sólo se necesitaría una.

Por lo que respecta al coste, en la tabla se observa como las baterías alcalinas y las zinc-carbón son las de menor coste relativo. No obstante, se debe tener en cuenta que serían necesarias dos baterías en serie, debido a su tensión de operación, duplicando el coste y el tamaño.

Se concluye que la solución de compromiso es el uso de una batería de litio de botón. Además, su coste relativo alto no lo es tanto para las baterías de menor capacidad de corriente (CR2025 0.73€y CR3032 1.05€ de Panasonic).

Selección de la batería

Dentro de la gama de baterías de lítio de botón (gama CR) existen distintos modelos de batería que difieren del resto en su capacidad de corriente y en sus dimensiones. Por ejemplo, el fabricante Energizer facilita la siguiente tabla en la que se muestran sus productos de la gama CR.

Se han marcado con fondo gris las baterías que no cumplen la condición de almenos medio año de autonomía, de este modo cualquiera de las que tiene el fondo blanco asegura una autonomía mayor al medio año en el peor de los escenarios. La tabla siguiente muestra la vida de la batería en el peor de los escenarios para los distintos modelos.

La vida de la batería aumenta considerablemente al aumentar el tiempo entre medidas. Por ejemplo, si consideramos el escenario descrito anteriormente pero con un tiempo entre medidas de 60 segundos, el promedio de consumo es de 9.31µA tomando los valores máximos, por lo que la duración de la batería se muestra en la tabla siguiente.

Se pueden comprobar los cálculos realizados mediante la gráfica que proporciona Maxell, que muestra el consumo de corriente en función de la duración de la batería para toda la gama CR.

Dado que la vida útil es muy dependiente de la configuración del sensor, en concreto del tiempo entre muestras, se ha decidido que la batería sea seleccionada por el usuario dependiendo del uso que vaya a darle, de este modo se ahorran costes pues la batería CR2025 tiene un coste inferior a 1€ y la batería CR2450 tiene un coste de unos 3€.

Referencias

Maxell Batteries Product Lineup.

Microchip AN606 Low Power Design Using PICmicro Microcontrollers.

Selección de componentes: Batería, estimación de consumo.

Se han seleccionado todos los componentes que forman el nodo sensor salvo la batería. Para poder seleccionar la batería, es preciso realizar una estimación preliminar del consumo que tendrá el sistema. Esta estimación se ha realizado con los datos disponibles, los facilitados por el fabricante, y ha precisado un esbozo del funcionamiento del nodo sensor y de los componentes que lo forman.

Funcionamiento del nodo sensor

Una primera aproximación al funcionamiento del nodo sensor se puede observar en la figura siguiente.

Se trata de un funcionamiento cíclico y se puede describir en los siguientes pasos:

  1. El sensor realiza una medida de humedad relativa.
  2. El sensor realiza una medida de temperatura.
  3. El microcontrolador alimenta al transceptor y lo configura.
  4. El transceptor envía los datos medidos.
  5. El transceptor entra en modo de recepción durante un tiempo determinado.
  6. El microcontrolador procesa el dato recibido y le corta la alimentación al transceptor.
  7. El microcontrolador entra en modo reposo durante múltiplos de cinco segundos.

Estos estados se han agrupado según el estado de los componentes. De este modo se tiene:

  1. Medida de HR y de Temperatura. El transceptor no está alimentado, no supone un consumo de corriente, el sensor está midiendo y el microcontrolador está en modo reposo.
  2. Transmisión. El transceptor se encuentra en modo de transmisión, el sensor y el microcontrolador en reposo.
  3. Recepción. El transceptor se encuentra en modo de recepción, el sensor y el microcontrolador en reposo.
  4. Configuración del transceptor. El transceptor y el sensor se encuentran en reposo y el microcontrolador se encuentra activo.
  5. Activo. En este estado se han agrupado las instrucciones ejecutadas por el microcontrolador a lo largo del funcionamiento. En este estado el transceptor y el sensor están en reposo y el microcontrolador se encuentra activo.
  6. Reposo. El transceptor no está alimentado, el sensor y el microcontrolador estan en reposo.

Para la estimación, se ha tomado el peor escenario posible, es decir el transceptor transmitiendo a la máxima potencia a una tasa de 250KB, el sensor midiendo a la máxima resolución y realizándose una medida cada cinco segundos. El microcontrolador se supone alimentado a 3 voltios, activo a 4MHz, con el watchdog activo durante el reposo y con el resto de periféricos desactivados.

Para obtener la duración del estado de transmisión, se ha supuesto que se enviarán 10bytes, 2 de dirección, 2 de CRC y 6 de datos donde 4 son las medidas de HR y Temperatura y los otros dos uno para el comando y el otro para la identificación del nodo. De este modo, se ha podido obtener el tiempo de transmisión utilizando la fórmula, facilitada por el fabricante, 1/250Kbps * (10+1).

Para el estado de Configuración del transceptor se ha supuesto una comunicación con el microcontrolador a 1Mhz.

Con este escenario, se han obtenido dos estimaciones, una para los valores facilitados por el fabricante denominados típicos y otra para los denominados máximos. Estas estimaciones se han realizado obteniendo la carga que supone cada estado que se define como la corriente que consume el sistema durante por su duración(Amperios por segundo). Estas cargas individuales se han sumado obteniéndose la carga total, la cual, dividida por la duración total del ciclo de estados, indica el consumo promedio de corriente. Esto se ha representado en las tablas siguientes.

Valores típicos

Valores máximos

En resumen, se ha estimado que el consumo promedio de corriente estará comprendido entre los 35µA y los 39µA.