Sensore di pressione analogico

Buongiorno,
Sto riscontrando problemi nel capire come tarare e quindi scrivere il codice in Arduino per leggere la pressione dal sensore avente uscita analogica.

Vi allego le caratteristiche del sensore, il datasheet, così da poter capire bene di cosa parliamo.

'https://docs-emea.rs-online.com/webdocs/1384/0900766b81384463.pdf' per il datasheet.

Sensore di pressione Relativa MPX5700GP, pressione massima 700kPa :
-Range di pressione 0-700 Kpa,
-Tensione di alimentazione 4,75-5,25 V c.c.
-Uscita analogica 4,75 V
-Tipo uscita Analogica.

In breve queste sono le caratteristiche del sensore che devo aggiungere allo sketch già creato.

In sostanza il sensore deve leggere la pressione all'interno del manicotto, confrontarla con un valore prestabilito. Se è più grande deve fermare l'insufflazione dell'aria, annotare la pressione, il tempo e passare allo stato successivo.
Altrimenti deve continuare a gonfiare fin quando non raggiunge il valore, quindi passare allo stato successivo.
Diciamo che la logica è questa e deve essere ripetuta negli stati che richiedono la lettura dal sensore.

In ogni caso vi allego lo sketch cosi che possiate capire meglio di cosa si tratti.
E' il mio primo progetto con Arduino, siate clementi. :slight_smile: :slight_smile:
Grazie in anticipo.

Nel tuo programma non c'è nessuna lettura analogica! Guarda bene la variabile dello switch() non è stato :slight_smile:

Se il sensore da valori proporzionali, zero =zero pascal, 1023 all'incirca 700000 pascal. Usando la funzione map() dovresti ottenere il valore APPROSSIMATO di pressione "approssimato perché il valore massimo del sensore non è 5 Volt ma 4,75".

long pressione=0;
int lettura=0;
void loop(){
  
     lettura=analogRead(A0);
     pressione=map(lettura,0,1023,0,700000);
     

}

Scusa spiegati meglio perché non ti seguo.
Cosa significa non leggo la pressione nello switch???

Inoltre, non deve essere dichiarato nel Setup() tramite pinMode() come INPUT il sensore, per poter leggere nel loop() il valore all'interno del manicotto??

Se è sbagliato il codice scritto cosi, mi puoi far vedere come devo scrivere la condizione dell'if che mi faccia leggere tramite sensore la pressione??

case GONFIAGGIO:
if(analogRead(AnalogInPin) >= Pmax) {
digitalWrite(INTELVALEPIN, LOW); //fermo
digitalWrite(PUMPPIN, LOW);
digitalWrite(EXHAUSTVALVEPIN, LOW);
digitalWrite(LED, LOW);
ValoreSensore = analogRead (AnalogInPin);

Dall'esempio che hai fornito non capisco come inserirlo nel codice.

Inoltre, avendo 2 elettrovalvole che hanno range da 0-350mmhg, il valore massimo del sensore in lettura deve essere 46662.7 Pascal e non 700000 Pascal. Come posso inserire questo range per avere il valore approssimato su 46662.7 Pascal e non sul limite del sensore?

Grazie

Tu nello switch usi la variabile che non esiste, state è diverso da stato !

Se fai delle letture analogiche non devi usare pinMode() perché si usa solo per pin digitali.

Presumo che il sensore dia valori proporzionali, al doppio di pressione restituisce il doppio del voltaggio,
almeno presumo.

L'esempio è abbastanza chiaro, sul pin analogico leggerai valori da 0 a 1023, che corrispondono a valori di pressioni da 0 a 700000 Pascal, con la funzione map, come ti ho mostrato, da valori 0-1023 ottieni valori da 0-700000. Poi se vuoi convertire i Pascal in bar il calcolo è semplice sapendo a quanti pascal corrisponde un bar.

Ciao, ti allego lo sketch così mi dici se ho capito.

Mancano da dichiarare Pmax e Pmin.

Grazie

Tu nei vari if() leggi il pin analogico, ma questo non ti da direttamente un valore di pressione. Per avere la pressione devi usare la funzione map() come da esempio.

Io lavorerei in modo diverso! Ad esempio per lo stato GONFIAGGIO

  1. Entro nel case, prima cosa leggo il pin analogico e ricavo la pressione tramite funzione map()
  2. Pongo una condizione tramite if-else Se la pressione è minore gonfio, else spengo

Ok, adesso sto seguendo il tuo discorso.
E' più chiaro ed effettivamente molto utile il tuo consiglio.

Grazie

Allora ho cambiato senza problemi due stati seguendo il tuo consiglio.

Riscontro problemi nello stato PAUSA e RABBOCCA.
Puoi darmi ulteriori consigli?

Ti allego lo sketch, grazie.

sketch_Prova.ino (4.29 KB)

Ti ho modificato un po il codice! Ma non funziona correttamente

Tu dovresti sostituire i vari if-else if, con altri stati con altri case.
Usa una macchina a stati finiti con quanti stati sono necessari, non usare else if, ma aggiungi altri stati
altri case nello switch();

Gli else if() dovrebbero essere sostituiti con altri case, stati di una macchina a stati finiti!

/* Arduino test  iniziale */

#define RIPOSO               0
#define GONFIAGGIO           1
#define PAUSA                2
#define RABBOCCA             3
#define SGONFIAGGIO          4
#define ATTENDI_NO_COMANDO   5
byte stato = RIPOSO;                          // stato che memorizza il case eseguito
#define SWITCHPIN 2
#define INTELVALVEPIN 6
#define PUMPPIN 5
#define EXHAUSTVALVEPIN 7
#define LED 13

long pressione = 0;
int lettura = 0;
unsigned long tempo=0;
                             
void setup() {
  Serial.begin(9600);
  pinMode(SWITCHPIN, INPUT);
  pinMode(INTELVALVEPIN, OUTPUT);  
  pinMode(PUMPPIN, OUTPUT);
  pinMode(EXHAUSTVALVEPIN, OUTPUT);
  pinMode(LED,OUTPUT);
   
}

void loop() {
  switch(stato) 
  {
    case RIPOSO:
          if (digitalRead(SWITCHPIN) == HIGH) {
              digitalWrite(INTELVALVEPIN, HIGH);        
              digitalWrite(PUMPPIN, HIGH);
              digitalWrite(EXHAUSTVALVEPIN, LOW);
              digitalWrite(LED, HIGH);             
              stato = GONFIAGGIO;                          // stato che memorizza il case eseguito
              }
           break;
     
     case GONFIAGGIO:
           
            lettura = analogRead (A0);
            pressione = map (lettura,0,1023,0,700000); 
            
            if(pressione >= 300){
                digitalWrite(INTELVALEPIN, LOW);              //fermo
                digitalWrite(PUMPPIN, LOW);
                digitalWrite(EXHAUSTVALVEPIN, LOW);
                digitalWrite(LED, LOW);
                Serial.print(pressione);
                //annotare tempo da scrivere
                stato = PAUSA; 
                tempo=millis(); // Inizio il conteggio tempo di pausa				
            }else if(pressione <= Pmax){
            
            Serial.print(pressione);
            digitalWrite(INTELVALVEPIN, HIGH);               //altrimenti se pressione bassa -> avvia gonfiaggio -> RABBOCCA
            digitalWrite(PUMPPIN; HIGH); 
            digitalWrite(EXHAUSTVALVEPIN, LOW);
            digitalWrite(LED, HIGH);
            stato = RABBOCCA;
			tempo=millis();// tempo per il rabbocco
            }
            break;
            
     case PAUSA:
	      lettura = analogRead(A0);
          pressione = map (lettura,0,1023,0,700000);
          if(millis()-tempo>=5000) {   // Al posto di 5000 5 secondi mettere il tempo voluto   
            digitalWrite(INTELVALVEPIN, LOW);            
            digitalWrite(PUMPPIN, LOW);                  
            digitalWrite(EXHAUSTVALVEPIN, HIGH);         
            digitalWrite(LED, LOW);                      
            stato = SGONFIAGGIO;
            }
           
            break;
            
     case RABBOCCA:
          if(millis()-tempo>=5000) {                        //se trascorsi N secondi -> avvia sgonfiaggio -> SGONFIAGGIO
             digitalWrite(INTELVALVEPIN, LOW);        
             digitalWrite(PUMPPIN, LOW);
             digitalWrite(EXHAUSTVALVEPIN, HIGH);
             digitalWrite(LED, LOW);
             stato = SGONFIAGGIO;                              
             }
           else if(analogRead(A0) >= Pmax){                    //altrimenti se pressione massima -> ferma gonfiaggio -> PAUSA
              digitalWrite(INTELVALVEPIN, LOW);       
              digitalWrite(PUMPIN, LOW);
              digitalWrite(EXHAUSTVALVEPIN, LOW);
              digitalWrite(LED, LOW);
              lettura = analogRead(A0);
              pressione = map (lettura,0,1023,0,700000);
              Serial.print(pressione);
              stato = PAUSA;
			  tempo=millis();
             }
             break;
            
     case SGONFIAGGIO:
           lettura = analogRead(A0);
           pressione = map (lettura,0,1023,0,700000)
           if(pressione == 0){
              digitalWrite(INTELVALVEPIN, LOW);       
              digitalWrite(PUMPPIN, LOW);
              digitalWrite(EXHAUSTVALVEPIN, LOW);    
              digitalWrite(LED, LOW); 
              Serial.print(pressione);                                    
              stato = ATTENDI_NO_COMANDO;                     
           }
            break;

     case ATTENDI_NO_COMANDO:                                   //se comando disattivo -> IN_ATTESA
            if (digitalRead(SWITCHPIN) != HIGH) stato = RIPOSO; 
            break;                       
  }
    
}

Grazie per il codice, sei stato davvero gentile.

Come mai l'if-else if dici che non funzionano??
Io non ho ancora testato il tutto quindi non ho la certezza del funzionamento :frowning: :frowning:

Grazie ancora.

Non funziona la logica!
Io passo a un case "uno stato della macchina a stati finiti" per eseguire una cosa, se mi trovo ad eseguire
"else if()" cambio stato per cui non posso fare più la prima cosa!
Esempio il primo if() deve attendere un intervallo di tempo per eseguire qualcosa, se viene eseguito l'else if
cambio stato, per cui dopo trascorso l'intervallo di tempo non succede niente.

Si risolve con più stati, io ho tanti case ognuno per ogni azione diversa che devo eseguire.

torn24:
Io passo a un case "uno stato della macchina a stati finiti" per eseguire una cosa, se mi trovo ad eseguire "else if()" cambio stato per cui non posso fare più la prima cosa!
Esempio il primo if() deve attendere un intervallo di tempo per eseguire qualcosa, se viene eseguito l'else if
cambio stato, per cui dopo trascorso l'intervallo di tempo non succede niente. Si risolve con più stati, io ho tanti case ognuno per ogni azione diversa che devo eseguire.

Più o meno. In uno stato si possono aspettare più eventi. Se questi richiedono un cambio di stato (e quasi sempre è così) allora la loro gestione deve anche essere mutuamente esclusiva (else if). Se sono veri tutti ha la priorità il primo testato.

Per il discorso dell'intervallo di tempo, nella logica è previsto di iniziare a misurarlo quando viene raggiunta la pressione massima, e di controllarlo sia nello stato 'pausa' che 'rabbocca', per cui non ci si perde mai il timeout (chiaro che se la logica viene alterata con modifiche più o meno a tentativi si sballa tutto).

Poi come già detto in precedenza, la pressione tanto vale leggerla una sola volta prima dello switch. In effetti c'è anche molto altro codice duplicato che potrebbe essere compattato in singole funzioncine, ma qui dipende anche se zio vuole usare delle funzioni o scrivere tutto assieme nel loop.

allora la loro gestione deve anche essere mutuamente esclusiva

Dal nome delle costanti usate e poi quello che effettivamente fa il programma, non ho capito bene l'algoritmo :slight_smile:

Io userei un algoritmo del genere

  1. La pressione è bassa vado allo stato GONFIAGGIO
    2)Nello stato gonfiaggio leggo di continuo la pressione , se non raggiunge il massimo continuo altrimenti
    passo allo stato sucessivo.

Comunque, ripeto, non mi è chiaro l'algoritmo...

L'algoritmo (ricavato dalla descrizione di Zio) è quello descritto qui, eventualmente già scritto completamente in C sotto forma di richiamo di tante piccole funzioni qui.

Ok sono andato in confusione...per un momento ho pensato che era da buttare lo sketch.

Appurato da Claudio che mi stavo sbagliando, procediamo per gradi.

Sono disposto a far tutte le semplificazioni del caso se spiegate.
Essendo al primo progetto con Arduino non so districarmi nel linguaggio C in quanto visto per la prima volta (sto cercando di apprendere il più possibile dal libro di testo, ma ovviamente non è facile).

E' vero che la logica di programmazione è la stessa per tutti i linguaggi ma rispetto a python la sintassi è completamente differente.

Confido nei vostri consigli, grazie.

Ziostep:
E' vero che la logica di programmazione è la stessa per tutti i linguaggi ma rispetto a python la sintassi è completamente differente.

Quindi in Python lo sapresti scrivere?
Perché la sintassi non mi sembra poi così diversa.
Se sai scrivere e usare una funzione con sintassi Python:

def avvia_gonfiaggio():
    digitalWrite(INTELVALVEPIN, HIGH)
    digitalWrite(PUMPPIN, HIGH)
    digitalWrite(EXHAUSTVALVEPIN, LOW)
    digitalWrite(LED, HIGH)

allora non dovrebbe essere così impossibile scrivere la versione C:

void avvia_gonfiaggio(){
    digitalWrite(INTELVALVEPIN, HIGH);
    digitalWrite(PUMPPIN, HIGH);
    digitalWrite(EXHAUSTVALVEPIN, LOW);
    digitalWrite(LED, HIGH);
}

O ancora:

def comando_attivo():  return digitalRead(SWITCHPIN) == HIGH

che diventa:

bool comando_attivo(){ return digitalRead(SWITCHPIN) == HIGH; }

Non ho mai usato Arduino, sensori di tipo analogico o altri componenti elettronici.
Ecco perché trovo alcune difficoltà nel progetto.

Ho fatto un paio di progetti con Raspberry pi 3, utilizzando Python, ma sempre di bassa difficoltà.
La mia conoscenza è ristretta, in quanto non studio informatica, quindi ho conoscenze scolastiche del linguaggio Python.

Non voglio cambiare il codice scritto perché fa esattamente quello che a me serve.
Non voglio cambiare gli stati perchè avvengono nella successione corretta.

La mia unica problematica resta l'inserimento del sensore negli stati già creati.

Detto questo, non capisco come posso eliminare le ripetizioni e come posso rendere più efficiente l'algoritmo.

La lettura del sensore analogico l'ha scritta torn24 (anche se senza calibrazione con uno strumento campione e senza un riferimento preciso e stabile credo che l'errore supererà il 5%).

La sequenza degli stati l'ho scritta io.

Il controllo del tempo suggerito in questo post alla fine l'ha scritto torn24.

Un esempio di funzione contenente alcune istruzioni ripetute in più punti l'ho scritto proprio nel post precedente a questo.

Si è detto più volte che la pressione potrebbe essere vantaggiosamente letta una sola volta prima dello switch/case, così da averla disponibile in chiaro in ogni case, ma va bene anche prima di ogni punto in cui serve usare il suo valore... e invece posti (di nuovo) una cosa come:

case GONFIAGGIO:
           if(analogRead(A0)) {                                         //leggo dal sensore
            lettura = analogRead (A0);
            pressione = map (lettura,0,1023,0,700000);      //ottengo la pressione
            }
            else if(pressione >= 300){                                  //la confronto con il valore di mio interesse
            digitalWrite(INTELVALEPIN, LOW);                       //fermo il gonfiaggio
            digitalWrite(PUMPPIN, LOW);
            digitalWrite(EXHAUSTVALVEPIN, LOW);
            digitalWrite(LED, LOW);
            Serial.print(pressione);                                     //stampo a video il valore di pressione
                                                                                  //devo annotare il tempo a cui avviene la lettura
            stato = PAUSA;                                                                                 
            }
            break;

che non ha alcun senso logico neppure se scritta con sintassi Python (anche i commenti non sono del tutto coerenti):

elif stato == GONFIAGGIO:
    if analogRead(A0):                               ##leggo dal sensore
        lettura = analogRead(A0)
        pressione = map(lettura, 0, 1023, 0, 700000) ##ottengo la pressione

    elif pressione >= 300:                           ##la confronto con il valore di mio interesse
        digitalWrite(INTELVALEPIN, LOW)              ##fermo il gonfiaggio
        digitalWrite(PUMPPIN, LOW)
        digitalWrite(EXHAUSTVALVEPIN, LOW)
        digitalWrite(LED, LOW)
        Serial.print(pressione)                      ##stampo a video il valore di pressione
                                                     ##devo annotare il tempo a cui avviene la lettura
        stato = PAUSA

Ora, io ho solo un diploma di maturità, attualmente faccio il magazziniere, ai miei tempi non esisteva proprio che qualcuno pensasse al posto mio risolvendomi magicamente ogni dettaglio. Se qualcosa non era chiaro lo rileggevo una settimana, provavo a metterlo in pratica, lo rileggevo due settimane, provavo a metterlo in pratica, lo rileggevo un mese, due mesi, soppesando ogni parola, cercando di capire cosa poteva voler dire di diverso da quello che credevo inizialmente, e cercando anche di capire se sbagliavo io o se era sbagliata la spiegazione (qualche volta capitava, oggi in rete capita molto di più). Quindi mi domando, manca qualcosa nelle nostre spiegazioni (che non sia lo scrivere tutto il codice già bello e pronto)?

DISCLAIMER: questa naturalmente vuole essere una critica costruttiva espressamente rivolta a un laureando in ingegneria informatica/biomedica. Se stessi parlando al ragazzino di terza media che fa qualche esperimento, o all'hobbysta della domenica privo di qualsiasi background tecnico, le cose potrebbero essere un pochino diverse, ma non troppo, perché lo scopo di questo forum non è quello di fare agratis i lavori agli altri :wink:

Non era il mio scopo avere cose finite ma ti ringrazio ugualmente per la critica formativa.

Vi ringrazio tutti per la pazienza e per i consigli dispensati fin ora.