Pues como comentaba nayma, aparte de poder definir en vectores lo pines, en este ejemplo vamos a utilizar estructuras de datos para definir los interruptores, una matriz para definir la máquina de estados y finalmente otro vector (array) para ejecutar las acciones.
El código queda muy limpio y sencillo, la mayor parte de las cosas son declaración de tipos y variables.
#include <Arduino.h>
#define OFF 0
#define SWITCHING_ON 1
#define ON 2
#define SWITCHING_OFF 3
// Defino la estructura de datos de mi interruptor
typedef struct
{
uint8_t buttonPin;
uint8_t miEstado;
uint8_t ledPin;
} t_switch;
// Variable con mis interruptores
t_switch miInterruptor[] =
{
// boton, estado, LED
{ 2, OFF, 13 },
{ 4, OFF, 12 },
{ 7, OFF, 8 }
};
// Definir transiciones de mi maquina de estados
// ---------------------------------------------
const uint8_t maquinaInterruptor[2][4] =
{
// Estados
//OFF, SWITCHING_ON, ON, SWITCHING_OFF
{ OFF, ON, ON, SWITCHING_OFF }, // transiciones cuando boton sin pulsar
{ SWITCHING_ON, SWITCHING_ON, SWITCHING_OFF, SWITCHING_OFF } // transiciones cuando boton pulsado
};
// Definir las acciones en cada estado
const uint8_t accion[4] = { LOW, HIGH, HIGH, LOW };
// Numero de interruptores
#define NUM_SWITCH ( sizeof(miInterruptor)/sizeof(t_switch) )
void scanAndSet ( uint8_t inPin, uint8_t outPin, uint8_t &state )
{
uint8_t nuevoEstado;
// Saco mi nuevo estado, sando la lectura del boton y mi estado actual
nuevoEstado = maquinaInterruptor[digitalRead(inPin)][state];
// Si el nuevo estado es diferente del antiguo ejecuto la accion
// en este caso actuar sobre el LED
if ( nuevoEstado != state )
{
digitalWrite ( outPin, accion[nuevoEstado] );
state = nuevoEstado;
}
}
void setup()
{
for ( uint8_t i = 0; i < NUM_SWITCH; i++ )
{
pinMode ( miInterruptor[i].buttonPin, INPUT );
pinMode ( miInterruptor[i].ledPin, OUTPUT );
}
}
void loop()
{
for ( uint8_t i = 0; i < NUM_SWITCH; i++ )
{
scanAndSet ( miInterruptor[i].buttonPin, miInterruptor[i].ledPin, miInterruptor[i].miEstado );
}
delay ( 100 );
}
Como veis, el código que ejecuta la maquina de estados, es muy simple. Lo único que hace es cambiar, el estado (utilizando la matriz de transiciones indexada por: el estado del pin y el estado actual). Funcionaría de la siguiente forma:
Supongamos que mi estado actual es SWITCHING_ON y el botón está a low, por lo tanto: maquinaInterruptor[1][0] == ON. Mi nuevo estado sería ON, ahora compruebo si ha habido cambio de estado e indexo la acción de digitalWrite con mi acción.
Espero que os haya gustado la solución. Esta es una solución muy rápida y fácil de implementar para una máquina de estados que no cambie mucho. Para rizar el rizo, se podría haber definido unos "functores" que ejecutasen la acción del estado en vez de usar el digitalWrite tal cual.
La solución algorítmica hace exactamente lo mismo que esta. Esta es más rápida pero consume un poco más de memoria, las matrices se podrían haber definido en memoria flash con lo que habríamos ganado en RAM.
El siguiente paso sería hacer lo mismo pero orientado a objetos.
Por cierto, por la razón que sea no me ha dejado definir el nombre de los estados como un tipo enumerado, que hubiese sido lo suyo. Ha saltado con un error de compilación absurdo.
typedef enum {OFF, SWITCHING_ON, ON, SWITCHING_OFF} t_estado;