Skip to the content.

Torna all’indice

ESEMPIO DI SFM

Ci concentreremo sugli aspetti pratici della programmazione di un compito utilizzando un FSM, utilizzando il LED lampeggiante come esempio iniziale. Per essere chiari, questa non è un’attività che necessita davvero di un approccio FSM, ma è utile illustrare come passare dal codice lineare a una struttura FSM con un esempio semplice e familiare.

Il codice “lineare” avrebbe grossomodo questa forma:

#define LED_DELAY 1000       // periodo base in millisecondi
byte LED =7; 
unsigned long timeLastTransition =0;  

void setup()
{
  	pinMode(LED, OUTPUT);   
}

void loop()
{
	blink();
}

void blink(){
	if(millis()-precm >= (unsigned long) LED_DELAY){  
		timeLastTransition = millis();        
		digitalWrite(LED, !digitalRead(LED));		
	}
}

Una prima versione FSM del codice potrebbe essere:

void blink()
{
  const uint32_t LED_DELAY = 1000;
  static uint8_t state = 0;
  static uint32_t timeLastTransition = 0;
 
  switch (state)
  {
    case 0:   // toggle the LED 
      digitalWrite(LED, !digitalRead(LED));
      timeLastTransition = millis();
      state = 1;
      break;
 
    case 1:   // wait for the delay period
      if (millis() - timeLastTransition >= LED_DELAY)
        state = 0;
      break;
  }
}

Dove possiamo individuare due stati: 0 in cui avviene la transizione, 1 in cui si attende il momento giusto per la transizione Possiamo far evolvere questo codice FSM per renderlo più robusto, leggibile e gestibile.

void blink(bool reset = false)
{
  const uint32_t LED_DELAY = 1000;
  static enum { LED_TOGGLE, WAIT_DELAY } state = LED_TOGGLE;
  static uint32_t timeLastTransition = 0;
 
  if (reset)
  { 
    state = LED_TOGGLE;
    digitalWrite(LED_BUILTIN, LOW);
  }
 
  switch (state)
  {
    case LED_TOGGLE:   // toggle the LED
      digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
      timeLastTransition = millis();
      state = WAIT_DELAY;
      break;
 
    case WAIT_DELAY:   // wait for the delay period
      if (millis() - timeLastTransition >= LED_DELAY)
        state = LED_TOGGLE;
      break;
 
    default:
      state = LED_TOGGLE;
      break
  }
}

Analizziamo le modifiche effettuate:

In realtà la definizione degli stati possiede dei margini di discrezionalità e quelli scelti per realizzare il blink possono infatti sembrare un tantino artificiosi.

Torna all’indice