Go Down

Topic: Input che aziona 5 relay in sequenza e si interrompe al rilascio improvviso (Read 2661 times) previous topic - next topic

AlPinkish

Ciao  tutti!
Vorrei sapere come posso scrivere un funzione, che in presenza di un segnale in ingresso sul pin 12, attivi 5 relay in sequenza, con un intervallo di 1 secondo l'uno dall'altro, ma che in mancanza del segnale in ingresso, smetta di proseguire l'accensione dei relay, tornando alla situazione di partenza, cioè a relay spenti.

Ho provato con il ciclo While, ma al rilascio del pulsante (usato per simulare l'ingresso) il cilco non si ferma e continua all'infinito e non so come fare.

ci sono altri modi per farlo?

grazie! :)

Homo Faber Fortunae Suae

gpb01

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

P.S.: Qui una serie di link utili, NON necessariamente inerenti alla tua domanda:
- serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections
- pinout delle varie schede by xxxPighi: Pinout
- link generali utili: Link Utili
Search is Your friend ... or I am Your enemy !

gpb01

... dopo che avrai fatto quanto su richiesto, prova a guardare l'istruzione "break" che ... probabilmente risolve il tuo problema ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

Etemenanki

O anche, volendo, metti un ciclo for in un ciclo if ... il for sequenzia i rele', il ritardo lo fai con un confronto millis, ed il ciclo if viene eseguito solo se il pulsante e' sempre premuto e se il for non ha gia superato il conteggio, "ELSE" spegni tutti i rele' ... ;)

EDIT: a proposito, i rele' devono fare un solo ciclo, o continuare ciclicamente finche' rimane l'ingresso ?
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

docdoc

Ho provato con il ciclo While, ma al rilascio del pulsante (usato per simulare l'ingresso) il cilco non si ferma e continua all'infinito e non so come fare.
Se non posti il TUO codice non possiamo aiutarti molto se non dandoti indicazioni generiche. E nella programmazione ogni persona potrebbe ragionare in modo diverso (ad esempio io l'implementerei come una "macchina a stati finiti", tempo fa realizzai anche una libreriola per gestirle).
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

AlPinkish

Tutto ok regolamento letto! Presentazione fatta!

Ho già provato con la funzione break, ma non so come utilizzarla affinché i relè si spengano al rilascio.

Non ho postato il codice, perchè sono indeciso su quale sia la migliore soluzione, se creare una variabile che venga richiamata nella condizione es:
Code: [Select]
while (input12== HIGH && controllo == 1)
   :smiley-lol:

oppure usare, proprio come avete suggerito altri cilcli. il mio intento è fare qualcosa di stabile che non dia problemi.

comunque vi scrivo quello che ho provato:

Code: [Select]
  digitalWrite(relay1, LOW); //spengo tutti i relay prima del ciclo while
  digitalWrite(relay2, LOW);
  digitalWrite(relay3, LOW);
  digitalWrite(relay4, LOW);
  digitalWrite(relay5, LOW);

while (input12== HIGH) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay1, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   digitalWrite(relay2, HIGH); //accendo il 2° relay
   delay(1000); // aspetto 1 secondo
   digitalWrite(relay3, HIGH); //accendo il 3° relay
   delay(1000); // aspetto 1 secondo
   digitalWrite(relay4, HIGH); //accendo il 4° relay
   delay(1000); // aspetto 1 secondo
   digitalWrite(relay5, HIGH); //accendo il 5° relay
   delay(1000); // aspetto 1 secondo
break;
 }

quello che succede quando rilascio il pulsante: la sequenza di accensione dei relay continua fino al 5°, e con break termina il ciclo.
quello che vorrei accadesse quando rilascio il pulsante: la sequanza di accensione si interrompe ed uscita dal ciclo, restando in attesa che venga ripremuto il pulsante "input12". Per poi ripartire dal primo relay alla nuova pressione del pulsante.



Quote
EDIT: a proposito, i rele' devono fare un solo ciclo, o continuare ciclicamente finche' rimane l'ingresso ?
I relay, devono fare un solo ciclo, o meglio se resto con il pulsante premuto, accende tutti i relay ed una volta acceso il 5°, non deve accadere più nulla. Questo perchè nel programma definitivo aggiungerò una variabile globale di controllo da restituire ad un altro costrutto if, per fare altro.
Homo Faber Fortunae Suae

fabpolli

Potreti fare una cosa simile, fuori dal loop:
Code: [Select]

byte arrRel[5] = {relay1, relay2, relay3, relay4, relay5};
void azzera()
{
  for (byte idxRelAzz = 0; idxRelAzz < 5; idxRelAzz++)
  {
    digitalWrite(arrRel[idxRelAzz], LOW);
  }
}

nel loop:
Code: [Select]

azzera();
if (input12 == HIGH)
  {
    for (byte idxRel = 0; idxRel < 5; idxRel++)
    {
      if (input12 == HIGH) {
        digitalWrite(arrRel[idxRel], HIGH);
        delay(1000);
      }
      else
      {
        azzera();
        break;
      }
    }
  }

ho tralasciato la parte di debounce perché se il segnale reale non ne può soffrire sarebbe superflua.
Ho lasciato il delay perché è più semplice da capire, ma se è imperativo che appena il segnale cessa sul pin 12 i relay debbano essere spenti allora occorre rivedere il codice.
Il codice non ho potuto provarlo

docdoc

Non ho postato il codice, perchè sono indeciso su quale sia la migliore soluzione
Non fa niente, metti un codice INTERO della versione che preferisci, almeno possiamo anche provare noi non ti pare?

Tra l'altro perché non usi un emulatore web nel quale potresti anche fare debug più rapidamente?
Io uso Tinkercad (una volta era Autodesk 123circuits), ti registri ed hai il tuo laboratorio virtuale online per provare tante cose (non tutte ovviamente ma queste sicuramente si)!!
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

AlPinkish

Mentre attendevo la vostra risposta ho fatto altri tentavivi ed ho scritto questo versione che funziona:

Code: [Select]



  digitalWrite(relay1, LOW); //spengo tutti i relay prima del ciclo while
  digitalWrite(relay2, LOW);
  digitalWrite(relay3, LOW);
  digitalWrite(relay4, LOW);
  digitalWrite(relay5, LOW);



   int controllo=0; //creo una variabile di controllo


   while (input12== HIGH) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay1, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=10; //associo 10 alla variabile perchè è ancora il pulsante premuto
   break;
   }

  while (input12== HIGH && controllo == 10) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay2, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=20; //associo 20 alla variabile perchè è ancora il pulsante premuto
   break;
   }
  while (input12== HIGH && controllo == 20) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay3, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=30; //associo 30 alla variabile perchè è ancora il pulsante premuto
   break;
   }
  while (input12== HIGH && controllo == 30) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay4, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=40; //associo 40 alla variabile perchè è ancora il pulsante premuto
   break;
   }
  while (input12== HIGH && controllo == 40) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay5, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto

   break;
   }






credo che i cicli sono separati, ma propedeutici.
Cosa ne pensate? è affidabile o è troppo macchinoso?



Quote
byte arrRel[5] = {relay1, relay2, relay3, relay4, relay5};
void azzera()
{
  for (byte idxRelAzz = 0; idxRelAzz < 5; idxRelAzz++)
  {
    digitalWrite(arrRel[idxRelAzz], LOW);
  }
}
Il ciclo for con l'array di sicuro è meglio in termini di byte e lo userò per spegnerli, ma non l'ho ancora provato per lo scopo.
quali differenze ci sono tra un metodo ed un altro, in questo caso tra il for che mi hai proposto ed il while che ho postato? Potrebbero esserci problemi nel modo in cui l'ho scritto io?


Quote
Tra l'altro perché non usi un emulatore web nel quale potresti anche fare debug più rapidamente?
Io uso Tinkercad (una volta era Autodesk 123circuits), ti registri ed hai il tuo laboratorio virtuale online per provare tante cose (non tutte ovviamente ma queste sicuramente si)!!
Si lo conosco, ma avendo già tutto montato fisicamente, sto testando direttamente. Poi è più divertente sentire il ticchettio dei relay :D

Scusate le troppe domande, ma piuttosto che accontentarmi di un codice funzionante, preferisco capire bene anche il "come" delle possibili alternative.
Homo Faber Fortunae Suae

docdoc

Si lo conosco, ma avendo già tutto montato fisicamente, sto testando direttamente. Poi è più divertente sentire il ticchettio dei relay :D
Si lo so, ma è che su quell'emulatore puoi fare DEBUG, mettere breakpoint, vedere il valore delle variabili...
Dopo aver creato il circuito con ARduino ed i relè (per semplicità anche simulati con LED) ci copiaincolli il tuo sketch e te lo debugghi (!!) lì.

Per tornare al tuo codice:
Code: [Select]

   while (input12== HIGH) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay1, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=10; //associo 10 alla variabile perchè è ancora il pulsante premuto
   break;
   }


Ma scusa, se metti un while() e dentro fa sempre break, di fatto è come un if(), a che ti serve messo così?)
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

AlPinkish

Quote
Per tornare al tuo codice:
Code: [Select]

   while (input12== HIGH) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay1, HIGH); //accendo il 1° relay
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=10; //associo 10 alla variabile perchè è ancora il pulsante premuto
   break;
   }


Ma scusa, se metti un while() e dentro fa sempre break, di fatto è come un if(), a che ti serve messo così?)
in effetti ho messo il while perchè teoricamente credevo fosse corretto, proprio per il significato letterale: "mentre".

ma adesso che me lo fai notare, posso sostituire if al while ed eliminare il break a tutti, giusto?
Homo Faber Fortunae Suae

fabpolli

Il ciclo for con l'array di sicuro è meglio in termini di byte e lo userò per spegnerli, ma non l'ho ancora provato per lo scopo.
quali differenze ci sono tra un metodo ed un altro, in questo caso tra il for che mi hai proposto ed il while che ho postato? Potrebbero esserci problemi nel modo in cui l'ho scritto io?

Ti ha già risposto docdoc un while con un break senza condizioni è innutile sono una serie di if di fatto.
Se vuoi la soluzione con il while se ben codificata ti permette di gestire le attese con millis() per fare ciò cui dicevo prima ovvero stai dento al while finché il 5 relé non è stato acceso oppure se non hai perso il segnale, dentro al while con la millis() contolli il tempo trascorso e attivi il relativo relé con il vantaggio che ad ogni ciclo senza attese appena manca il segnale spegni tutti i relé ed esci

docdoc

Si, se metti if() al posto di while() e togli i break funziona allo stesso modo. Ma quel codice DOVE lo hai messo, nel loop()?

E ripeto, o metti tutto il codice o è inutile andare avanti magari proponendoti soluzioni migliori o più eleganti o più efficienti.
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

docdoc

stai dento al while finché il 5 relé non è stato acceso oppure se non hai perso il segnale, dentro al while con la millis() contolli il tempo trascorso e attivi il relativo relé con il vantaggio che ad ogni ciclo senza attese appena manca il segnale spegni tutti i relé ed esci
Esatto, ma se non posta tutto il SUO codice, e visto che ha appreso ora la differenza tra while() e if(), ti pare che -senza offesa- possa capire quello che gli stai suggerendo? 8)
Io quando vedo il suo codice intero possiamo magari provare a fargli qualche esempio di modifica, fino a quel momento è inutile proseguire, secondo me.
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

AlPinkish

fabpolli grazie per i chiarimenti.

Si, se metti if() al posto di while() e togli i break funziona allo stesso modo. Ma quel codice DOVE lo hai messo, nel loop()?

E ripeto, o metti tutto il codice o è inutile andare avanti magari proponendoti soluzioni migliori o più eleganti o più efficienti.

hai ragione non l'ho specificato, ho messo tutto nel loop() e naturalemnte i vari settaggi dei pin nel setup(). ecco lo sketch completo:

Code: [Select]

const int relay1= 3;
const int relay2= 4;
const int relay3= 5;
const int relay4= 6;
const int relay5= 7;
int input12=12;

int controllo; //creo una variabile di controllo
int restituzione=0; // valore restituito per l'azionamento di una funzione


void setup() {

 Serial.begin(115200); //attivo comunicazione seriale

  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(input12, INPUT);


}


void loop() {
  Serial.println("inizio del programma");

   int controllo=0; //azzero la variabile

  digitalWrite(relay1, LOW); //spengo tutti i relay prima del ciclo while
  digitalWrite(relay2, LOW);
  digitalWrite(relay3, LOW);
  digitalWrite(relay4, LOW);
  digitalWrite(relay5, LOW);



   if(input12== HIGH) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay1, HIGH); //accendo il 1° relay
   Serial.println("1_acceso");
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=10; //associo 10 alla variabile perchè è ancora il pulsante premuto
   }


   if(input12== HIGH && controllo == 10) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay2, HIGH); //accendo il 1° relay
   Serial.println("2_acceso");
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=20; //associo 20 alla variabile perchè è ancora il pulsante premuto
 
   }
   if(input12== HIGH && controllo == 20) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay3, HIGH); //accendo il 1° relay
   Serial.println("3_acceso");
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=30; //associo 30 alla variabile perchè è ancora il pulsante premuto

   }
   if(input12== HIGH && controllo == 30) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay4, HIGH); //accendo il 1° relay
   Serial.println("4_acceso");
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   controllo=40; //associo 40 alla variabile perchè è ancora il pulsante premuto

   }
   if(input12== HIGH && controllo == 40) {   //mentre il pulsante è premuto eseguo:
   digitalWrite(relay5, HIGH); //accendo il 1° relay
   Serial.println("5_acceso");
   delay(1000); // aspetto 1 secondo
   input12=digitalRead(12); //ricontrollo se il pulsante è ancora premuto
   Serial.println("restituisco 1");
   restituzione= 1;
 
   }

funzione_esterna();

}// fine loop


void funzione_esterna(){
if(restituzione == 1){
Serial.println(" tutti i relay sono stati accesi e la nuova funzione è stata richiamata correttamente");
//nuova funzione da preparare
}
}




ecco :D

Come posso migliorare il tutto? implementare la funzione millis è comodo per spegnere i relay immediatamente, perchè con il delay arduino resta occupato, giusto, ma come?
Homo Faber Fortunae Suae

Go Up