errore nel loop

scusate, sto cercando di mettere in quadro lo sketch di una centralina antidecubito che mi da ancora qualche problema.
praticamente a me serve che alterni 2 settori di un materasso prima uno e poi l'altro e così via.
nello sketch che ho fatto il gonfiaggio dei 2 settori me lo fa casuale e non capisco il motivo.
le istruzioni non dovrebbero essere eseguite in successione?

void loop(){

lettura_sensori(); //leggo il valore di 2 sensori pressione aria
azionamento_pompa (); //aziono la pompa per il gonfiaggio del materasso

if(vpress==vpeso){//vpress e vpeso sono 2 sensori di pressione aria e da questo punto inizia un semiciclo
delay(2000) ;
digitalWrite(elettrovalvola1,LOW); //apro la valvola 1 e scarico l'aria dal settore 1 del materasso
for(unsigned long stoptime=millis()+60000L;stoptime>millis(); ){//stoppo per un minuto lo sketch con un settore gonfio del materasso e l'altro sgonfio
}}
digitalWrite(elettrovalvola1, HIGH); //apro l'elettrovalvola

lettura_sensori(); //rileggo il valore dei 2 sensori
azionamento_pompa ();//aziono nuovamente la pompa in modo che porti i valori di vpress e vpeso uguali

if(vpress==vpeso){//da questo punto inizia l'altro semiciclo
delay(2000) ;
digitalWrite(elettrovalvola2,LOW); //apro la valvola 1 e scarico l'aria dal settore 2 del materasso
for(unsigned long stoptime=millis()+15000L;stoptime>millis(); ){//stoppo per un minuto lo sketch con un settore gonfio del materasso e l'altro sgonfio
}}

digitalWrite(elettrovalvola2, HIGH);//apro l'elettrovalvola

}

salve, qualcuno mi potrebbe dare qualche dritta su questo problemino?
Arduino esegue il codice ininterrottamente secondo la sequenza definita in void loop(). Giusto?
perche a me con questo loop che ho postato mi gonfia i due settori in maniera casuale e non alternata come serve a me?
grazie

Secondo me il tuo codice è tutto da riscrivere.
Quel ciclo for per calcolare il passaggio del tempo non mi piace proprio.
Ed inoltre i tuoi commenti contraddicono il codice, non si capiscono alcune cose.
Prima scrivi:

digitalWrite(elettrovalvola1,LOW); //apro la valvola 1 e scarico l'aria dal settore 1 del materasso

e poi scrivi:

digitalWrite(elettrovalvola1, HIGH); //apro l'elettrovalvola

Apri o chiudi? Poi leggo:

for(unsigned long stoptime=millis()+15000L;stoptime>millis(); ){//stoppo per un minuto lo sketch

15000 ms sono 15s.

Un'altra cosa:

if(vpress==vpeso)

Se però vpress<>vpeso allora esegue digitalWrite(elettrovalvola1/2, HIGH);, che è fuori dagli if.

scusate per le descrizioni.
la valvola è 3 vie, quando è LOW apro il canale tra out e scarico, quando è HIGH apro tra in e out.
i tempi nell'istruzione FOR non guardarli, li ho accorciati di tantissimo per poter testare velocemente.
Al momento che aziono la pompa, vpress è < a vpeso, per questo si aziona la pompa.
comunque l'istruzione FOR per i ritardi, funziona benissimo, l'unica cosa è che non mi fa questo loop() è una sequenza alternata ma casuale e non capisco il motivo.
tralasciando il resto anche perchè dovrò inserire altre istruzioni in mezzo, come mai non mi fà l'alternato secondo te?

Te l'ho detto, secondo me il codice non è scritto bene.
Se l'if è falso, non esegue il blocco di codice però subito dopo trova la chiusura della valvola. E poi un controllo con "==" non si mette mai perché potrebbe anche capitarti che vpress sia maggiore di vpeso, quindi anche in questo caso l'if viene saltato.

Poi non so come agisce la funzione azionamento_pompa: da il comando di avvio e poi esce oppure cicla finché non si verifica una condizione? Cosa fa, gonfia di continuo le pompe? Vedo che è chiamata 2 volte..
Insomma, è difficile poter ragionare senza sapere cosa fa il resto del programma, come dovrebbero lavorare i meccanismi né la logica che ricerchi tu XD

la funzione pompa agisce così:

void azionamento_pompa (){
if (vpress < vpeso){
digitalWrite(pompa,HIGH);}else {digitalWrite(pompa,LOW);}
}

niente di più semplice, probabilmente il problema stà nel fatto, come hai individuato tu, che potrebbe esserci qualche volta vpress>vpeso e allora crea un malfunzionamento del loop

Forse dovrei spiegare cosa é un materasso antidecubito.

Un decubito é quando la pelle e tessuto sottostante muoiono a causa di un appoggio costante in pazienti che non sono autosufficenti, che hanno una circolazione sanguinia compromessa e coricati a letto come persone anziane o per esempio pazienti in rianimazione. Un decubito non fa male perché, e non ci si accorge di prenderlo.
Il trucco per evitarlo é cambiargli la posizione del paziente in modo che non appoggiano sempre sulla stessa parte del corpo.
Per questo pazienti a rischio vengono riposizionati a letto ogni 2 ore.

Un alternativa sopratutto per anziani o non autosufficienti é il materasso antidecubito. Il materasso antidecubito ha diverse camere d'ária come salsiciotti che vengono gonfiati e sgonfiati ciclicamente per non tenere il peso sempre sulla stessa posizione.

Per persone "sane" non c'é problema, perché quando dormono si muovono abbastanza da non aver questo problema.

Ciao Uwe

Conosco il materasso antidecubito, però volevo solo capire cosa francusallen volesse fare come "sequenza" di azioni antidecubito.
E poi secondo me tutte quelle istruzioni di azionamento pompa fuori dagli if, gli if impostati con un controllo per uguaglianza e basta, ecc... hanno reso lo sketch... capriccioso :wink:
Perché se la pressione passa il peso, l'if non viene eseguito ma la chiusura della valvola sì. All'inizio del ciclo viene riattivata la pompa, che gonfierà anche quella sezione che invece doveva essere sgonfia.

scusate ma quello che chiedo è un piccolo aiuto per far funzionare in questo modo il loop:
1 fase) gonfio i 2 settori fino al valore vpeso
2 fase) sgonfio settore 1 e attendo tempo impostato (es15000)
3 fase) rigonfio settore 1 fino a vpeso
4 fase) sgonfio settore 2 e attendo tempo impostato
5 fase) rigonfio setore 2
e così via all'infinito.
nel mio sketch i due settori me li sgonfia in modo casuale, qualcuno mi sa dire come posso risolvere questo problema??
grazie

Stiamo lavorando per questo :smiley:
Ti ho già detto che hai tanti comandi di azionamento fuori dagli if e secondo me è per questo motivo che ti sgonfia a caso.

Vorrei capire una cosa: ma la pompa sta sempre accesa, una volta azionata?
Dalla tua funzione pare di sì perché la accendi con un semplice if.

Quindi deduco che la pompa tiene in pressione il materassino, e solo l'apertura/chiusura delle valvole comanda lo sgonfiamento/gonfiamento dei 2 settori.

ciao, no la pompa appena vpress è = a vpeso si spegne. il comando è
if (vpress < vpeso){
digitalWrite(pompa,HIGH);}else {digitalWrite(pompa,LOW);}.
ho provato inserire anche
digitalWrite(elettrovalvola1, HIGH); //apro l'elettrovalvola
all'interno dell'IF ma è la stessa cosa.

Allora mi pareva di aver capito....

Scusa, non ti offendere, però se il tuo sketch è tutto quello che ci hai postato, allora secondo me è normale che non funzioni perché non ha una logica di funzionamento.

Nella funzione accendi_pompa tu controlli solo se la pressione è inferiore al peso nel qual caso accendi o spengi. In realtà però l'if non è un ciclo per cui quel controllo il micro lo esegue solo una volta e poi esce: non sta ad aspettare che la pressione raggiunta sia quella corretta. Poi si infila in tutta una serie di controlli if nel restante codice che alla fine porta a vedere il materassino gonfiato a caso.

Poi tu continui a pubblicare lo sketch solo ai pezzetti... E l'intestazione dello sketch dov'è? Dove sono dichiarate la variabili che mancano? Cosa fa setup? Come leggi i sensori? Boh... Non ci è dato di sapere... XD

Prendendo per buono quel poco che c'è, faccio un piccolo sketch buttato lì così, non so se funzionerà meglio o peggio del tuo.

/*
DICHIARAZIONE
VARIABILI
*/

void setup(){}

/*
lettura_sensori(){}
*/

void azionamento_pompa (){

    lettura_sensori();
    if (vpress < vpeso) {
        digitalWrite(pompa, HIGH); //immagino tu gonfi i materassini con HIGH;
        do {
            lettura_sensori();
        } while (vpress < vpeso);
        digitalWrite(pompa,LOW); //spengo
    }
}

void loop(){

    azionamento_pompa();
    digitalWrite(elettrovalvola1,LOW); //apro la valvola 1 e scarico l'aria dal settore 1 del materasso
    delay(60000L); //attendo 1 minuto
    digitalWrite(elettrovalvola1, HIGH); //chiudo l'elettrovalvola

    azionamento_pompa ();
    digitalWrite(elettrovalvola2,LOW); //apro la valvola 1 e scarico l'aria dal settore 2 del materasso
    delay(60000L);
    digitalWrite(elettrovalvola2, HIGH);//chiudo l'elettrovalvola

}

stasera proverò, comunque lo sketch l'ho già pubblicato 2 volte intero .
so che sarà pieno di errori ma sto studiando da poco l'arduino e mi ero stufato di far accendere un led per ore e ore. questo è lo sketch:

// includo la library del display
#include <LiquidCrystal.h>
#define pompa 13
#define elettrovalvola1 10
#define elettrovalvola2 9
#define allarme 8

// inizializzo la library con il numero dei pin di interfaccia
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// Variabile array contenente i messaggi da stampare per le varie voci di menù
char* menu[]={"attendere gonfiaggio", "da 40 a 60kg", "da 60 a 80kg", "da 80 a 100kg", "da 100 a 120kg",};
// Costante valore sensore sensore peso
const int sensore_peso = 2;
// costante valore sensore press
const int sensore_press = 1;
// Variabile contenente il valore letto dal pressostato della lettura del peso in ingresso
int vpeso=0;
// Variabile contenente il valore letto dal pressostato della lettura del peso di uscita
int vpress=0;

void setup(){

// imposto il numero di righe e colonne del display LCD
lcd.begin(16, 2);
// Stampo a display una riga di credits
lcd.setCursor(0, 0);
lcd.clear();
lcd.print(" centralina");
lcd.setCursor(4, 1);
lcd.print("Antidecubito");
delay(2000);
lcd.clear();
lcd.print("peso paziente");
delay(2000);
pinMode(pompa, OUTPUT);
pinMode(elettrovalvola1, OUTPUT); //elettrovalvola settore materasso1
pinMode(elettrovalvola2, OUTPUT);//elettrovalvola settore materasso2
pinMode(allarme, OUTPUT);//allarme buco
digitalWrite(elettrovalvola1, HIGH); //aziono l'elettrovalvola 1
digitalWrite(elettrovalvola2,HIGH);//aziono l'elettrovalvola 2

}

void azionamento_pompa (){
if (vpress < vpeso){
digitalWrite(pompa,HIGH);}else {digitalWrite(pompa,LOW);}
}

void loop(){

lettura_sensori();
azionamento_pompa ();

if(vpress==vpeso){
delay(2000) ;
digitalWrite(elettrovalvola1,LOW); //apro la valvola 1 e scarico l'aria dal settore 1 del materasso
for(unsigned long stoptime=millis()+15000L;stoptime>millis(); ){
}
digitalWrite(elettrovalvola1, HIGH);}

lettura_sensori();
azionamento_pompa ();

if(vpress==vpeso){
delay(2000) ;
digitalWrite(elettrovalvola2,LOW); //apro la valvola 1 e scarico l'aria dal settore 2 del materasso
for(unsigned long stoptime=millis()+15000L;stoptime>millis(); ){
}

digitalWrite(elettrovalvola2, HIGH);}

}

void lettura_sensori(){
// Leggo il valore del sensore peso
vpeso=map(analogRead(sensore_peso), 300, 1023, 1, 5); // valore da 1 a 6 del peso del paziente
lcd.setCursor(0, 1);
lcd.print(menu[vpeso-1]);
delay(400);
// Leggo il valore del sensore press
vpress = map(analogRead(sensore_press), 300,1023,1,5); // valore da 1 a 6 della pressione del materasso
}

adesso magari ti è più chiaro ma errori c'è ne sono tanti penso.
ciao

In pratica cosa fa lo sketch?
All'avvio, ovvero appena acceso il sistema, leggendo i sensori l'Arduino si accorgerà che non c'è pressione per cui gionfierà il materassino (ricordati di controllare che le elettrovalvole siano chiuse, non so se sono del tipo normalmente chiuse o aperte: prendo per buono che in assenza di un segnale di tensione stiano chiuse).
Durante l'azionamento della pompa il ciclo do-while controlla periodicamente i sensori, spengendo la pompa non appena abbiamo ottenuto che vpress >= peso.

A questo punto inizia un semplice loop in cui, alternativamente:

  • apre 1 elettrovalvola, fa passare 1 minuto (durante il quale l'elettrovalvola fa svuotare la sezione corrispondente);
  • chiude l'elettrovalvola
  • rigonfia tutto
  • apre la 2a elettrovalvola, ecc....

2 volte per intero? ma dove? XD XD XD XD XD

Cmq controlla un po' quello che ho postato io ed integralo con le parti che non avevi pubblicato e che non conoscevo.

grazie Leo, non ho capito molto bene la tua funzione azionamento_pompa() però funziona.
sei grande

A differenza della tua, che uscivi dalla funzione non appena avviate le pompe, la mia aspetta che la pressione abbia raggiunto il valore giusto.
Te la commento:

void azionamento_pompa (){

    lettura_sensori();  //leggo i sensori per avere i valori iniziali
    if (vpress < vpeso) { //la pressione è inferiore al peso del paziente?? Sì, allora entro nella sezione sottostante
        digitalWrite(pompa, HIGH); //immagino tu gonfi i materassini con HIGH; //attivo la pompa
        do { //ciclo!
            lettura_sensori(); //leggo i sensori per sapere a che punto sono
        } while (vpress < vpeso); //La pressione ha bilanciato il peso del paziente?? Se no, torno all'inizio del ciclo
        digitalWrite(pompa,LOW); //ho ottenuto la pressione giusta, spengo tutto
    }
}

mi piacerebbe avere ancora un suggerimento.
potrei in questa funzione" void azionamento_pompa ()" che mi ha suggerito leo72, far partire un timer che quando la pompa si aziona, e se rimane allo stato HIGH per più di 15 min, suona l'allarme? Praticamente sta ad indicare che vpress non raggiunge mai vpeso perchè il materasso ha una perdita.

Trasformi la funzione così:

byte azionamento_pompa (){
unsigned long allarme;
byte codice;

codice = 0;
lettura_sensori(); //leggo i sensori per avere i valori iniziali
if (vpress < vpeso) { //la pressione è inferiore al peso del paziente?? Sì, allora entro nella sezione sottostante
digitalWrite(pompa, HIGH); //immagino tu gonfi i materassini con HIGH; //attivo la pompa
allarme = millis()+50000L; //5 minuti di tempo max: sono più che sufficienti
do { //ciclo!
lettura_sensori(); //leggo i sensori per sapere a che punto sono
if (millis() > allarme) {
codice = 1; //allarme
break;
}
} while (vpress < vpeso); //La pressione ha bilanciato il peso del paziente?? Se no, torno all'inizio del ciclo
digitalWrite(pompa,LOW); //ho ottenuto la pressione giusta, spengo tutto
return codice;
}
}

Poi basta che invece di chiamare la funzione con:

azionamento_pompa();

tu faccia:

byte codice;

    codice = azionamento_pompa();
    if (codice == 1) {
        ALLARME
    }

La funzione restituisce "0" se tutto va bene e termina il suo compito correttamente.
Se invece funziona per più di 5 minuti, restituisce "1", quindi una condizione di allarme.
Il codice in azionamento_pompa spenge le pompe in entrambe le situazioni, prima di uscire dalla funzione.

grazie leo
questa sera mi impegnerò al massimo per studiare questa nuova funzione