- Queremos hacer varias cosas, es decir, no nos vale con quedarnos en un while y esperar a que llegue algo.
- Queremos poder gestionar la plataforma.
- La placa MEGA tiene varios temporizadores.
Bueno, todo esto nos lleva al uso de las interrupciones. El micro de la placa MEGA (ATMega2560 http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf) tiene 3 temporizadores. Curiosenado un poco por internet he encontrado una librería (esta es la potencia de arduino) que encapsula el uso de éstos. La librería es la TimerThree https://www.pjrc.com/teensy/td_libs_TimerOne.html funciona bien para lo que yo la he utilizado.
He generado un fichero "Definiciones.h" que irá englobando todas las definiciones que vamos a meter en compilador (es decir, no gestionables externamente). Básicamente, para no volvernos locos buscando las constantes y demás.
//
// Fichero: Definiciones.h
// Version: 2.0
// Autor: Raul Hermosa
// Fecha: 20 de julio de 2016
// Descripcion: Fichero que define los parámetros fundamentales del sistema
//
#define _DEFINICIONES_h
// define el pin CS para la SD, funciona mediante bus SPI
#define CS_SD 53
// definicion de tiempos
#define TEMPO_POLL_SENS 30 // Cada 30 segundos
#define TEMPO_POLL_PROGS 10 // Cada 10 segundos
#define TEMPO_REINI_CONFIG 2 // Cada 2 segundos
#define TEMPO_POLL_MAN_DISP 0.2 // Cada 200 milisegundos
#define TEMPO_POLL_PET_REMOTA 0.3 // Cada 300 mseg
#define NUM_POLLS_CHECK_WIFI 500 // cada 500 veces que se cheque la conf, se chequea
// el servidor WIFI
#define TEMPO_TICK 10000 // define el tiempo de interrup (tick) en microseg en Timer3
#define USEGS_EN_SEG 1000000 // microsegs de 1 segundo
//definiciones de los numeros de ticks
#define NUM_TICKS_SEG USEGS_EN_SEG/TEMPO_TICK // Ticks cada 1 segundo
#define NUM_TICKS_SENS TEMPO_POLL_SENS*NUM_TICKS_SEG
#define NUM_TICKS_PROGS TEMPO_POLL_PROGS*NUM_TICKS_SEG
#define NUM_TICKS_CONFIG TEMPO_REINI_CONFIG*NUM_TICKS_SEG
#define NUM_TICKS_MAN_DISP TEMPO_POLL_MAN_DISP*NUM_TICKS_SEG
#define NUM_TICKS_PET_REMOTA TEMPO_POLL_PET_REMOTA*NUM_TICKS_SEG
#endif //_DEFINICIONES_h_
Bueno, la realidad es que nuestro .ino es de lo más sencillo. Sólo programa una serie de temporizadores y pone un flag para que se ejecuten diferentes métodos.
//
// Fichero: ControlDomoPlat.ino
// Version: 2.0
// Autor: Raul Hermosa
// Fecha: 20 de julio de 2016
// Descripcion: Fichero principal de ejecucion de plataforma IoT
//
#include <TimerThree.h>
#include "GestorConfiguracion.h"
#include "Definiciones.h"
// Crea el Gestor de Configuracion para que habilite la configuracion del sistema
GestorConfiguracionClass _config;
// Variables locales
int num_ticks_seg;
int num_ticks_sens;
int num_ticks_progs;
int num_ticks_config;
int num_ticks_man_disp;
int num_ticks_pet_remota;
bool chequea_tick_seg;
bool chequea_tick_sens;
bool chequea_tick_progs;
bool chequea_tick_config;
bool chequea_tick_man_disp;
bool chequea_tick_pet_remota;
void setup()
{
Serial.begin(VEL_PUERTO_SERIE);
delay(200);
Serial.println(F("\n\nPUERTO SERIE INICIADO"));
_config.init();
Serial.println(F("\n\nINICIANDO TEMPOS"));
Timer3.initialize(TEMPO_TICK);
Timer3.attachInterrupt(ISR_tick);
// Configuro el temporizador para controlar los ticks donde controlar las tareas periodicas
num_ticks_seg = 0;
num_ticks_sens = 0;
num_ticks_config = 0;
num_ticks_man_disp = 0;
num_ticks_pet_remota = 0;
chequea_tick_seg = false;
chequea_tick_sens = false;
chequea_tick_progs = false;
chequea_tick_config = false;
chequea_tick_man_disp = false;
chequea_tick_pet_remota = false;
}
void loop()
{
if (chequea_tick_sens)
{
_config.escribe_sensor_log();
chequea_tick_sens = false;
}
if (chequea_tick_config)
{
_config.configura_sistema();
chequea_tick_config = false;
}
if (chequea_tick_man_disp)
{
// TODO: ivocar un metodo de chequeo de peticion manual
// _config.chequea_pet_manual();
chequea_tick_man_disp = false;
}
if (chequea_tick_pet_remota)
{
//Serial.println(F("Chequeo peticiones web"));
//_config.chequea_peticion_remota();
chequea_tick_pet_remota = false;
}
if (chequea_tick_progs)
{
//Serial.print(F("Chequeando PROGS: ")); Serial.println(_rtc.getData().toString());
//_config.chequea_tempos();
chequea_tick_progs = false;
}
}
void ISR_tick()
{
if (num_ticks_seg++ >= NUM_TICKS_SEG)
{
chequea_tick_seg = true;
num_ticks_seg = 0;
}
else if (num_ticks_sens++ >= NUM_TICKS_SENS)
{
chequea_tick_sens = true;
num_ticks_sens = 0;
}
else if (num_ticks_config++ >= NUM_TICKS_CONFIG)
{
chequea_tick_config = true;
num_ticks_config = 0;
}
else if (num_ticks_progs++ >= NUM_TICKS_PROGS)
{
chequea_tick_progs = true;
num_ticks_progs = 0;
}
else if (num_ticks_man_disp++ >= NUM_TICKS_MAN_DISP)
{
chequea_tick_man_disp = true;
num_ticks_man_disp = 0;
}
else if (num_ticks_pet_remota++ >= NUM_TICKS_PET_REMOTA)
{
chequea_tick_pet_remota = true;
num_ticks_pet_remota = 0;
}
}
Como puede verse, al final lo que he hecho es utilizar un temporizador del micro para generar los temporizadores que a mi me interesan. Defino una serie de tiempos en Definiciones.h (lo he hecho para configurar en segundos y dar claridad), pongo unos contadores, configuro el tempo 3 y cada vez que salta la interrupción (invoca la rutina ISR_tick) controlo con los contadores si es el timeout de cada uno. Como siempre, en esa rutina no conviene hacer nada (evita comprometer datos), sólo pongo un flag y reinicio los contadores. En el loop es donde invoco los métodos que me interesan a través de un obejto de clase GestorConfiguracion, de la que todavía no hemos hablado.
Como puede verse todo muy fácil, cada vez que acabemos de hacer una cosa, esperamos a que nos avise el flag de qué toca revisar. De esta forma evitamos quedarnos enganchados con cosas como delay() o while (xx.available()), que sirven para otros propósitos.
Ahora ya podemos complicarnos la vida en los métodos invocados, si se quiere hacer pruebas, activar el monitor serie y lo podéis ir viendo, a efectos de prueba no hace falta la clase GestorConfiguracion, se puede imprimir algo y ya está.
Aunque es muy evidente, espero que os sirva para esto o para otros proyectos.
No hay comentarios:
Publicar un comentario