Go Down

Topic: Sensore di pressione analogico (Read 1 time) previous topic - next topic

Ziostep

Nov 26, 2018, 11:03 am Last Edit: Nov 27, 2018, 08:32 pm by Ziostep
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. :)  :)
Grazie in anticipo.

torn24

#1
Nov 26, 2018, 11:49 am Last Edit: Nov 26, 2018, 11:50 am by torn24
Nel tuo programma non c'è nessuna lettura analogica! Guarda bene la variabile dello switch() non è stato :)


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".


Code: [Select]


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

}


Ziostep

#2
Nov 26, 2018, 04:25 pm Last Edit: Nov 26, 2018, 04:39 pm by Ziostep
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

torn24

#3
Nov 27, 2018, 08:35 am Last Edit: Nov 27, 2018, 08:50 am by torn24
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.



Ziostep

#4
Nov 27, 2018, 10:54 am Last Edit: Nov 27, 2018, 08:32 pm by Ziostep
Ciao, ti allego lo sketch così mi dici se ho capito.

Mancano da dichiarare Pmax e Pmin.

Grazie

torn24

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

Ziostep

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


Grazie

Ziostep

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.

torn24

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!
Code: [Select]



/* 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;                       
  }
   
}
 






Ziostep

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 :(  :(

Grazie ancora.

torn24

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.


Claudio_FF

#11
Nov 27, 2018, 01:19 pm Last Edit: Nov 27, 2018, 01:22 pm by Claudio_FF
Quote from: 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.
* * * * Una domanda ben posta è già mezza risposta * * * *

torn24

Quote
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 :)

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...

Claudio_FF

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.
* * * * Una domanda ben posta è già mezza risposta * * * *

Ziostep

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.

Go Up