Accensione 3 led + fotoresistenza

Salve a tutti , mi sono appena inoltrato in questo mondo di arduino , e ho deciso di cominciare con piccoli programmini e capirne le basi.
Ho un problema con questo semplice circuitino dove ci sono 1 fotoresistenza e 3 led , uno verde , uno giallo e uno rosso disposti a semaforo.
Il programma dovrebbe far si che superato il range prefissato di intensità luminosa il primo led verde si deve accendere , al trascorrere di un tot di tempo , se il valore continua ad essere superiore si dovrebbe accendere anche quello giallo e cosi via fino a quello rosso. una volta che i valori ritornano dentro il range i 3 led dovrebbero spegnersi.
Il programma che ho scritto funziona , ma non come vorrei , il tempo di risposta è lungo , e non essendo esperto in arduino non so come scrivere il programma in maniera da far funzionare il circuito correttamente. Vi chiedo quindi un gentil aiuto da parte vostra , ascolterò volentieri tutti i vostri consigli purechè siano costruttivi e mi aiutino ad ampliare le mie conoscenze su questo mondo a me nuovo. Grazie in anticipo , di seguito vi allego le 2 righe di code che ho scritto.

#define InputAnalogico A0

const int leduno = 11; 
const int ledue = 10;
const int ledtre = 9;


int Valorepericolo = 255;


void setup()
{
  pinMode(leduno, OUTPUT);
 pinMode(ledue, OUTPUT);
 pinMode(ledtre, OUTPUT);
 Serial.begin(9600); // Inizializzo la comunicazione a 9600
}

void loop()
{
 int ValoreSensore = analogRead(InputAnalogico); // Inserisco il valore della lettura dell'input analogico sull'intero ValoreSensore
 Serial.println(ValoreSensore, DEC); // Scrivo sullo schermo il valore del sensore in numeri decimali

if(ValoreSensore > Valorepericolo) {
  
  digitalWrite(leduno, HIGH);
  
   
}else{ 
  
  digitalWrite(leduno, LOW);
  digitalWrite(ledue, LOW);
  digitalWrite(ledtre, LOW);
  
}

delay(1000);

if(ValoreSensore > Valorepericolo) {
  
    digitalWrite(ledue, HIGH);
  
   }

   
delay(1000);

if(ValoreSensore > Valorepericolo) { 
          
     digitalWrite(ledtre, HIGH);
     
   }
   
    
}

I delay fermano l'esecuzione del codice per cui se il tuo programma sembra rispondere con "lentezza" forse è perché per accendere ogni led l'Arduino deve aspettare il tempo che hai impostato.

Ti consiglio di dare un'occhiata all'esempio BlinkWithoutDelay per capire come usare millis() per sostituire il delay.

Grazie del suggerimento , ora provo subito. E' possibile magari sostituire il delay anche con dei cicli for che incrementino una variabile fino a tot?

In teoria sì ma non è funzionale né preciso perché dovresti andare per tentativi per trovare un for che attenda il tempo che vuoi. Cmq poi se punto e a capo, perché avresti sempre il micro bloccato nel loop.

Ecco un esempio, non so se funziona perche non lo ho provato, però dovrebbe dare l'idea... se non capite qulacosa chiedete pure

int tempo = 1000; //indica il numero di volte che il ciclo viene ripetuto
const int leduno = 11; 
const int ledue = 10;
const int ledtre = 9;
int A;

#define InputAnalogico A0
int Valorepericolo = 255;

void loop ()
{
   pinMode(leduno, OUTPUT);
 pinMode(ledue, OUTPUT);
 pinMode(ledtre, OUTPUT);
 Serial.begin(9600); // Inizializzo la comunicazione a 9600
}

void setup()
{
 while(true)
 {
  int ValoreSensore = analogRead(InputAnalogico); // Inserisco il valore della lettura dell'input analogico sull'intero ValoreSensore
  Serial.println(ValoreSensore, DEC); // Scrivo sullo schermo il valore del sensore in numeri decimali
  while(ValoreSensore > Valorepericolo)
    {
    int ValoreSensore = analogRead(InputAnalogico);
    digitalWrite(leduno, HIGH);
     if(A > tempo)
     {
     digitalWrite(ledue, HIGH);
     }
     if(A > (2*tempo))
     {
      digitalWrite(ledtre, HIGH);
     }
     delay(1);
     A=A+1; //incrementa il numero a per ogni cilco di uno.1 ciclo dura 0,001 sec
            //il valore tempo = 1000, quindi 0,001 * 1000 =circa 1 sec
    }
  digitalWrite(leduno, LOW);
  digitalWrite(ledue, LOW);
  digitalWrite(ledtre, LOW);
  delay(10);
 }
}

L'ho provato non funziona , comunque posso farti un paio di domande ? non ho capito la variabile A , che valore assume?

Il tuo programma fa quello che chiedi nel primo post, la lentezza è data dai 2 delay aspetta sempre 2 secondi che ci sia o meno la condizione.

Se vuoi piu velocità nella lettura della luce quando è al di sotto dei 255 metti i delay dentro gli if, sarà più lento solo quando gli if saranno veri.

ciao

Dovrebbe essere quello che chiedi, ho usato la funzione Millis(), ho letto un po’ di post e fatto diverse prove, ma il millis non riesco a resettarlo per non andare in overflow.
Puoi semplificarlo magari usando il case a me interessava provare il millis che non avevo mai usato

Ho separarto i timer di passaggio da 1 a 2 a 3 con “long timer1 = 5000;” e “long timer2 = 5000;”
Riducendo int delay_lettura = 1000; aumenterai la velocità di aggiornamento della luce, ma gli step di passaggio da 1 a 2 a 3 saranno sempre di 5 secondi ovviamente se timer 1 e 2 restano a 5000

ciao

#define InputAnalogico A0

const int leduno = 11; 
const int ledue = 10;
const int ledtre = 9;

//const int leduno = 46; 
//const int ledue = 47;
//const int ledtre = 48;

unsigned long previousMillis = 0;
long timer1 = 5000;
long timer2 = 5000;
//long timer3 = 2000;
int delay_lettura = 1000;
int Valorepericolo = 255;
int st=1; 

void setup()
{
 pinMode(leduno, OUTPUT);
 pinMode(ledue, OUTPUT);
 pinMode(ledtre, OUTPUT);
 Serial.begin(9600); // Inizializzo la comunicazione a 9600
}

void loop()
{
 int ValoreSensore = analogRead(InputAnalogico); // Inserisco il valore della lettura dell'input analogico sull'intero ValoreSensore
 unsigned long currentMillis = millis();
 
   if((ValoreSensore >= Valorepericolo) && (st==1)) 
   {
       previousMillis = currentMillis;
       st=2; 
   }
    
        if((ValoreSensore >= Valorepericolo) && (st==2)) 
        {
          //previousMillis = currentMillis; 
          digitalWrite(leduno, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm VERDE " + String ((currentMillis- previousMillis)/1000) + " Secondi " );
         
              if(currentMillis - previousMillis >= timer1) 
              {
                st=3 ;
                Serial.println("*** Fine ciclo led 1 e inizio ciclo led 2 ***");
                previousMillis =  currentMillis;
              }
        }  

        if((ValoreSensore >= Valorepericolo) && (st==3)) 
        {
          digitalWrite(ledue, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm GIALLO " + String ((currentMillis- previousMillis)/1000) + " Secondi ");
              if(currentMillis - previousMillis >= timer2)
              {
                st=4 ;
                Serial.println("*** Fine ciclo led 2 e inizio ciclo led 3 infinito ***");
                previousMillis =  currentMillis;
              }
        } 
        
         if((ValoreSensore >= Valorepericolo) && (st==4)) 
        {
          digitalWrite(ledtre, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm ROSSO " + String ((currentMillis- previousMillis)/1000) + " Secondi ");
        } 
 
            if(ValoreSensore < Valorepericolo) 
            {
              st=1;
              digitalWrite(leduno, LOW);
              digitalWrite(ledue, LOW);
              digitalWrite(ledtre, LOW);
              Serial.println("valore sensore " + String (ValoreSensore) + " Nel Range");
              //extern volatile unsigned long timer0_overflow_count;
            }
          
 delay (delay_lettura);         
 }

Non funziona l'ho scitto solo come esempio.. la variabile a indica il numero di cilci effettuati... cioè quante volte controlla se è vero che la fotoresistenza indica molta luce.Sapendo che ha compiuto, per esempio, 1000 cicli e sapendo che gli ho dato un delay di 1 ms vuol dire che in tutto è durato 1*1000 = 1000 circa 1 sec.
Non funziona perche fuori dal "while(valoreinput > 255)" ci va A=0 in modo tale da far tornare i cicli a zero nel caso la fotoresistenza dia valori minori di 255, resettando il "tempo"...
prova così
Cmq oggi non ho niente da fare quindi provo a vedere se ci riesco...

Ecco il codice funziona e lo ho provato personalmente.
l'unico problema è nel caso che la fotoresistenza non dia valori precisi , (per esempio 260,260,245,260,260,260,245) perchè altrimenti il codice trova che è scesa e resetta il "timer" ma poi ritornando come prima si riaccende il led verde, questo a velocità tali da non vedere il led spegnersi e quindi si potrebbe pensare ad un malfunzionamento. Il tempo si puo settare a piacimento, in questo caso dopo 1 secondo cambia colore...
A non si tocca e valmax è il valore dopo il quale i led si accendono.
Ah dimenticavo... i pin sono 11,12,13 (gli unici che mi sono rimasti liberi :disappointed_relieved:)

//BY arduino4ever_ita
int spegni();//la subroutine che serve per spegnere tutti i led senza dover ogni volta scrivere 3 righe di codice
int fotoresistenza; //valore dato dalle fotoresistenza
 //non avendo a disposizione fotoresistenza ho usato ultrasuoni

int tempo = 1000; //indica il numero di volte che il ciclo viene ripetuto
int A;
int valmax = 255; //valore massimo 
void setup()
{
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);
 Serial.begin(9600);
}

void loop()
{
 while(true)
 {
  fotoresistenza=analogRead(A5);
  
  while(fotoresistenza > valmax)
    {
     fotoresistenza=analogRead(A5);
     
     digitalWrite(11, HIGH);
     if(A > tempo)
     {
     digitalWrite(12, HIGH);
     }
     if(A > (2*tempo))
     {
      digitalWrite(13, HIGH);
     }
     delay(1);
     A=A+1;
    }
  Serial.println(fotoresistenza, DEC);//questo è utile perche scriverà solo nel caso la fotoresistenza dia valori meno alti
  spegni();
  A=0;
 }
}

int spegni()
{
 digitalWrite(11,LOW);
 digitalWrite(12,LOW);
 digitalWrite(13,LOW);
}

:stuck_out_tongue: :slight_smile: :stuck_out_tongue:

2 appunti:
è inutile incapsulare il tuo codice in un ciclo infinito con while(true) perché questo già lo fa loop() :wink:

delay(1); attende 1 ms, forse è qui che ti da il lampeggio "schizofrenico". Quanto volevi fargli attendere?

@pablo:
millis non puoi resettarla, è solo una funzione che legge il contatore agganciato al timer 0 dell'Arduino. Dovresti resettare a mano tale contatore (spengendo prima per un attimo l'interrupt agganciato e poi riattivandolo).

leo72:
millis non puoi resettarla, è solo una funzione che legge il contatore agganciato al timer 0 dell'Arduino. Dovresti resettare a mano tale contatore (spengendo prima per un attimo l'interrupt agganciato e poi riattivandolo).

Millis(), inteso come il suo contatore, la puoi resettare quando ti pare e senza spegnere nessun interrupt, ne avevamo già parlato di questa cosa e avevo già proposto la soluzione.

Il semplice sketch di test che avevo preparato per dimostrare come si resetta millis()

/*
    Millis reset
 */

// dichiarazione indispensabile per accedere al contatore di millis()
extern unsigned long timer0_millis;

const int ledPin =  13;        // LED pin
int ledState = LOW;           // ledState 
long interval = 500;           // periodo

void setup()
{
  pinMode(ledPin, OUTPUT); 
  Serial.begin(9600); 
}

void loop()
{
  if(millis() > interval)   // verifica intervallo
  {
    Serial.println(millis(),DEC);   // stampa il valore di millis() per verifica 
    timer0_millis = 0;                    // resetta millis()
   
 // fa lampeggiare il led con periodo pari a "interval"
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

Grazie astrobeed, ho aggiunto il reset del mills() per completezza ora il programmino va che è un orologio :slight_smile:
Ma non credo che a RedEvil interessi ancora pare scomparso. :grin:

#define InputAnalogico A0

const int leduno = 40; 
const int ledue = 41;
const int ledtre = 42;

unsigned long previousMillis = 0;
long timer1 = 5000;
long timer2 = 5000;
//long timer3 = 2000;
int delay_lettura = 1000;
int Valorepericolo = 255;
int st=1; 
extern unsigned long timer0_millis;

void setup()
{
 pinMode(leduno, OUTPUT);
 pinMode(ledue, OUTPUT);
 pinMode(ledtre, OUTPUT);
 Serial.begin(9600); // Inizializzo la comunicazione a 9600
}

void loop()
{
 int ValoreSensore = analogRead(InputAnalogico); // Inserisco il valore della lettura dell'input analogico sull'intero ValoreSensore
 unsigned long currentMillis = millis();
 
   if((ValoreSensore >= Valorepericolo) && (st==1)) 
   {
     Serial.println("*** Inizio ciclo led 1 ***");  
     previousMillis = currentMillis;
       st=2; 
   }
    
        if((ValoreSensore >= Valorepericolo) && (st==2)) 
        {
          //previousMillis = currentMillis; 
          digitalWrite(leduno, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm VERDE " + String ((currentMillis- previousMillis)/1000) + " Secondi " );
         
              if(currentMillis - previousMillis >= timer1) 
              {
                st=3 ;
                Serial.println("*** Fine ciclo led 1 e inizio ciclo led 2 ***");
                previousMillis =  currentMillis;
              }
        }  

        if((ValoreSensore >= Valorepericolo) && (st==3)) 
        {
          digitalWrite(ledue, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm GIALLO " + String ((currentMillis- previousMillis)/1000) + " Secondi ");
              if(currentMillis - previousMillis >= timer2)
              {
                st=4 ;
                Serial.println("*** Fine ciclo led 2 e inizio ciclo led 3***");
                previousMillis =  currentMillis;
              }
        } 
        
         if((ValoreSensore >= Valorepericolo) && (st==4)) 
        {
          digitalWrite(ledtre, HIGH);
          Serial.println("valore sensore " + String (ValoreSensore) + " --> Alarm ROSSO " + String ((currentMillis- previousMillis)/1000) + " Secondi ");
        } 
 
            if(ValoreSensore < Valorepericolo) 
            {
              st=1;
              digitalWrite(leduno, LOW);
              digitalWrite(ledue, LOW);
              digitalWrite(ledtre, LOW);
              Serial.println("valore sensore " + String (ValoreSensore) + " Nel Range" + "valore millis()verifica .. " + String(millis(),DEC));
              timer0_millis = 0;
            }
          
 delay (delay_lettura);         
 }

@leo72:
lo so che è inutile aggiungere il while(true) nel void loop() , però sono abituato così :grin:
E' ben giusto il delay di 1 , quello che volevo dire è che controllando così velocemete può capitare (a me è successo solo 2 volte, però non si sa mai...) che esca dal while dopo aver ricevuto un dato sbagliato, A ritorna 0, si ritorna nel while e quindi il timer si resetta però non si vede il led spegnersi.

@pablos71:
concordo con te, RedEvil1991 è proprio sparito :roll_eyes: