elettroserratura e temporizzazione

Salve a tutti sto realizzando un progetto che prevede l'utilizzo di un sensore magnetico per l'apertura di un'elettroserratura. Il mio problema è il seguente: quando il magnete è sul sensore magnetico il relè è attivo e l'elettroserratua è alimentata, dovrei impostare un tempo dove anche se il magnete si trova ancora sull'elettroserratura dopo ad esempio 10 secondi il relè si stacca. Ho provato ad inserire un delay ma non ho concluso nulla. Spero in un vostro aiuto.

Ciao, la funzione millis() può fare al caso tuo e negli argomenti recenti trovi molti esempi.....
QUI una discussione recentissima
QUI un articolo consigliato

Stefano

il codice che sto utilizzando è il seguente:

int ledPin = 13;
int sensore_magnetico =4;
int val = 0;     // variabile per leggere lo stato del pin

void setup() {
 pinMode(sensore_magnetico, INPUT);
 pinMode(ledPin, OUTPUT);

}

void loop(){
 val = digitalRead(sensore_magnetico);
 
 if (val == LOW) {                    
   digitalWrite(ledPin, HIGH);
   delay(3000);
   digitalWrite(ledPin, LOW);
  
 }                                     
 else {                                
   digitalWrite(ledPin, LOW);         
 }
}

Se metto il magnete vicino al sensore e dopodichè lo tolgo il questo caso il led dopo 3 secondi si spegne, ciò che interessa realizzare a me e che anche se il magnete resta vicino al sensore dopo 3 secondi deve spegnersi lo stesso

Primo, in conformità al regolamento, punto 7, devi editare il tuo post (in basso a destra del post, bottone More → Modify) e racchiudere il codice all’interno dei tag CODE (… sono quelli che in edit inserisce il bottone fatto così: </>, tutto a sinistra) …

… secondo, l’istruzione delay() che tu usi è un’istruzione che “blocca” il codice e non ti permette di fare altro. Prova quindi a studiarti come si usa la millis() prima QUI, poi QUI ed infine leggi anche QUI e QUI … dovrebbe risultarti più chiaro cosa fare :wink:

Guglielmo

ho editato il codice, qualcuno che mi può aiutare a correggerlo?

Ricordati sempre che sei in un loop() che gira in continuazione, quindi ... devi ...

  1. salvarti lo stato attuale del sensore_magnetico in una variabile, es. sensore_old
  2. se sensore_old è HIGH e sensore_magnetico è LOW vuol dire che hai rilevato il sensore ... aggiorni sensore_old e accendi i tuoi led per 3 secondi
  3. se sensore_old è LOW e sensore_magnetico è sempre LOW vuol dire che NON lo hai tolto e che è sempre li ... non fai nulla
  4. se sensore_old è LOW ed ora sensore_magnetico è HIGH vuol dire che lo hai tolto e quindi aggiorni sensore_old

In pratica, accendi il LED solo se sensore_old è HIGH e sensore_magnetico è LOW e, fino a quando non ritorna in questa condizione non lo accendi più ...

A te sviluppare il codice :wink:

Guglielmo

Ho un po di confusione in testa, essendo ai primi progetti con Arduino, ho provato a seguire le linee guida che mi hai dato, ma con scarsi risultati, mi servirebbe un aiuto nello sviluppo del codice in modo da rendermi conto dove sbaglio, questo è il punto a cui sono arrivata:

int ledPin = 13;
int sensore_magnetico =4;
int val = 0;
int val_old = 0;

void setup() {
 pinMode(sensore_magnetico, INPUT);
 pinMode(ledPin, OUTPUT);

}

void loop(){
 val = digitalRead(sensore_magnetico);
  val_old = val;
 
 if (val_old == HIGH && val == LOW) {                    
   
   val_old = val;
   digitalWrite(ledPin, HIGH);
   delay(3000);
   
  
 }                                     

else

}
 val_old = val;
 
 if (val_old == HIGH && val == LOW) {

prima copi uno sull altro e poi controlli se sono diversi?

La copia devi farla alla fine di tutti i controlli.
Ciao Uwe

Ok, hai impostato la prima condizione (... anche se con l'errore segnalato da Uwe), ma ti mancano le condizioni successive. Poi .. impara a risparmiare memoria, non sei su un PC, sei su una piccola MCU dove anche il byte fa la differenza, per cui:

  1. i valori dei pin mettili con delle #define che NON usano memoria
  2. i valori digitali letti dai pin (LOW/HIGH) NON necessitano di 2 bytes (int), ma gli basta 1 byte (byte)

Detto questo, aggiungendo un paio di IF ELSE lo scheletro del tuo programma diventa :

#define ledPin 13
#define sensore_magnetico 4

byte val     = HIGH;
byte val_old = HIGH;

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

void loop() {
  val = digitalRead(sensore_magnetico);
  if ((val_old == HIGH) && (val == LOW)) {
    // si è avvicinato il magnete ...
    val_old = val; // ... ricordatelo
    //
    // qui quello che vuoi fare
    //
  }
  else if ((val_old == LOW) && (val == LOW)) {
    // non si è ancora allontanato il magnete ...
    //
    // se devi fare qualche cosa in questo caso ... la puoi fare qui
  }
  else if (( val_old == LOW) && (val == HIGH)) {
    // si è allontanato il magnete ...
    val_old = val; // ... ricordatelo
    //
    // se devi fare qualche cosa in questo caso ... la puoi fare qui
  }
}

... a te completarlo ed integrarlo.

Guglielmo

*P.S.: Resta valido il mio suggerimento di imparare ad usare la funzione millis() ed evitare quel delay() che, in questo contesto, non crea particolari problemi, ma, se tu in quei 3 secondi comunque dovessi fare altre cose ... sarebbe un bel problema !!! *

ho integrato il codice in questo modo:

#define ledPin 13
#define sensore_magnetico 4

byte val     = HIGH;
byte val_old = HIGH;

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

void loop() {
  val = digitalRead(sensore_magnetico);
  if ((val_old == HIGH) && (val == LOW)) {
    // si è avvicinato il magnete ...
    val_old = val; // ... ricordatelo
    //
    // qui quello che vuoi fare
    //
    digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);
  }
  else if ((val_old == LOW) && (val == LOW)) {
    // non si è ancora allontanato il magnete ...
    //
    // se devi fare qualche cosa in questo caso ... la puoi fare qui
  
  digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);
  }
  else if (( val_old == LOW) && (val == HIGH)) {
    // si è allontanato il magnete ...
    val_old = val; // ... ricordatelo
    //
  
    // se devi fare qualche cosa in questo caso ... la puoi fare qui
  
  
  }
}

Però il problema che avevo inizialmente non si è risolto, nel senso se avvicino il magnete e poi lo allontano il led resta acceso 3 secondi e poi si spegne, e fin qui va bene, ma se non allontano il magnete il led non si spegne ed è questo il mio problema, che il led deve spegnersi anche se il magnete resta vicino al sensore

... perché evidentemente NON hai studiato il codice ed ... hai messo delle istruzioni dove NON andavano ... guarda BENE cosa hai fatto !!!

Guglielmo

ho capito dove ho sbagliato, però non capisco il perchè

  else if ((val_old == LOW) && (val == LOW)) {
    // non si è ancora allontanato il magnete ...
    //
    // se devi fare qualche cosa in questo caso ... la puoi fare qui
  

    delay(3000);
    digitalWrite(ledPin, LOW);
  }

ma scusa, se il magnete NON è stato allontanato ((val_old == LOW) && (val == LOW)) tu NON devi fare nulla … devi solo aspettare che il magnete si allontani (( val_old == LOW) && (val == HIGH)) quindi …
… perché inserisci qualche cosa in quel else if ? ? ?

Guglielmo

gpb01:
ma scusa, se il magnete NON è stato allontanato ((val_old == LOW) && (val == LOW)) tu NON devi fare nulla ... devi solo aspettare che il magnete si allontani (( val_old == LOW) && (val == HIGH)) quindi ...
... perché inserisci qualche cosa in quel else if ? ? ?

Guglielmo

forse mi sono spiegata male all'inizio, sia nel caso che avvicino il magnete e poi lo tolgo, e sia nel caso che il magnete resta vicino, dopo 3 secondi il led si deve spegnere

NO, no, ti sei spiegata benissimo ... e il tuo codice, se eviti di mettere qualsiasi cosa nel secondo e terzo if, fa esattamente quello ...
... sei TU che invece non stai seguendo le possibili condizioni logiche che si creano!

  1. magnete lontano e mai avvicinato: old = HIGH, attuale = HIGH
  2. magnete avvicinato: old = HIGH, attuale LOW
  3. magnete avvicinato e NON allontanato: old = LOW, attuale LOW
    4 magnete allontanato: old = LOW, attuale HIGH
  4. di nuovo in condizione di riposo: old HIGH, attuale HIGH

Tu devi lavorare SOLO sulla condizione 2, per le altre non devi fare nulla.

Guglielmo

ok, ora volevo capire come funziona, perchè il codice che ho utilizzato inizialmente non ha funzionato?
Chiedo ciò per cercare di capire e di imparare

Questo è il codice che ho scritto inizialmente

int ledPin = 13;
int sensore_magnetico =4;
int val = 0;     // variabile per leggere lo stato del pin

void setup() {
 pinMode(sensore_magnetico, INPUT);
 pinMode(ledPin, OUTPUT);

}

void loop(){
 val = digitalRead(sensore_magnetico);
 
 if (val == LOW) {                    
   digitalWrite(ledPin, HIGH);
   delay(3000);
   digitalWrite(ledPin, LOW);
  
 }                                     
 else {                                
   digitalWrite(ledPin, LOW);         
 }
}

Mmmm ... perdona la franchezza, ma ... se NON riesci a seguire la differenza ed ha capire il perché del funzionamento ... mi sembra che ti manchino proprio le basi ...
... che ne dici, prima di proseguire, magari di dedicare un po' di tempo per studiarti un po' meglio la programmazione di Arduino? ... perché poi ti riavvicinerai, sicuramente più produttivo, al tuo programma :wink:

Magari puoi cominciare con QUESTO e con QUESTO, inoltre puoi scaricarti QUESTO libro (... tranquilla, è un sito legale, purché per esclusivo uso PERSONALE).

Guglielmo

Ovviamente, come ho scritto anche nella presentazione, è il mio progetto con arduino, è normale che lo approfondirò. Di conseguenza adesso ero curiosa di capire del perchè il mio codice iniziale non funzionava, cioè non funzionava solo nel caso che il magnete restava sul sensore, perchè togliendo il magnete il led dopo 3 secondi si spegneva

Ciao, leggo il codice che hai scritto....
se avvicini il magnete e lo togli: entra nell'if, accende il led, attende 3 secondi, spegne il led e finisce il ciclo. Al ciclo successivo se non c'è magnete (ingresso high) spegne il led (che è già spento da prima) ed esce.
Se invece il magnete rimane: entra nell'if, accende il led, attende 3 secondi, spegne il led e finisce il ciclo. Al ciclo successivo rientra nell'if e riaccende il led. Da notare che tra lo spegnimento prima della fine del ciclo e la riaccensione nel ciclo successivo passano ad occhio 2-3 microsecondi quindi ad occhio rimane acceso.

Stefano

Miriam, il codice di Guglielmo ti permette di muoverti con molta più versatilità con quello che vuoi fare. Francamente io nemmeno l'ho capito bene, però con quegli if gestisci TUTTE le fasi che vuoi :slight_smile:
Il tuo vecchio codice funziona male, in realtà ha funzionato bene per quello che dici soltanto per caso, perché tu tieni conto solo se il magnete si è avvicinato e di nient'altro, come pretendi che risolva quello che vuoi? A come ho capito io, quello che vuoi è che se il magnete si avvicina, il led si accende per 3 secondi e poi si spegne, se resta vicino deve rimanere spento? E poi se si allontana il magnete che deve fare?

Esempio per quello che io ho capito che vuoi fare, ma alzo le mani, ci sono troppi errori di punteggiatura nei tuoi messaggi e non conosco io il tuo modo di parlare :slight_smile:

#define ledPin 13
#define sensore_magnetico 4

byte val     = HIGH;
byte val_old = HIGH;

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

void loop() {
  val = digitalRead(sensore_magnetico);
  
  if ((val_old == HIGH) && (val == LOW)) {
    val_old = val;
    digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);
  }
  else if ((val_old == LOW) && (val == LOW)) {
   
   digitalWrite(ledPin, LOW);//ci metti questa riga così sei sicura che il led è spento al 100% anche se il magnete è vicino
  }
  else if (( val_old == LOW) && (val == HIGH)) {
    
    val_old = val; 
    // qua non so che vuoi fare, ovvero quando il magnete si allontana...
    
  
  }
}

Questo fa che se il magnete si avvicina accende il led e lo spegne dopo 3 secondi. Se il magnete resta vicino il led rimane comunque spento. Appena il magnete si allontana, fa qualcos'altro che sai solo tu e ritorna allo stato che sono tutte e due, sia val e val_old, 'HIGH'