lampeggiare un led al verificarsi di un evento.

Salve tutti, colgo occasione di augurare Buona Pasqua.

Mi chiamo Lorenzo, sono alle prime esperienze di programmazione con arduino quindi abbiate pazienza, questo è il mio secondo proggetto e vi spiego cosa vorrei fare.
Vorrei realizzare un misuratore di livello carburante per il serbatoio della barca; però invece di utilizzare il solito galleggiante con resistenza variabile annessa io vorrei usare due sensori di pressione.
Il primo sensore legge la pressione idrostatica del carburante ed il secondo legge la pressione dentro il serbatoio il cui valore sarà sattratto al valore di pressione letto dal primo sensore e determinare così il livello finale del carburante.
Lo sketch che ho generato, che per il momento utilizza due potenziometri, sembra funzionare correttamente sul simulatore Proteus 8.9.

Quello che nn riesco ad associare è far lampeggiare un led al raggiungimento della riserva ma solo a farlo accendere impostato sul pin12. Usare il semplice digitalWrite HIGH e poi Low non risolve perché occorre attendere il termine del calcolo della media nel loop e questo impiega un certo tempo abbastanza lungo e il led lampeggia solo al temine del calcolo della media per un solo lampeggio e cio si ripete ad ogni ciclo
mentre a me serve che il led lampeggi sempre quando il carburante entra in riserva anche al ripetersi del loop successivo.
Ciò che va tenuto presente è che
Ho cercato e letto vari esempi di lampeggio del led tipo questo:

 /* Blink without Delay
  http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/


const int ledPin =  13;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
   pinMode(ledPin, OUTPUT);     
}

void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
     previousMillis = currentMillis; 
   if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

però non riesco ad associarlo alla condizione "if "che a me interessa visibile nel secondo sketch:

//questo vuole essere un tentativo di determinre il livello del carburante
//nel serbatoio della barca utilizzando due sensori di pressione da 30psi pari a 2bar
// descrizione il sensore Pr1 misura la pressione che esercita il liquido,
// il sensore P2 invece misura la pressione all'interno del serbatoio e sarà il riferimento.
// l'idea è di misurare la pressione del liquido ogni 15 sec e fornire una media delle letture
// ogni 5 min. 

int Pr1 = (A0);  // sensore pressione 1 
int Pr2 = (A1);  // sensore pressione 2 
int Array[20];  //  carica valori nell array
int T_campionamento = 500;   // verificato il funzionamento pertare al valore 15000
int somma;   // somma valori dell'array
float media;  // calcola la media dei valori memorizzati nell'array


void setup(){
    Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);  // attiverà led riserva carburante, potrei usare un timer con ne555
  
            }

void loop(){
  
for (int i=0; i<20; i++){
    Array[i] = analogRead(A0) - analogRead(A1);
    Serial.print("Array[i]    ");
     Serial.println( Array[i]); 
    delay(T_campionamento); //
                          }
 
  somma = 0; // il primo valore sia zero altrimenti sballa tutto il calcolo
                      // finito di acquisire, fai la somma di tutti i campioni
  for(int i=0; i<20; i++) {
   somma = somma + Array[i];
   Serial.print("somma    ");
     Serial.println( somma);
                           }
  //ottenuta la somma puoi fare la media
  media = somma / 20;
  Serial.print("media=     ");
Serial.println( media);              // Stampa il valore medio
  
    //il loop finisce e di seguito ricomincia
  //per questo è mecessario azzerare di volta in volta la variabile somma

somma =0;
  
 if ( media > 0 && media <= 102 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    digitalWrite(12, HIGH);
  }

  // accensione della barra led
  else if ( media > 102 && media <= 203 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
   digitalWrite(12, HIGH);
  }

  //  accensione della barra led
  else if ( media > 204 && media <= 305 )  // al verificarsi di questa condizione la variabile "media"
                                                               // minore del valore 305 il led deve lampeggiare 
                                                                //continuamente  
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    digitalWrite(12, HIGH);
  
 }


  // accensione della barra led
  else if ( media > 306 && media <= 407 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    digitalWrite(12, LOW);
  }

  // accensione della barra led
  else if ( media > 408 && media <= 509 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
    digitalWrite(12, LOW);
  }

  // accensione della barra led
  else if ( media > 510 && media <= 611 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
  }

  // accensione della barra led
  else if ( media > 612 && media <= 713 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
  }

  // accensione della barra led
  else if ( media > 714 && media <= 815 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, LOW);
    digitalWrite(11, LOW);
  }

  // accensione della barra led
  else if ( media > 816 && media <= 919 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(11, LOW);
  }

  // accensione della barra led
  else if ( media > 920 && media <= 1023 )
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(11, HIGH);
  }
  
  Serial.println("nuova sequenza");
}

allego uno screenshoot del test con simulatore,

Grazie a tutti, e Buona Pasqua.

Esattamente come detto qui occorre strutturare in modo diverso la logica. Nel seguente disegno a sinistra il tuo for di acquisizione che monopolizza tutto il tempo. A destra la stessa procedura realizzata tramite due if che se non sono veri proseguono subito (e se sono veri durano comunque pochissimo).

Il calcolo del tempo trascorso si effettua esattamente come per l'esempio blink senza delay.

Per quanto riguarda il lampeggio sotto una certa media si potrebbe usare una logica come questa:

Come si vede sono tutti if che se non veri vanno giù dritti come un fuso, in questo modo il loop si ripete migliaia di volte al secondo senza ritardi.

Scusami se porto il discorso leggermente OT, ma mi interessa, non tanto per la misurazione carburante, per la quale preferisco la strumentazione di bordo precisa ed affidabile, quanto per la misurazione livello serbatoio acqua dolce per il quale io sto invece sperimentando (appeno posso rimetterci i piedi sopra) un misuratore a ultrasuoni. In pratica a me interessa solo conoscere tre livelli o meglio intervalli (vuoto - medio - pieno) cui assocerò tre segnali acustici con misurazione a scafo fermo (vista l'inutilità della misurazione in movimento). Il circuito misura. Tu come intento realizzare il tuo circuito?...un sensore immerso ed uno esterno per la barometrica? Lo vedo però un pò complicato per i calcoli e le compensazioni dovute a tipo di liquido (diversità di pressione) e le altre variabili ambientali che, per quanto ne sappia ma non ho approfondito, possono portare ad errori significativi e trattandosi di carburante in barca è bene andare sul sicuro. Infatti la famosa colonnina trasparente accanto ai serbatoio è la misurazione che preferisco.
Grazie

Ciao Claudio_FF, grazie per il suggerimento, ci studiero sopra al diagramma di flusso.

Vince 59, la mia idea è di usare u tubicino di alluminio chiuso sul fondo e immerso nel carburante poi un piccolo foro da 1mm permette al carburante di entrare neltubicino e quindi portarsi allo stesso livello del carburante nel serbatoio, la pressione esercitata dal carb. nel tubicino sarà misurata dal sensore 1. Il secondo sensore misurera invece la pressione che si crea all'interno del serbatoio.
Il piccolo foro dovrebbe smorzare le grandi oscillazioni del carburante durante la navigazione.
La mia idea è prorio quella di evitare di portare cavi elettrici per misurare il livello di carburante come avviene con i galleggianti dei serbatoi delle autovetture o come aviene nei serbatoi delle moto con dei NTC.
Se devi misurare il livello nel serbatiio dell'acqua allora è sufficente usare tre elettrodi di inox che a contatto con l'acqua conducono corrente.
Per le tue esigenze elimina ciò che riguarda il 2ndo sensore dallo sketch ed adattarlo all'uso dell'ultrasuono.

In ogni caso la colonnina trasparente rimane sempra una validissima soluzione.

Questo proggetto è per me un esercizio di programmazione poichè sono alle prime esperienze con arduino.
Ovviamente il tutto è ancora da sperimentare e i valori da adattare alla reale situazione.

Però sono contento che abbia suscitato dell'interesse.

Ciao a tutti e Buona Pasqua.

Salve A tutti, rieccomi qui dopo tanto studiare sono arrivato allo sketch qui sotto. Ho trovato il modo di far lampeggiare il led quando il valore della media raggiunge il valore desiderato prendendo spunto da un esempio di un Youtuber (il Sig. Paolo Olivieri) questo il suo link
Usare un sensore di pressione con Arduino e filtro a media mobile - Video 331 - YouTube.

Ora mi rendo conto di quanto era semplice l'uso del blink led senza delay.

Ringrazio x 1000 volte tutti coloro che mi hanno dato suggerimenti.

Però ce una cosa ancora da aggiustare:
Le veloci letture/acquisizioni del valore del sensore comporteranno rapidi variazioni nell'indicatore a led rendendo molto instabile la visualizzazione.
Quindi mi pongo la domanda di come rendere piu stabile la visualizzazione sulla barra led oppure come rallentare le letture del sensore?
Una prima ipotesi lo gia sperimentata inserendo un delay ma questo rallenta il lampeggio del led a seconda del valore delay inserito.
Come risolvere questo inghippo?

Se volete ancora darmi un piccolo aiuto vi sarò grato.

questo lo sketch:

//questo vuole essere un tentativo di determinre il livello del carburante
//nel serbatoio della barca utilizzando due sensori di pressione da 30psi pari a 2bar
// descrizione il sensore Pr1 misura la pressione che esercita il liquido,
// il sensore Pr2 invece misura la pressione all'interno del serbatoio e sarà il riferimento.
// l'idea è di misurare la pressione del liquido ogni 15 sec e fornire una media delle letture
// ogni 5 min. Il valore della media finale sarà dato dal calcolo media Pr1 - media Pr2

int Pr1 = (A0);  // sensore pressione 1 
int Pr2 = (A1);  // sensore pressione 2 
const int ledPin = 12;
int ledState = LOW;
unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 500;           // interval at which to blink (milliseconds)


void setup(){
  Serial.begin(9600);
   DDRD=0b11111110;
   DDRB=0b00011111;
}
int const fsize = 50;
int fil[fsize];  //imposta filtro buffer
int i=0;
float avg=0;


void loop(){
   int Pr1 = analogRead(A0) - analogRead(A1);
   fil[i]= Pr1;
  if (i < (fsize-1)) i++;
  else i = 0;
  avg=0;
  for (int j=0; j< fsize; j++) {
    avg+=(float)fil[j];
  }
  avg = avg / (float)(fsize);
  
  unsigned long currentMillis = millis();
  if ( avg  <= 310  ){
 if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState); // set the LED with the ledState of the variable:
    }
 }
   Serial.print(Pr1);
  Serial.print("  ");    
  Serial.print(avg);
  delay(100);
 
if ( avg > 0 && avg <= 102 ) {
    PORTD=0b00000100;
   // PORTB=0b00010000;
   }
  // accensione della barra led2+riserva
  else if ( avg > 103 && avg <= 203 )
  {
    PORTD=0b00001100;
  //  PORTB=0b00010000;
  }
  //  accensione della barra led3+riserva
  else if ( avg > 204 && avg <= 305 )
  {
    PORTD=0b00011100;
  //  PORTB=0b00010000;
   }
  // accensione della barra led4 spegna riserva
  else if ( avg > 306 && avg <= 407 )
  {
    PORTD=0b00111100;
    PORTB=0b00000000;
   }
  // accensione della barra led5 no riserva
  else if ( avg > 408 && avg <= 509 )
  {
    PORTD=0b01111100;
    PORTB=0b00000000;
  }
  // accensione della barra led6 
  else if ( avg > 510 && avg <= 611 )
  {
    PORTD=0b11111100;
    PORTB=0b00000000;
   }
  // accensione della barra led
  else if ( avg > 612 && avg <= 713 )
  {
    PORTD=0b11111100;
    PORTB=0b00000001;
  }
  // accensione della barra led
  else if ( avg > 714 && avg <= 815 )
  {
    PORTD=0b11111100;
    PORTB=0b00000011;
 }
  // accensione della barra led
  else if ( avg > 816 && avg <= 919 )
  {
    PORTD=0b11111100;
    PORTB=0b00000111;
 }
  // accensione della barra led
  else if ( avg > 920 && avg <= 1023 )
  { 
    PORTD=0b11111100;
    PORTB=0b00001111;
   }
 Serial.println("nuova sequenza");  
}

Nello stesso modo del LED, temporizzi anche le altre operazioni con millis (PS: per il LED mi sembra manchi lo spegnimento quando sopra soglia)

La media per il filtro NON funziona se i campioni vengono presi tutti in rapida successione... bisognerebbe campionare una volta al secondo così da avere la media degli ultimi 50 secondi (e magari partire all'inizio con un campionamento ogni 0,1 secondi in modo da popolare l'array in 5 secondi).

Per la media non serve l'aritmetica float, 50 letture da massimo 1023 ci stanno anche in una unsigned int.

Le Serial.print ad ogni giro di loop intasano il buffer di trasmissione rallentando l'esecuzione.

Indentailcodiceconcontrol+taltrimentileggereiltuoprogrammaècomeleggerequestotesto.

Ciao Claudio_FF,
grazie della risposte e dei suggerimenti,
Vero le serial print posso toglierle, le ho tenute solo per capire quali valori di media venivano misurati.
Al simulatore il led smette di lampeggiare se la media supera il valore impostato.

Altro test che ho fatto è aumentare il nr di letture da 50 a 200 ed oservando (al simulatore ) le oscillazioni della barra led, i segmenti led si spengono o accendono dopo 10 sec al variare del sensore, che per il momento è un potenziometro.

Effettivamente mi sono posto anche io la domanda di come rallentare il campionamento in modo da riempire l'arry in un certo tempo (diciamo in15sec.).

Grazie del suggerimento studiero ancora durante il prossimo mese mentre sarò impegnato ad effettuare rilevamenti geomarini.

Ciao buona serata

Salve a Tutti,
Dopo svariati giorni ed in attesa che il brutto tempo passi rieccomi qui a dirvi che studiando e rielaborando lo sketch sono riuscito a far lampeggiare il Led, anzi 3 led, quando il livello del carburante scende al di sotto di un certo livello (Riserva).
Per ora il funzionamento mi va bene così, verificherò meglio quando avrò realizzato il circuito.

grazie a tutti

Qui di seguito lo sketch:

int Pr1 = (A0);  // sensore pressione 1 
int Pr2 = (A1);  // sensore pressione 2 
const int ledPin2 = 2;
const int ledPin3 = 3;
const int ledPin4 = 4;
int ledState = LOW;
unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 500;           // interval at which to blink (milliseconds)


void setup(){
  Serial.begin(9600);
   DDRD=0b11111110;
   DDRB=0b00011111;
}
int const fsize = 250;   //aumentando il nr letture si stabilizza la visualizzazione sul display.
int fil[fsize];  //imposta filtro buffer
int i=0;
float avg=0;


void loop(){
   int Pr1 = analogRead(A0) - analogRead(A1);
Serial.println(Pr1);
Serial.println("  ");
Serial.println(Pr2);
   
   fil[i]= Pr1;
  if (i < (fsize-1)) i++;
  else i = 0;
  avg=0;
  for (int j=0; j< fsize; j++) {
    avg+=(float)fil[j];
  }
  avg = avg / (float)(fsize);
  
  unsigned long currentMillis = millis();
  if ( avg  <= 310  ){
 if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin2, ledState); //lampeggio led pin 2
    digitalWrite(ledPin3, ledState);//lampeggio led pin 3
    digitalWrite(ledPin4, ledState);// lampeggio led pin 4
    }
 }
   Serial.print(Pr1);
  Serial.print("  ");    
  Serial.print(avg);
  delay(100);
 
if ( avg > 0 && avg <= 102 ) {
    PORTD=0b00000100;
   // PORTB=0b00010000;
   }
  // accensione della barra led2+riserva
  else if ( avg > 103 && avg <= 203 )
  {
    PORTD=0b00001100;
  //  PORTB=0b00010000;
  }
  //  accensione della barra led3+riserva
  else if ( avg > 204 && avg <= 305 )
  {
    PORTD=0b00011100;
  //  PORTB=0b00010000;
   }
  // accensione della barra led4 spegna riserva
  else if ( avg > 306 && avg <= 407 )
  {
    PORTD=0b00111100;
    PORTB=0b00000000;
   }
  // accensione della barra led5 no riserva
  else if ( avg > 408 && avg <= 509 )
  {
    PORTD=0b01111100;
    PORTB=0b00000000;
  }
  // accensione della barra led6 
  else if ( avg > 510 && avg <= 611 )
  {
    PORTD=0b11111100;
    PORTB=0b00000000;
   }
  // accensione della barra led
  else if ( avg > 612 && avg <= 713 )
  {
    PORTD=0b11111100;
    PORTB=0b00000001;
  }
  // accensione della barra led
  else if ( avg > 714 && avg <= 815 )
  {
    PORTD=0b11111100;
    PORTB=0b00000011;
 }
  // accensione della barra led
  else if ( avg > 816 && avg <= 919 )
  {
    PORTD=0b11111100;
    PORTB=0b00000111;
 }
  // accensione della barra led
  else if ( avg > 920 && avg <= 1023 )
  { 
    PORTD=0b11111100;
    PORTB=0b00001111;
   }
 Serial.println("nuova sequenza");  
}

sensore carburante.JPG