Pilotare elettrovalvole Arduino

ciao ti consiglio di cambiare nome a IDLE, perchè come vedi si colora di blu da solo, ciò vuol dire che è un qualcosa di già utilizzato all'interno del core di Arduino.

Lascio la parola ai più esperti, però nel dubbio io cambierei il nome :slight_smile:

MD

Ah, vero, c'è sempre il rischio di scrivere qualche nome già predefinito.
Si potrebbe cambiare in ONIDLE.
A parte un ; svista il resto è tutto corretto.

Grazie ragazzi,

ulteriore dubbio.

Nel passare dallo stato ONILDE --> INFLATE (INFLATE-->PAUSE ECC) non so scrivere il codice in quanto non riesco a capire bene come funzioni Switch/case in arduino... :cold_sweat: :cold_sweat:

Scusate ma sto facendo il massimo per capire il linguaggio nel più breve tempo possibile.
Grazie ancora.

P.s.: ho caricato lo sketch dove ho provato ad implementare lo stato WAIT_NO_COMMAND, non sono sicuro di aver fatto bene.

sketch_Prova.ino (2.63 KB)

Ziostep:
non riesco a capire bene come funzioni Switch/case in arduino

Come il codice del post #16

ho provato ad implementare lo stato WAIT_NO_COMMAND, non sono sicuro di aver fatto bene

Il caso WAIT_NO_COMMAND serve solo ad attendere che l'interruttore sia portato nello stato non attivo se per caso non lo è già.

   case WAIT_NO_COMMAND:
            if (digitalRead(SWITCHPIN) == LOW) state = ONIDLE;
            break;

IL commento "stato che memorizza il case eseguito" sarebbe più corretto: "variabile che memorizza lo stato corrente", di fatto lo stato corrente corrisponde al case eseguito.

Se durante la pausa serve anche mantenere la pressione tramite "rabbocchi" allora bisogna aggiungere uno stato REFILL, e si potrà andare avanti e indietro diverse volte tra i due stati PAUSA e REFILL a seconda del valore letto della pressione.

Con la logica ci sei quasi, in ogni case un if corrisponde a un evento che si vuole gestire, e il contenuto dell'if alle azioni in risposta all'evento. Lo stop sgonfiaggio va dentro il caso DEFLATE, non dentro il WAIT_NO_COMMAND.

    case DEFLATE:
        if(raggiunta la pressione minima nel manicotto) { // <----EVENTO
            digitalWrite(INTELVALVEPIN, LOW);             // <----AZIONI
            digitalWrite(PUMPPIN, LOW);
            digitalWrite(EXAUSTVALVEPIN, LOW);
            digitalWrite(LED, LOW);
            state = WAIT_NO_COMMAND;
            }
         break;

Non serve (anzi non si deve) usare delay da nessuna parte, altrimenti l'esecuzione dei casi si blocca.

Grazie Claudio,
adesso il codice inizia ad essere più chiaro.
Inizio, finalmente, a comprendere anche la logica dello switch/case.

Continuo e cerco di inserire anche il codice per il sensore di pressione.
Grazie per il momento.

P.s.: Nel DEFLATE
digitalwrite(EXHASTVALVEPIN, HIGH); e non LOW altrimenti l'aria non esce e si blocca a quella pressione il tutto.

sketch_Prova.ino (2.83 KB)

Ziostep:
P.s.: Nel DEFLATE
digitalwrite(EXHASTVALVEPIN, HIGH); e non LOW altrimenti l'aria non esce e si blocca a quella pressione il tutto.

Nel DEFLATE le azioni vengono eseguite a sgonfiaggio già terminato (evento pressione zero).
L'avvio dello sgonfiaggio avviene quando nel PAUSE si rileva l'evento timeout.

Quindi devo seguire questa logica??

sketch_Prova.ino (3.09 KB)

La logica è esattamente come la si descriverebbe in italiano:

Quando sono in attesa (ONIDLE)
    se comando attivo -> avvia gonfiaggio -> INFLATE
    
Quando sto gonfiando (INFLATE)
    se pressione massima -> ferma gonfiaggio e
                            annota tempo attuale -> PAUSE

Quando sono in pausa (PAUSE)
    se trascorsi N secondi -> avvia sgonfiaggio -> DEFLATE
    altrimenti se pressione bassa -> avvia gonfiaggio -> REFILL

Quando sto rabboccando (REFILL)
    se trascorsi N secondi -> avvia sgonfiaggio -> DEFLATE
    altrimenti se pressione massima -> ferma gonfiaggio -> PAUSE

Quando sto sgonfiando (DEFLATE)
    se pressione minima -> ferma sgonfiaggio -> WAIT_NO_COMMAND

Quando sto attendendo nessun comando (WAIT_NO_COMMAND)
    se comando disattivo -> ONIDLE

Poi questa è una logica di partenza, su un sistema reale io vorrei poter interrompere il processo in qualsiasi momento, e far fronte ai guasti della sonda pressione (ad esempio aggiungendo dei timeout). Ma queste modifiche sono solo altre semplici righe descrittive da aggiungere ai "quando" (gli stati/situazioni), o altre situazioni, ad esempio uno stato ERROR.

Ovviamente devo aggiungere il sensore di pressione collegandolo al pin analogico.
Saranno modifiche che dovrò apportare in quanto deve funzionare in real-time il sistema e deve poter essere adattato alle situazioni.

Comunque grazie Claudio, essendo alle prime armi con Arduino devo prendere un po la mano.

Ciao Claudio,
seguendo la tua guida sto scrivendo così lo sketch ( in allegato).
Riscontro un bel problema sul come inserire il codice per il sensore e quindi mettere la condizione nello stato dell'if facente riferimento sempre al sensore.

Hai ulteriori direttive in merito? :sweat_smile:

sketch_Prova.ino (3.66 KB)

Usando nel programma parole italiane come attesa, gonfia, sgonfia, pausa non si correrebbe il rischio di creare conflitti con parole "proibite". Un francese non si sognerebbe nemmeno di scrivere parole in inglese! :slight_smile:

Ciao DATMAN,
grazie per la direttiva, ma sembra che non ci siano parole proibite all'interno del codice...
Ma ho sostituito gli stati in italiano e anche il resto.

Allora si può scrivere proprio tutto in italiano, così la logica è perfettamente leggibile:

switch(stato) 
{
    case RIPOSO:
        if (comando_attivo()) {
            avvia_gonfiaggio();
            stato = GONFIAGGIO;
            }
        break;

    case GONFIAGGIO:
        if(pressione_massima()) {
            fermo();
            annota_tempo();
            stato = PAUSA;
            }
        break;

    case PAUSA:
        if(trascorsi(10000)) {
            avvia_sgonfiaggio();
            stato = SGONFIAGGIO;
            }
        else if(pressione_bassa()){
            avvia_gonfiaggio();
            stato = RABBOCCA;
            }
        break;

    case RABBOCCA:
        if(trascorsi(10000)) {
            avvia_sgonfiaggio();
            stato = SGONFIAGGIO;
            }
        else if(pressione_massima()){
            fermo();
            stato = PAUSA;
            }
        break;

    case SGONFIAGGIO:
        if(pressione_minima()) {
            fermo();
            stato = ATTENDI_NO_COMANDO;
            }
        break;

    case ATTENDI_NO_COMANDO:
        if (!comando_attivo()) stato = RIPOSO; 
        break;                       
}

Dopo di che restano da scrivere le brevi funzioncine che vengono richiamate (per quasi tutte credo basti una sola riga).

Sto facendo bene così???

sketch_Prova.ino (3.77 KB)

Devi mettere le condizioni pressione bassa, pressione massima, ...

Si lo so DATMAN,
volevo sapere se il resto era tutto corretto.

Inoltre, non avendo acquistato ancora il sensore il codice lo posso scrivere oppure devo tenere a mente casi particolari??

Ovviamente ho il datasheet del sensore che voglio usare, quindi so la Vcc,Vout e il range di pressioni in mmhg di utilizzo.

Grazie

Che cos'è:

sensorValue = analogRead (AnalogInPin);   //annota pressione attuale

??

Da leggersi come:

quando sto gonfiando
    se pressione massima
        spegni valvole
        annota pressione attuale
        passa a pausa

Scusa Claudio non mi sono spiegato bene,
nello sketch è stato definito lo switch/case con i vari stati, fin qui tutto perfetto.

Devo dichiarare il sensore di pressione all'interno del codice ( non è stato ancora acquistato, mi serve un consiglio sull'acquisto). Vorrei acquistare un sensore con un buon range di misura, spendendo poco se possibile, tenendo a mente che le elettrovalvole hanno range di 0-350 mmhg.

Ti allego il link di quello che vorrei prendere ' Sensore di pressione Relativa MPX5700GP, pressione massima 700kPa '. Volutamente voglio prendere un sensore con un range maggiore dell' elettrovalvole oggi utilizzate per poter fare un UPGRADE futuro cambiando solo le elettrovalvole.

Negli STATI devo leggere la pressione presente all'interno del manicotto, tramite lettura del sensore di pressione, e passare da uno stato all'altro in funzione della pressione letta.

Se la pressione nello STATO è nel RangeMax allora si ferma il gonfiaggio, il RangeMax deve essere mantenuto per tot secondi e la pressione deve essere stampata sul computer.

Adesso posso passare allo STATO successivo.

Stavo cercando di scrivere proprio questo, pensavo che con " sensorValue = analogRead (AnalogInPin);" andavo a leggere il valore del sensore.

Spero di aver chiarito le idee :confused: :confused:

Ziostep:
Stavo cercando di scrivere proprio questo, pensavo che con " sensorValue = analogRead (AnalogInPin);" andavo a leggere il valore del sensore.

Si, la lettura è giusta, quello che chiedevo era il significato di metterla quel punto li, cioè in un punto dove significa: "quando è stata rilevata la pressione massima allora annoto la pressione". Mi domandavo se quella "annotazione" (ben diversa da quella che ho scritto io nelle spiegazioni precedenti) avesse uno scopo in previsione di qualcosa da implementare.

Per il resto la pressione basta leggerla prima dello switch (saranno da fare delle calibrazioni per far corrispondere le scale).

Se ho capito bene quello che vuoi dire è:

case GONFIAGGIO:
if(analogRead (AnalogInPin)>=Pmax) { // leggo la pressione e la confronto con il valore
digitalWrite(INTELVALEPIN, LOW); //smetto di gonfiare
digitalWrite(PUMPPIN, LOW);
stato = PAUSA; //passo allo stato successivo
}
break;

Ovviamente io vorrei sapere se la pressione è di 302/310/306, vorrei stamparla a video sul computer ma non so scrivere il codice, inoltre, la lettura della pressione non ho capito se va fatta in PAUSA.
Non so se sia giusto quello che ho scritto sopra.

grazie Claudio