Led Class - Part 1

Introduction
Dans l'article "PushButton class - part 1" je jetais les bases d'une classe permettant de capturer facilement l'état des boutons poussoirs mais surtout savoir s'ils avaient été pressé, combien de fois et en déparasitant la capture d'état de façon logiciel.
Cette petite introduction pour mettre en avant l'utilité et l'efficacité d'un tel outils car, en effet, j'y reviens tout le temps.

Une classe pour contrôler une led
Dans le même ordre idée, pourquoi ne pas utiliser une classe (ou des fonctions utilitaires) pour contrôler une Led.
De prime abord cela peut sembler ridicule s'il faut seulement allumer ou éteindre la dite LED.
Par contre, cela devient beaucoup plus pertinent s'il faut faire clignoter la LED à intervalle régulier sans bloquer l'exécution du logiciel.

Pour faire clignoter une LED sans blocage logiciel, vous pouvez consulter l'article "blink without delay" disponible sur le site officiel d'arduino.cc.

Un cas d'utilisation réel
Justement j'ai besoin d'une LED clignotante non bloquante pour le projet ArduinoCar.
ArduinoCar utilise une state machine (machine à état) pour fonctionner et je dois justement y inclure une LED clignotante sans perturber ni bloquer le fonctionnement du logiciel existant.
L'idéal serait de pouvoir le faire facilement à l'aide de quelques fonctions simple d'emploi.

Dans le cadre du projet ArduinoCar, je veux utiliser un bouton marche/arrêt et une LED qui s'illumine durant l'activation du programme (durée de fonctionnement pré-programmé de 60 secondes).
Je veux également utiliser un second bouton pour activer/désactiver un mode debug afin de faciliter le débogage de la voiture. En mode debug, la LED doit clignoter au lieu d'être fixe.

Un développeur perspicace détectera immédiatement la multitude d'états et de variables nécessaire à l'aboutissement de mes exigences.
L'utilisation d'une classe pour le contrôle d'une LED n'est donc plus si absurde que cela.
Par ailleurs, l'utilisation d'une classe (ou fonctions utilitaires) ne polluera pas le programme principal avec variables et états propres à l'état de la LED.

Quelques détails techniques
Avant d'écrire la classe finale, je vais d'abord m'attarder sur les fonctions utilitaires nécessaires à la réalisation de mon objectif (voir le contenu du LedTools.h).

La structure ledData
Avant d'aborder les premières fonctions, je vais aborder la structure me permettant de maintenir toutes les variables et états nécessaires au bon fonctionnement des fonctions de type "led".
Cette structure sera passée en paramètre aux diverses fonctions utilitaires de contrôle de la "led".

struct  ledData attachLed( int pin, byte displayType )
Fonction qui configure la pin pour contrôler la LED et retourne une structure ledData.
Le deuxième paramètre permet d'indiquer si la led est fixe (LED_FIXED) ou clignotante (LED_BLINK).
Dans le cas d'une led clignotante, l'intervalle de clignotement est fixé par défaut à 1 seconde.

boolean updateLed( struct ledData* data )
La fonction magique qu'il faut appeler dans loop().
C'est elle qui s'occupera de faire clignoter/allumer-éteindre la LED de façon totalement indépendante. Il suffit d'appeler la fonction avec la structure ledData retournée par attachLed.
La fonction retourne true lorsque la led est lumineuse.

void turnLed( struct ledData* data, boolean state )
Permet de commander l'allumage ou l'extinction de la LED.
Forcement, pour une led de type clignotante, turnLed( ledData, true ) active le clignotement de la LED alors que turnLed( ledData, false ) l'éteint jusqu'à nouvel ordre.


void setBlinkInterval( struct ledData* data, long interval )
Permet de modifier l'intervalle de clignotement d'une LED de type LED_BLINK.

Exemple
En guise de test, j'ai écris un petit programme de test qui utilise LedTools.h et ButtonTools.h.
Les deux boutons permettent de modifier un état debugState et startState.
En fonction de l'état de debugState, la led clignote ou reste éteinte.

Notez au passage la simplicité d'implémentation de attachLed, updateLed et turnLed.

Variables
int pinStart = 7; // Start/Stop - Brun
int pinDebug = 8; // Debug Switch - Orange

int pinLed = 9;    // State Led

buttonData btnStart;
buttonData btnDebug;
ledData    ledYellow;
boolean debugState = false; // Debug Mode activated
boolean startState = false; // Start/Stop mode

Initialisation
La fonction setup() déclare les boutons et la led.
void setup() {
  Serial.begin( 9600 );

  // Boutons
  btnStart = attachButton( pinStart );
  btnDebug = attachButton( pinDebug );
  
  //-- Declare a FIXED LIGHTNING led ----------
  //ledYellow = attachLed( pinLed, LED_FIXED );
  
  //-- Declare a BLINKING led -----------------
  ledYellow = attachLed( pinLed, LED_BLINK );
  setBlinkInterval( &ledYellow, 300 ); // Change the default blink interval 
}

Contrôle des états
La fonction loop() commence par faire les différents appel aux fonctions updates (updateButton pour les boutons et updateLed pour la Led).
Par la suite, le code change les états debugState et startState en fonction des boutons pressés.
Finalement, la LED est activée/désactivée en fonction de l'état debugState.
void loop(){
  // Update all the button statistics
  updateButton( &btnStart ); 
  updateButton( &btnDebug );

  // Update the led
  updateLed( &ledYellow );  
   
  // Wait the the user press the button "btn" to send the 
  // resume of operation over the serial port
  boolean bChanged = false;
  
  // When the btn is pressed (read once only)
  if( pressedReadAllButton( &btnStart ) ) {
    startState = !(startState);
    bChanged = true;
  }  
  
  if( pressedReadAllButton( &btnDebug ) ){
    debugState = !(debugState);
    bChanged = true;
  }
  
  // Afficher un changement d'état
  if( bChanged ){
    Serial.println( " -----------------------------" );
    if( startState ) 
      Serial.println( "Started [X]" );
    else
      Serial.println( "Started [ ]" );
    
    
    if( debugState ) 
      Serial.println( "Debug [X]" );
    else
      Serial.println( "Debug [ ]" );
      
    
    bChanged = false;
  }
  
  turnLed( &ledYellow, debugState );
}

Code source
Le code source de l'exemple est disponible dans le lien ci-dessous.
Source: ArduinoCar_Test_BtnInterface.zip 

Suite de l'article Led Class - Part 2 et Led Class - Part 3 | PushButton Class - Part 2