Macchina a stati finiti e Arduino

luca 30/04/2013 29

Dopo la pubblicazione dei miei sketch, ricevo spesso domande sul perché al loro interno vada a definire degli stati e più in generale su cosa sia una macchina a stati finiti. In questo tutorial, spiegherò come utilizzare tale modello per realizzare un semplice timer.

SimpleTimer

Utilizzeremo Arduino per realizzare un timer giornaliero, con un solo orario di accensione e spegnimento. Collegheremo Arduino ad un RTC (real-time clock) per avere l’ora corrente e ad un relay per controllare una lampadina.

Ho scelto di utilizzare due breakout board, una per l’integrato DS1307 (RTC) e una per il relay, così collegate ad Arduino:

L’integrato DS1307 ha una interfaccia i2c, utilizziamo quindi i PIN A4 (SDA) e A5 (SCL), mentre il modulo relay richiede un solo PIN digitale (nell’esempio il PIN 2).

RTC e Arduino

Per leggere l’orario dal modulo RTC, ho scelto la libreria RTCLib fornita da Adafruit, già usata in un precedente post.

Il suo utilizzo è semplice: per prima cosa dobbiamo includere nello sketch due files:

#include <Wire.h>
#include "RTClib.h"

Quindi definiamo un nuovo oggetto RTC_DS1307:

RTC_DS1307 RTC;

All’interno del setup(), inizializziamo la libreria Wire (i2c) e l’oggetto RTC:

Wire.begin();
RTC.begin();

Per leggere l’orario corrente, è quindi sufficiente chiamare il metodo now(), che restituisce un oggetto DateTime. Questo oggetto ha poi metodi per recuperare le varie parti (giorno, ora, minuto…) di data e ora:

DateTime now = RTC.now();
int hour = now.hour();
[...]

MSF

Una macchina a stati finiti è un modello che descrive il comportamento di un sistema. Il sistema può avere un numero finito di stati e in ogni istante può essere in un solo di essi, lo stato corrente. Il sistema può passare da uno stato all’altro in base ad eventi e/o condizioni: tale passaggio si chiama transizione.

Nel nostro esempio, il sistema potrà avere solo due stati:

  • luce accesa (= relay attivo)
  • luce spenta (= relay disattivo)

Il passaggio da uno stato all’altro dipende dall’orario corrente e dai due orari impostati di accensione e spegnimento. Una MSF si può visivamente definire tramite il suo diagramma degli stati:

All’interno dello sketch, definiamo due costanti che indicano i due diversi stati possibili:

#define STATE_OFF  0
#define STATE_ON   1

e una variabile che memorizzerà lo stato corrente:

int fsm_state;

Nel setup() è importante definire lo stato iniziale:

fsm_state = STATE_OFF;

All’interno del loop(), utilizziamo lo statement Switch per identificare lo stato attuale e verificare se ci sono le condizioni per una transizione di stato:

switch(fsm_state) {
  case STATE_OFF:
    if(now > START_TIME && now < END_TIME) {
        [...]
        fsm_state = STATE_ON;
      }
      break;
    case STATE_ON:
      if(now > END_TIME) {
      [...]
      fsm_state = STATE_OFF;
    }
    break;
}

Funzionamento

Lo sketch completo è disponibile nel mio repository su Github, ecco un paio di foto del progetto funzionante:

29 Comments »

  1. Ronald 01/10/2013 at 01:35 - Reply

    Buongiorno Sig. Luca!
    Sono Ronald, mi trovo alle prime armi con Arduino, non ho problemi con l’hardware, essendo quadrista e anche un po’ di piu (faccio dei circuiti elettronici, è una passione) ma purtroppo come software, non conosco il linguaggio DELLA PROGRAMMAZIONE, volevo controllare dal cellulare (Android) via rete certe 0/1 del quadro di casa…
    volevo sapere da lei, visto la sua notevole conoscenza dell’argomento,
    quale software scaricare sul telefono (anche a pagamento) purche sia
    semplice nel futuro uso e che disponga di almeno 8 o 10 comandi apri/chiudi contatto, quindi molto semplice,
    rinominabili a piacere… e magari se si trovano degli sketch, come comunica android/rete – rete/scheda ethernet di Arduino…
    La ringrazio davvero per l’attenzione e spero di ricevere una risposta!!!
    A presto! GRAZIE MILLE!!!

    • luca 01/10/2013 at 19:46 - Reply

      Ciao Ronald,

      visto che non hai molta esperienza di programmazione, ti consiglio di andare su una soluzione “chiavi in mano”, ad esempio il progetto Arduino Commander ti mette a disposizione una app per Android e il relativo sketch per Arduino, anche con shield Ethernet come serve a te. Buon divertimento!

  2. Beppe 02/10/2013 at 10:02 - Reply

    Buongiorno Luca.
    Ho eseguito il tuo codice, ma non riesco a capire come impostare l’ora del timer, e neanche come faccia il programma a recuperare l’ora esatta, devo impostarla io?

    Ad esempio i minuti corrispondono con l’ora del PC, ma le ore sono otto ore avanti.

    Il problema e mio in quanto neofita, ti ringrazio lo stesso e ti faccio i complimenti per i tuoi tutorial.

    saluti
    Beppe

    • luca 03/10/2013 at 19:10 - Reply

      Ciao Beppe,

      l’ora esatta è mantenuta dal CHIP RTC, che va pre-configurato… ho pronto un piccolo tutorial su come farlo!

  3. Beppe 05/10/2013 at 17:56 - Reply

    Ciao Luca.
    Grazie per aver risposto.
    Ho capito come fare per configurarlo,solo che adesso mi da soltanto ff ff ff come risultato, mi sa che ho cimito l’rtc , non so cosa puo essere successo. Ne prendero un altro e provero di nuovo.
    Grazie
    Saluti Beppe

  4. raffaele 07/11/2013 at 12:27 - Reply

    Buongiorno,
    avrei dei progetti da realizzare con arduino , vorrei chiederle se è disposto a realizzarli o ha un nominativo al quale rivoelgermi

  5. Patrick 15/04/2014 at 22:42 - Reply

    Ciao sto utilizzando questo sketch utilissimo e lo sto riadattando alle mie esigenza ma purtroppo non riesco a configurare orari notturni dopo le 23.59 come vanno scritti? ti ringrazio in anticipo

    • luca 27/04/2014 at 12:37 - Reply

      Ciao Patrick, l’intervallo di funzionanmento se ho capito bene è a cavallo della mezzanotte?

  6. max 01/08/2014 at 07:34 - Reply

    Buongiorno Luca, complimenti per il validissmo aiuto che dai agli sviluppatori.
    Mi accodo alla richiesta di Patrick, rimasta inevasa: se il mio spegnimento è dopo la mezzanotte, come mi devo comportare?
    Stavo cercando qualche via d’uscita, ma per il momento non ho trovato nulla di elegante!

    Max

  7. Aristide 07/03/2015 at 12:17 - Reply

    Ciao Luca ti chiedevo ma riesco collegare ad arduino tre rele’ invece di uno perche volevo far eccitare i tre rele in orari diversi del giorno . Riesci a spiegarmi come posso collegari e poi penso che devo modificare lo sketch che ho scaricato per un solo rele giusto o no ?

    • luca 08/03/2015 at 13:33 - Reply

      ciao, ogni relè si collega ad un diverso PIN di Arduino. Il modo per collegarli è identico… per il resto dovrai immagino gestire 3 diversi orari per i 3 relè nello sketch e modificarlo di conseguenza.

  8. Aristide 09/03/2015 at 16:29 - Reply

    ok grazie mille

  9. Aristide 10/03/2015 at 10:28 - Reply

    Ciao Luca ho montato il progetto come hai fatto tu e cioe macchina stati finiti . Ma nel monitor seriale mi esce la scritta SimpleTimer running …… e basta l orario non ce e il rele’ rimane eccitato . Come mai ho fatto qualche errore da premettere che ho usato lo skecht com e’ senza modifica

    • luca 11/03/2015 at 20:18 - Reply

      ciao! penso ci sia qualche problema su come hai collegato i componenti: lo sketch nel setup fa digitalWrite(RELAY_PIN, LOW); quindi il rele all’inizio deve essere NON eccitato

  10. Aristide 12/03/2015 at 10:38 - Reply

    ok grazie .E per il fatto dell ora come posso fare per regolare un orario tanto per vedere se funziona tipo non so esempio inizio 13.30 fine 13.35 .

    • luca 12/03/2015 at 20:50 - Reply

      modifica lo sketch, in alto ci sono orario di attivazione e di disattivazione del relè

  11. Aristide 12/03/2015 at 21:06 - Reply

    Adesso ci provo . GRAZIE

  12. Mario 24/04/2015 at 15:54 - Reply

    Ciao Luca,

    innanzitutto ti ringrazio per i fantastici articoli scritti fin qui!
    Come gestisci il cambio dell’ora legale/solare?
    Grazie!

    • luca 24/04/2015 at 19:16 - Reply

      Ciao Mario, in questo semplice esempio non lo gestisco. In altri progetti, ho utilizzato ad esempio questa libreria.

  13. Mario 26/04/2015 at 07:44 - Reply

    Grazie Luca,

    prezioso… come sempre :)

  14. Moises Lima 29/04/2015 at 00:19 - Reply

    I am newbie in Arduino and enjoyed this project, as put more of a time for execution.
    may give light.
    hugs and thanks

  15. giovanni 14/08/2015 at 11:04 - Reply

    Ciao, grazie per condividere la Tua conoscenza con tutti noi, in merito a questo progetto avevo la necessità di aggiungere un sensore PIR, nello specifico la mia esigenza nasce per le luci di ingresso e vorrei fare che le stesse si accendessero tipo, dalle 19:00 alle 23:00 e successivamente 23:01 alle 03:00 solo tramite sensore PIR, ho trovato diversi sketch in rete ma nessuno ha entrambe le funzioni, vorrei partire dal tuo progetto, grazie anticipatamente e buon lavoro

    • luca 14/08/2015 at 16:02 - Reply

      Ciao Giovanni, la cosa è abbastanza semplice: se usi un RTC (chip che fa da orologio) puoi scrivere uno sketch che verifica lo stato del sensore PIR, se questo rileva movimento, legge l’ora corrente da RTC e se ricade nel range che ti serve accendi per tot secondi le luci.

      • giovanni 14/08/2015 at 16:31 - Reply

        infatti, sto cercando di scriverlo, ma non riesco a far comunicare il tutto! cmq arduino è bello per quello, ci sbatto la testa finché non va’, pensavo che avessi qualcosa di simile da adattare… Ciao Luca

  16. Linus 21/09/2015 at 09:32 - Reply

    Hi there

    I want to control an 8 channel relay module using an Arduino Uno R3, RTC DS1302 and internet. I would like to ” ON ” & ” OFF ” individual relays at a set time of the day and over the internet.

    • luca 26/09/2015 at 10:24 - Reply

      Hi! looking forward to your sketch ;)

  17. Domenico 24/09/2015 at 17:37 - Reply

    Ciao Luca,

    Ho notato che non hai dato una risposta per la gestione degli orari dopo mezzanotte; presumo che la soluzione — if(now > START_TIME && now START_TIME) — risolvo il problema dell’accensione, ma si spegnerebbe subito perchè now sarà sempre maggiore END nel case STATE_ON:
    La soluzione che a me viene subito è quello di mettere — if(now = START_TIME) — e if(now = END_TIME).
    Ma sono sicuro che tu hai in mente un approccio più efficace.

    Saluti

    • luca 26/09/2015 at 10:29 - Reply

      Ciao Domenico, la cosa più facile è fare un controllo ulteriore verificando a monte se start_time > end_time… in questo caso significa che l’intervallo di ON è a cavallo di mezzanotte e quindi inverti la logica.
      bye

  18. lui 22/03/2016 at 15:25 - Reply

    Salve qualcuno ha già usato la DMBoard? ne ho sentito parlare bene in riferimento alla semplicità per la programmazione proprio in relazione agli stati finiti. cosa ne pensate?
    Sono indeciso se prenderla o orientarmi su arduino. Io di programmazione ne sono poco anzi nulla.
    http://www.dmboard.it

Leave A Response »

Questo sito usa i cookie per poterti offrire una migliore esperienza di navigazione maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi