ciao, ho intenzione di temporizzare le luci delle scale tramite una scheda arduino che utilizzo anche per altro, quindi sto cercando di fare un codice non bloccante.
a banco sembra funzionare (non ho rilevato bug) però non è ancora integrato nel resto del codice.
volevo chiedervi se cè un modo per semplificare il codice (per non intralciare il resto del codice) pur mantenendo le caratteristiche principali ovvero:
1 pressione accende le luci > poi si spegne dopo tot secondi
1 pressione durante il tempo di accensione > mi resetta il timer
2 pressioni consecutive > blocca la luce su on
1 pressione dopo lo stato di blocco > spegne le luci
ora mi funziona ma mi sembra un codice esagerato
#define pulsante 5
#define luce 6 //relè
byte stato;
byte clic = 0;
byte statopulsante = 1;
byte statopulsanteprecedente = 0;
int doppioclic = 2000; //durata doppio clic
int timerluce = 10000; //durata luce
unsigned long tempopuls; //variabile per doppio clic
unsigned long iniziotimer; //variabile per tempo luce
void setup() {
pinMode (pulsante, INPUT_PULLUP);
pinMode (luce, OUTPUT);
digitalWrite (luce, HIGH);
Serial.begin(9600);
}
void loop() {
if ((digitalRead (pulsante) == LOW) && (clic == 0)) {
clic = 1;
statopulsante = 0;
}
if ((digitalRead (pulsante) == HIGH) && (clic == 1)) {
clic = 0;
statopulsante = 1;
}
if ((statopulsante == LOW) && (stato == 0)) { //prima accensione luce
Serial.println ("primo if");
tempopuls = millis();
iniziotimer = millis();
digitalWrite (luce, LOW);
stato = 1;
statopulsante = 1;
}
if ((statopulsante == LOW) && (stato == 1) && ((millis() - tempopuls) < doppioclic)) { //blocco su on se faccio 2 pressioni consecutive
Serial.println ("blocco on");
stato = 2;
statopulsante = 1;
}
if ((statopulsante == LOW) && (stato == 1) && ((millis() - tempopuls) > doppioclic)) { // reset secondi se faccio 1 pressione mentre è acceso
Serial.println ("reset secondi");
tempopuls = millis();
iniziotimer = millis();
statopulsante = 1;
}
if ((statopulsante == LOW) && (stato == 2)) { //spegnimento premendo il pulsante se mi trovo nello stato "on bloccato"
Serial.println ("spegnimento manuale");
digitalWrite (luce, HIGH);
stato = 0;
statopulsante = 1;
}
if ((stato == 1) && ((millis() - iniziotimer) > timerluce)) { //spegnimento automatico dopo superato il tempo imposto
Serial.println ("spegnimento automatico");
digitalWrite (luce, HIGH);
stato = 0;
}
delay (50);
}
non mi pare esagerato... sono 60 righe di programma... devi solo levare
byte statopulsanteprecedente = 0;
visto che non l'hai usata e i vari print sulla seriale una volta testato...
e si riduce il tutto a
Lo sketch usa 1430 byte (4%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 21 byte (1%) di memoria dinamica, lasciando altri 2027 byte liberi
Se 'statopulsante' lo si setta sempre all'inizio del ciclo e si resetta solo all'istante di una pressione, si può togliere quel statopulsante = 1; da tutti i gestori degli eventi:
A proposito dei gestori degli eventi, questi andrebbero eseguiti in modo mutuamente esclusivo (else if), senza valutare ogni volta tutti gli if. Infatti mi pare strano che funzioni, perché una volta eseguito il codice del primo if (prima accensione luce) dovrebbe risultare vero anche il secondo, e quindi si finisce sempre subito nello stato 2.
Claudio_FF:
Se 'statopulsante' lo si setta sempre all'inizio del ciclo e si resetta solo all'istante di una pressione, si può togliere quel statopulsante = 1; da tutti i gestori degli eventi:
statopulsante = 1;
if ((digitalRead (pulsante) == LOW) && (clic == 0)) {
A proposito dei gestori degli eventi, questi andrebbero eseguiti in modo mutuamente esclusivo (else if), senza valutare ogni volta tutti gli if. Infatti mi pare strano che funzioni, perché una volta eseguito il codice del primo if (prima accensione luce) dovrebbe risultare vero anche il secondo, e quindi si finisce sempre subito nello stato 2.
statopulsanterecedente si è da eliminare,mi è rimasto dalle varie prove.
quindi da come mi hai modificato la prima parte del codice, stato pulsante verrà resettata solo dall'if che verrà eseguito, ottima idea!
mentre non ho capito cosa intendi qui:
Claudio_FF:
A proposito dei gestori degli eventi, questi andrebbero eseguiti in modo mutuamente esclusivo (else if), senza valutare ogni volta tutti gli if. Infatti mi pare strano che funzioni, perché una volta eseguito il codice del primo if (prima accensione luce) dovrebbe risultare vero anche il secondo, e quindi si finisce sempre subito nello stato 2.
non può essere vero anche il secondo if perchè "statopulsante" viene messo a 1
boh, non so, tra poco comincia il film, quindi non posso provare
ma questo compila in:
Lo sketch usa 1034 byte (3%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 11 byte (0%) di memoria dinamica, lasciando altri 2037 byte liberi per le variabili locali. Il massimo è 2048 byte.
e credo vada:
// di Nelson "StandardOil"
// Idea da sviluppare:
// timer per luci scala
#define LUCE 6
#define PULSANTE 5
#define DURATA 600 // tempo in decimi di secondo dell'accensione
#define PASSO 5 // distanza massima tra due pressioni per bloccare la luce
int contatore; // il de-contatore di accensione luce
void setup(void)
{
pinMode(LUCE, OUTPUT);
pinMode(PULSANTE, INPUT_PULLUP);
}
void loop(void)
{
if (!digitalRead(PULSANTE))
// se leggo il pulsante
{
if (contatore != DURATA + 1)
{
// luce non bloccata
contatore = DURATA;
// carico il de-contatore
}
else
{
// luce era bloccata
// la spengo
contatore = 0;
}
if (contatore > DURATA - PASSO)
{
// siamo entro un passo di click
// blocco acceso
contatore = DURATA + 1;
// contatore oltre il limite significa contatore bloccato
}
else
{
// nulla da fare, ho già ricaricato prima
}
while (!digitalRead(PULSANTE));
// no falsi avviamenti, aspettiamo la fine della pressione
}
if (!millis() % 100) // ogni decimo di secondo
{
if (contatore)
{
contatore--;
// de-conto il decimo di secondo
}
}
digitalWrite(LUCE, contatore);
}
no, comunque non andrebbe
lo proverò certamente nel pomeriggio ma serve di cambiare queste righe
if (contatore)
{
contatore--;
// de-conto il decimo di secondo
}
con queste:
if (contatore)
{
if (contatore > DURATA)
{
contatore--;
// de-conto il decimo di secondo
}
}
così dovrebbe andare
se provi tu fammi sapere
per Guglielmo invece:
Perchè un programma che usa una sola variabile int globale e nessuna locale alloca 11 byte di variabili globali?
probabilmente è qualche cosa che viene caricato dalle librerie incluse automaticamente....
infatti se compili un programma vuoto ti da
Lo sketch usa 444 byte (1%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 9 byte (0%) di memoria dinamica, lasciando altri 2039 byte liberi...
Nessun programma è realmente "vuoto" ...
... ricordatevi che voi in realtà definite (come minimo) solo due funzioni, setup() e loop(), ma che tutto il resto, anche se NON lo vedete (il main(), tutte le routines del "core", le sue variabili globali, ecc. ecc.), c'è ed occupa sia flash che SRAM.
Provato, naturalmente non funziona(va)
ma una volta capito il gioco è facile da correggere, il risultato finale lo ho provato e va come deve:
Lo sketch usa 1128 byte (3%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 11 byte (0%) di memoria dinamica, lasciando altri 2037 byte liberi per le variabili locali. Il massimo è 2048 byte.