Programmazione a stati finiti con arduino

Con questo articolo si chiude il ciclo di articoletti riguardanti la programmazione di Arduino. Davide, non dire che batto la fiacca :-) Questa volta ho trattato la programmazione a stati finiti che permette di dividere grossi sketch in sotto programmi. Spero che l'articoletto possa essere interessante ed utile a più persone... Arduino e programmare a stati finiti.

Scusa se faccio degli appunti, non ho testato lo sketch pero' cosi' leggendolo mi pare un po' ridondante.. inoltre secondo me ha una minore richiesta computazionale, laddove usabile, l'utilizzo della struttura case-switch http://www.arduino.cc/en/Reference/SwitchCase F

Assolutamente corretto. Mannaggia mi hai battutto sul tempo. Con questo articolo concludo il ciclo dei "suggerimenti" in modo che se arriva qualcuno che chiede del millis() o del multitasking o di semplificare il codice lo posso rimandare a questi articoli senza riscrivere tutto ogni volta. A tendere (ma a questo punto con calma) voglio fare un articoletto dove parlo proprio delle ottimizzazioni di codice con case. In questo tipo di sketch però il case non penso si potesse usare perchè al programma è richiesto una lettura continua, un altrettanto continuo movimento dei motori ed una altrettanta continua scrittura su seriale. Il SwitchCase si inserisce (da come la vedo io) quando c'è una logica nel loop principale cosa che, come ho scritto alla fine dell'articolo, in questo caso non esiste. Cosa ne pensi? Mi farebbe piacere un parere esterno. E per il resto ti è piaciuto l'articolo? L'hai trovato chiaro?

Poi ad aprile facciamo gli oscar di arduino per chi ha contribuito di più alla comunità italiana.

ora estorco qualche prototipo a smart projects e li mettiamo in palio.

:)

si è vero, l'ide di arduino offre la comodità delle schede ma io preferisco scrivere dele librerie esterne ed includerle... ma questa è solo uanquestione di gusti :)

per il resto: perchè "programmazione a stati finiti?" in realtà con gli automi a stati finiti il tuo articolo non centra niente o quasi... io l'avrei chiamato "programmazione - approccio top down"br

cmq bravo :) ciao

come scrivi le librerie? grazie

questo potrbbe esserti di aiuto

http://www.arduino.cc/en/Hacking/LibraryTutorial

@nathanvi Per quello che riguarda il case non ho scritto "io sostituirei con" proprio perche' avevo sospettato che il codice richiedesse una variazione continua. Magari lo aggiungerei nell'articolo, perche' laddove hai magari una selezione da parte dell'utente che puo' scegliere O 1 O 2 O 3 l'utilizzo di "if" e' superfluo.

Sistemerei ad esempio questa parte qui

/* Muove i SERVI*/

void muoviServoMotori(){
if(time>servotime1+15){ 
   posservo1= analogRead(letturaluce1);
   posservo1=map(posservo1,0,1023,0,179);
   servo1.write(posservo1);
   servotime1=millis();
}

if(time>servotime2+15){ 
   posservo2= analogRead(letturaluce2);
   posservo2=map(posservo2,0,1023,0,179);
   servo2.write(posservo2);
   servotime2=millis();
}
}

Dove se supponiano che la variazione di un millis() con l'altro sia tendente a 0 poteva essere fatta una chiamata sola al posto di due, che ne pensi?

L'articolo mi e' piaciuto e mi pare chiaro. Anche io da un po' utilizzo i tab, ma ci ho messo del tempo per arrivarci, mentre vorrei imparare a scrivere librerie ma le mie skill programmative sono ancora un po' schifose.

Si, quello che scrivi è giusto :-) Son contento che sia piaciuto anche a te. Per quanto riguarda la scrittura delle librerie vorrei farlo anche io solo che non faccio così tanti progetti da spenderci del tempo :-( Soprattutto son tutti progetti differenti e quindi...

Anche a me capita poco il riutilizzo ma sai com'e', e' anche una questione di STILE 8-)

ah ah ah, sei un grande!! Potresti parlarne al prossimo dorkbot di milano...

vivo a milano e non sono mai stato al dorkbot... sono una mezza sega :)

Ottimo grazie mille, ora stampo il tutto (perchè non riesco a leggere dal monitor, non mi soddisfa :P) e cerco di capire come cavolo si usi il mills :)

Massimo: puoi estorcere a smartprj anche la possibilità di rispondere alle mail e confermare gli ordini? Un mese mi sebra sufficiente, occhei che magari ce l'ha un po' su con me, però c'è qualcosa che non quadra e non voglio comprare all'estero un prodotto da loro creato e esportato... :(

aggiuntina

Nella sezione dove parli dei tabs, hai scritto "Scrivi su Outout" :)

ciao,
complimenti anche per questo articolo, soprattutto per la chiarezza che hai nell’esporre gli argomenti! :wink:

L’articolo secondo me per chi vuole imparare è molto istruttivo, però anch’io come programmazione a stati finiti intendevo un’altra cosa, per esempio con tre soli blocchi:

//nel Setup

 k = 0   //inizializzazione k

//nel Loop

if(k == 0){
     blocco_0(); //quando finisce di fare quello che deve fare incrementa k 
     k = k+1;
     }

if(k == 1){
     blocco_1(); //con le sue istruzioni, alla fine incremento k per cambiare passo
     k = k+1;
     }

if (k == 2){
    blocco_2();//è l'ultimo blocco da eseguire quindi alla sua fine devo resettare k per ripartire
k = 0;
    }

Questo pseudocodice in linea di massima è l’idea di come intendo io una macchina a stati finiti (in realtà anzichè usare “k” intero, farei economia di memoria usando più variabili booleane, una per ogni stato).

L’ho chiamata idea perchè non esce da nessun libro e non è una critica, consideralo un feedback e se vi va discutiamone, voglio imparare! :wink:

Ciao Fede, assolutamente d'accordo. Personalmente quello che intendo io per macchina a stati finiti rispecchia la tua idea. Tuttavia, come detto nel articolo, non essendoci "logica" all'interno dello sketch gli if mi sembravano ridondanti. Il realtà lo sviluppo che ne faccio io, a livello di codice è proprio come il tuo e a questo punto anticipo il prossimo articolo. Prima di tutto si vedono i componenti/eventi. Facciamo caso: due bottoni ed un menù su display LCD.

  • Normalmente sono in modalità "normal" (magari visualizza ora o temperatura).
  • Se premo bottone 1 vado al menù
  • Se premo bottone 2 senza essere nel menù mi dice "lascia perdere"
  • Se premo bottone 2 e sono in menù avanza nei menù....

A quel punto costruisco una tavola della verità:

Modo---------Bottone1------Bottone2-----Menu
Normale------OFF------------OFF----------OFF
MenuStart----ON-------------ON-----------OFF
MenuChange--OFF------------ON-----------ON
EsciMenu-----ON-------------ON-----------ON

Ovviamente ognuno se la costruisce a seconda dei suoi gusti e di che dinamica vuole dare al programma. Qui si presuppone che per entrare nel menù si preme bottone 1 e per uscirne si premano entrambi i bottoni... A quel punto nel loop sviluppo la tavola della verità e ciò diventa una cosa del genere:

//Determino lo stato nel quale sono
//Pesante a livello di calcolo per i vari if ma necessario
//Tuttavia esegue tre if a ciclo
if(bott1==TRUE){
  if(bott2==TRUE){
    if(menu==TRUE){
      esciMenu(); //va nella funzione e fa qualcosa.
    }
    else{
      lcd.print("Devi essere nel menù per fare sta cosa...")
    }
   else{
      ......
   }
  }
}

A questo punto ecco la macchina a stati finiti. Lo switch case può essere un metodo alternativo di sviluppare il discorso ma personalmente penso che un microcontrollore (tieni conto che potrei sbagliarmi dato che non ho grande esperienza in merito) non si "affatichi" con tanti IF dato che... in fondo... fa poi solo quello ;)

ahah!!! Anch'io ho cominciato a sbattere la testa sulla programmazione a stati finiti proprio per fare un menu sul display!!!!!!!!!! ;D

Poi ieri ho usato gli IF nell'esempio, perchè stavo pensando al tuo...però uno switch case forse è anche più intuitivo (come "costo computazionale" non ne ho idea).

Con i compilatori moderni non dovrebbero esserci problemi di "costo computazionale" ci pensano loro ad ottimizzare ma di sicuro e' molto piu intuitivo per chi legge il codice ( magari ci devi tornare sopra tra 6 mesi e non ti ricordi piu il giro degli if, mentre lo switch case e' piu leggibile)