Sto cercando di far funzionare un programma relativamente semplice:
legge il valore della fotoresistenza
se inferiore a 512 accende il led per 10 secondi e poi lo spegne per 20 secondi
se superiore a 512 lo spegne per 20 secondi
Sto continuando a provare da diversi giorni, ormai non so più che pesci pigliare.
Questo è il codice che ho attualmente:
#define LED 6
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
unsigned long TempTime=0;
unsigned long LedTime=0;
unsigned long LedCycle=0;
int ValTemp;
int ValTempMin=1023;
int Counter=0;
int Temp=0;
void setup() {
pinMode(LED,OUTPUT); //indica output
delay(3000); //attendi 3 secondi
}
void loop() {
unsigned long Check1=millis();
if(Check1-TempTime>=5000){
TempTime=Check1; //controlla la fotoresistenza ogni 5 secondi
ValTemp=analogRead(A0); //leggi il valore di temperatura
ValTempMin=min(ValTemp,ValTempMin); //confronta i valori e trova il minore
lcd.setCursor(2,0); //setta il cursore in posizione
lcd.print(ValTemp); //scrivi il valore rilevato
lcd.setCursor(11,0); //setta il cursore in posizione
lcd.print(ValTempMin); //scrivi il valore minimo
}
unsigned long Check2=millis();
if(Check2-LedCycle>=20000){
LedCycle=Check2; //controlla il led ogni 20 secondi
Temp=analogRead(A0); //leggi il valore di temperatura
Startup(); //esegui void
}
}
void Startup() {
if(Temp<512){
On(); //esegui void
}
else{
Off(); //esegui void
}
}
void On() {
LedTime=millis(); //inizia il conteggio
if(millis()-LedTime<10000){
digitalWrite(LED,HIGH); //accendi l'output
Counter++; //aumenta di 1
lcd.setCursor(14,1); //setta il cursore in posizione
lcd.print(Counter); //scrivi il valore
}
else{
digitalWrite(LED,LOW); //spegni l'output
}
}
void Off() {
LedTime=millis(); //inizia il conteggio
if(millis()-LedTime<20000){
digitalWrite(LED,LOW); //spegni l'output
}
}
Quando esegue il void On() è come se non capisse che deve spegnere il led dopo 10 secondi, rimane acceso.
SI, uno solo: riparti da capo quando un progetto non va si fa prima a ripaertire che perdere tempo a salvarlo
inoltre mi sembra che hai messo troppi punti dove controlli troppi tempi
semplificati, non gestire lo LCD per adesso
e chiarisci cosa significa:
se superiore a 512 lo spegne per 20 secondi
e lo tiene acceso per quanto? oppure vuoi dire che per 20 secondi, a led spento NON legge la fotocellula?
Standardoil:
SI, uno solo: riparti da capo quando un progetto non va si fa prima a ripaertire che perdere tempo a salvarlo
inoltre mi sembra che hai messo troppi punti dove controlli troppi tempi
semplificati, non gestire lo LCD per adesso
e chiarisci cosa significa:
se superiore a 512 lo spegne per 20 secondi
e lo tiene acceso per quanto? oppure vuoi dire che per 20 secondi, a led spento NON legge la fotocellula?
Si, volevo far aggiornare la Temp ogni 5 secondi e scrivere il valore sull'lcd.
Nell 3) intendevo che il led rimane spento per 20 secondi, terminati questi il programma rilegge la fotocellula e ricomincia il ciclo.
OK, per il momento non guarderei troppo per il sottile, la lettura ogni 5 secondi dopo
io farei un ciclo semplice
primo spengo (che male non fa mai)
poi un semplice test, analogread < di soglia
se si accendi e carica un timer a 10 secondi
se no carica un timer a 20 secondi
come prima cosa puoi provare con dei delay, per poi passare a millis
domanda strana: funziona? Non vedo a pinMode per settare il pin del led ad output.
Comunque se stai usando una Arduino Uno (più comune) e non usi quel pin per altro, puoi usare come pin led il 13, sul quale è già collegato un led
#define LED 6
int Temp=0;
unsigned long Shutdown=0;
unsigned long OnTimer=0;
void setup() {
Serial.begin(9600);
pinMode(LED,OUTPUT);
delay(1000);
}
void loop() {
digitalWrite(LED,LOW);
Temp=analogRead(A0); //leggi il valore analogico
Shutdown=millis()+20000; //inizia il conteggio
if(Temp<512){ //se il valore è inferiore a 512
digitalWrite(LED,HIGH); //accendi il led
OnTimer=millis()+10000; //inizia il conteggio
if(OnTimer<millis()&&Shutdown<millis()){ //10 secondi dopo l'accensione e fino a 20 secondi
digitalWrite(LED,LOW); //spegni il led
}
Temp=1023; //resetta il valore analogico al massimo
OnTimer=millis()+10000; //resetta il conteggio
Shutdown=millis()+20000; //resetta il conteggio
}
else{ //se il valore è superiore a 512
digitalWrite(LED,LOW); //spegni il led
Serial.println("off"); //scrivi off
if(Shutdown<millis()){ //se sono trascorsi più di 20 secondi
Shutdown=millis()+20000; //resetta il conteggio
}
}
}
Immagino sia una cosa del genere, però mi sfugge qualcosa…
Silente:
domanda strana: funziona? Non vedo a pinMode per settare il pin del led ad output.
Comunque se stai usando una Arduino Uno (più comune) e non usi quel pin per altro, puoi usare come pin led il 13, sul quale è già collegato un led
Si funziona senza specificare il pinMode, forse grazie al #define LED 6(?)
gagliardo:
Si funziona senza specificare il pinMode, forse grazie al #define LED 6(?)
No, funziona per pura fortuna, la define semplicemente dice al compilatore di mettre 6 ogni volta che trova la scritta LED, in realtà il pinMode c'è ma è sul pin errato, per modificare il programma in modo che sia corretto basta modificare
avanti un passo.
Provo a ragionare liberamente, cme se fossi io da solo a riflettere sul problema
risscrivendo le tue specifiche (sempre pensare a cmabiate l'ordine dei fattori, il risultato non cambia, la complessità forse sì)
dicevo riscrivo le tue specifiche: se c'è luce accendo per 10 secondi, poi spengo per venti
se invece non c'è luce aspetto 20 secondi per provare di nuovo
ancora: provo, aspetto 20 secondi, provo di nuovo, aspetto 20 secondi, provo di nuovo, aspetto20 etc etc, ma se quando provo trovo luce accendo e aspetto 10 secondi
proviamo a scriverlo, sempre in italiano, ma un po' formale, quasi come un programma
ciclo ripetuto sempre:
Vedo se c'è luce
Se c'è:
Accendo il led
aspetto 10 secondi
Spengo il led
Altrimenti
Aspetto 20 secondi
Ripeto il ciclo
il problema sono le attese, senza delay, usando millis. per il momento ignoriamo il problema dello owerflow di millis, facciamo finta che non ci sia
ri-scriviamo di nuovo le specifiche: se ho il led accceso sto aspettando 10 secondi, invece se ho il led spento ne sto aspettando 20
il testo può essere una cosa del tipo:
se millis> target
dove target è il tempo che devo aspettare
se il led è acceso
lo spengo
adesso devo aspettare 20 secondi
target = millis+20000
altrimenti
provo la luminosità
se OK
accendo il led
adesso devo aspettare solo 10 secondi
altrimenti
non accendo il led
e aspetto 20 secondi
fine del ciclo
Sono sicuro che non è difficile tradurlo in una loop funzionante
poi s pensa al display con misure ogni 5 secondi
e poi si pensa allo overflow della millis
HUUU a proposito
scegli se leggi una luminosità o una temperatura, e metti consistenti nomi di variabili e commenti, prima regola del buon programmatore secondo Nelson (che sono io):
Vero, ma io lo IF non lo ho messo, me ne guardo bene
ho già fatto una volta l'errore di scrivere il programma per uno OP, e mi ha cazziato nvece di ringraziarmi
adesso il programma se lo scrivono gli OP, e le IF le fanno loro.........
Standardoil:
... ho già fatto una volta l'errore di scrivere il programma per uno OP, e mi ha cazziato nvece di ringraziarmi
adesso il programma se lo scrivono gli OP, e le IF le fanno loro ...
Ho sistemato e provato, così funziona perfettamente! Grazie!! PS pensavo che programmare un timer fosse molto più complicato di target=millis()+timer, mi hai aperto un mondo
Ho letto qualcosa sull’overflow e per il momento ho capito che devo usare unsigned long, approfondirò con calma. Domani provo ad aggiungere le rilevazioni ogni 5 secondi!
#define LED 7
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
int Lum; //valore analogico fotoresistenza
unsigned long int target=0; //timer
byte LedState=LOW; //stato led spento
void loop() {
if(millis()>target){ //se tempo trascorso è maggiore del timer
if(LedState==HIGH){ //se lo stato del led è acceso
LedState=LOW; //cambia lo stato del led in spento
digitalWrite(LED,LedState); //spegni il led
Serial.println("cool"); //scrivi cool
target=millis()+20000; //imposta il timer di 20 secondi
}
else{ //se lo stato del led è spento
Lum=analogRead(A0); //rileva il valore analogico
if(Lum>=512){ //se è uguale o superiore a 512
LedState=LOW; //cambia lo stato del led in spento
digitalWrite(LED,LedState); //spegni il led
Serial.println("off"); //scrivi off
target=millis()+20000; //imposta il timer di 20 secondi
}
else{ //se è inferiore a 512
LedState=HIGH; //cambia lo stato del led in acceso
digitalWrite(LED,HIGH); //accendi il led
Serial.println("on"); //scrivi on
target=millis()+10000; //imposta il timer di 10 secondi
Lum=1023; //resetta il valore analogico al massimo
}
}
}
}
Aggiunte anche le rilevazioni luminosità ogni 5 secondi:
unsigned long LumTimer=5000; //intervallo tra misurazioni di luminosità
unsigned long prevLum=0; //variabile usata per memorizzare il momento dell'ultima rilevazione
...
if(millis()-prevLum>=LumTimer){
prevLum=millis(); //esegui ogni 5 secondi
Lum=analogRead(A0); //rileva il valore analogico
minLum=min(Lum,minLum); //confronta i valori e trova i minore
Da quel che ho capito sull'overflow, la soluzione qui sopra è già ok e fa il rollover da sola.
Quello che bisogna modificare è questo IF:
if(millis()>target){
...
Che si potrebbe mettere così immagino:
unsigned long target;
...
if((long)(millis()-target)>=0){
Adesso sarebbe da modificare il registro come scritto QUI per verificare che funzioni