Simulazione nastro trasportatore

Salve, sono nuovo del forum. Sono uno studente di 16anni di elettrotecnica. Da poco abbiamo iniziato lo studio di Arduino, ma vengo subito al dunque. Devo simulare un nastro trasportatore senza peraltro il motore. Premendo un pulsante P1 si attiva un relé e si accede un led1 che indica che il nastro si è avviato. Questo per 10s, tempo necessario per giungere al finecorsa. Trascorsi questo tempo si accende un altro LED per 3 secondi, il quale simula il conteggio del pezzo trasportato. Premendo poi il Pulsante P2 il nastro trasportatore si ferma. Il problema è banale, col PLC mi basterebbe usare un paio di pulsanti in serie, un normalmente aperto e l'altro normalmente chiuso, la bobina e i due led. Con Arduino riesco a fare la prima parte: Attivo il relè (con un transistor pilotato dall'uscita di Arduino) ed accendo il LED1 per 10.000ms. Dopo accendo l'altro LED2 per 3.000ms in modo da simulare il conteggio. Il problema, almeno per me, è P2, quello che dovrebbe spegnere tutto l'impianto (relè e LED1). Io ho provato a scrivere questo sketch, ma all'avvio LED1 mi lampeggia molto velocemente. Premo P1 si accende il LED1 (e scatta il relé), passano i 10s e si accende il LED2 per 3s e fin qui nessun problema se non che all'inizio, prima di premere S1 il LED1 lampeggia in modo molto veloce, quasi impercettibile. dopo essere trascorsi i 3s di accensione del secondo LED, indipendentemente che prema o meno S2 il LED1 si spegne ed il relé si diseccita. :frowning: Dove sbaglio? Grazie a chi vorrà darmi un aiuto, che ammetto sarà banale ma che non riesco a capire...

int pinLed1=13; //assegna Led 1 al pin 13
int pinLed2=12; //assegna Led 2 al pin 12 
int bottone1=2; //assegna S1 al pin 2
int bottone2=3; //assegna S2 al pin 3
int statoPulsante1=LOW; 
int StatoPulsante2=HIGH;

void setup() {                
 pinMode(pinLed1, OUTPUT);  //Led 1 come uscita
 pinMode(pinLed2, OUTPUT);  //Led 2 come uscita
 pinMode(bottone1, INPUT);  //S1 come ingresso
 pinMode(bottone2, INPUT);  //S2 come ingresso
}

void loop() {
 int leggiBottone1=digitalRead(bottone1); //legge lo stato logico di S1
 int leggiBottone2=digitalRead(bottone2); //Legge lo stato di S2

 if (leggiBottone1 == 0)
 statoPulsante1=LOW;
      digitalWrite(pinLed1, LOW); 

} else {
      statoPulsante1=HIGH; // Se S1 chiuso pone alto il Led1
      digitalWrite(pinLed1, HIGH);
      delay(10000); //Accende il Led1 per 10s (simula trasporto)
      digitalWrite(pinLed2, HIGH);
      delay (3000); //Accende il Led2 per 3s (simula conteggio)
      digitalWrite(pinLed2, LOW); //Spegne Led2 (conteggio avvenuto)
             
} 


 if (leggiBottone2 == 1)
     statoPulsante2=HIGH; 
     digitalWrite(pinLed1, LOW); //Se S2 è chiuso, spegne Led1
      

} else {

      statoPulsante=LOW;
      digitalWrite(pinLed1, HIGH); //Altrimenti ripete il loop in attesa che S1 venga chiuso
      


    }


}

> JuniorPI: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

Grazie,

Guglielmo

Spero di aver corretto bene. :-[

JuniorPI:
Spero di aver corretto bene. :-[

Guglielmo

Alcuni consigli ...

  1. Usa la funzione del IDE Tools -> Auto Format per riorganizzare in modo ordinato, con tutte le indentature fatte bene, il codice.

  2. Imparerai presto che usare la delay() è si mooooolto facile, ma ha un pesante rovescio della medaglia ... durante la delay() tutto è bloccato e NON si può fare null'altro, quindi il consiglio è ... studiati come si usa la millis(), prima QUI, poi QUI ed infine leggi anche QUI e QUI ... vedrai che ti tornerà molto utile appena il programma dovà fare più cose (es. durante un periodo di attesa, comunque leggere i bottoni).

  3. NON stai tenedo affatto conto dei "rimbalzi" dei bottoni ...
    ... un bottone "ideale" quando lo premi si chiude e quando lo rilasci si apre ... purtroppo NON è affatto così con un bottone "reale" il quale, esaminato con un oscilloscopio, ha il segunete comportamento:


... e quindi, quando leggi, leggi una raffica di "premuto"/"rilasciato".

Per ovviare a ciò o si fa un "debouncing" software (cerca su Google "arduino debouncing") o lo si fa hardware (soluzione più semplice e consigliata ... vedi schemi allegati).

Guglielmo

debouncing_hw.pdf (22.8 KB)

Guglielmo mille grazie. Purtroppo, essendo un "compito" scolastico non posso ricorrere all'istruzione millis per il semplice fatto che il prof. non ce l'ha ancora spiegata... e se pure mi piacerebbe darmi delle arie e dirgli "prof. però se si usasse Millis..." :smiley: non credo sia opportuno. Sull'antiribalzo HW, ricordo che in laboratorio di etn in terza abbiamo creato un circuito simile, quando abbiamo fatto i contatori. Detto questo, pensi sia per il rimbalzo che se non premo S2 si spegne tutto, così come se lo premo?

JuniorPI:
... Detto questo, pensi sia per il rimbalzo che se non premo S2 si spegne tutto, così come se lo premo?

Sicuramente i rimbalzi ti creano dei problemi ... piccola rete R/C e passa la paura, poi ... sistema il codice come ti ho chiesto (1) e ripubblicalo pulito (... togliendo anche le inutili linee vuote) che lo si esamina meglio :wink:
Guglielmo

Ok, ci provo.

... quando lo avrai riformattato come ti ho detto prima .. capirai perché NON ti funziona ... hai fatto un "bel disastro" con le parentesi graffe :smiley: :smiley: :smiley: :smiley:

Guglielmo

... altra cosa che NON inficia il funzionamento, ma l'occupazione di memoria ... tutto ciò che può assumere un valore tra 0 e 255 (... quindi il numero di un pin, la lettura di un pin digitale, ecc.) è INUTILE metterlo in un "int", che occupa 2 bytes (... quindi da +32768 a +32767), ma è sufficiente una variabile di tipo "byte" :wink:

Guglielmo

Ho apportato qualche modifica ed usato il comando di formattazione automatica, pare funzionare mah... se premo o non premo S2 trascorsi i 10+3s i due Led si spengono entrambi (cosa che dovrebbe avvenire solo premendo S2). Se premo di nuovo S1 il ciclo si avvia nuovamente: Led1 10s (HI) + Led2 3s (HI)
:roll_eyes:

L'Ide non mi segnala alcun errore di sintassi in fase di compilazione, bella soddisfazione...

int pinLed1 = 11; //assegna Led 1 al pin 13
int pinLed2 = 12; //assegna Led 2 al pin 12
int bottone1 = 2; //assegna S1 al pin 2
int bottone2 = 3; //assegna S2 al pin 3
int statoPulsante = LOW;

void setup() {
  pinMode(pinLed1, OUTPUT);  //Led 1 come uscita
  pinMode(pinLed2, OUTPUT);  //Led 2 come uscita
  pinMode(bottone1, INPUT);  //S1 come ingresso
  pinMode(bottone2, INPUT);  //S2 come ingresso
}

void loop() {
  int leggiBottone1 = digitalRead(bottone1); //legge lo stato logico di S1

  if (leggiBottone1 == 0) {
    statoPulsante = LOW;
    digitalWrite(pinLed1, statoPulsante);
  }
  else {
    statoPulsante = HIGH; // Se S1 chiuso pone alto il Led1
    digitalWrite(pinLed1, HIGH);
    delay(10000); //Accende il Led1 per 10s (simula trasporto)
    digitalWrite(pinLed2, HIGH);
    delay (3000); //Accende il Led2 per 3s (simula conteggio)
    digitalWrite(pinLed2, LOW); //Spegne Led2 (conteggio avvenuto)
  }

  int leggiBottone2 = digitalRead(bottone2); //Legge lo stato di S2
  if (leggiBottone2 == 0) {
    statoPulsante = LOW;
    digitalWrite(pinLed1, statoPulsante); //Se S2 è aperto, non spegne Led1
  } else {
    statoPulsante = HIGH;
    digitalWrite(pinLed1, statoPulsante); //Altrimenti S2 è chiuso e spegne Led!
  }
}

... mmm ... COME hai collegato i pulsanti ? Hai messo le resistenze di pull-up ?

Guglielmo

P.S. Vedo che non hai applicato quanto ti ho detto al post #9 ...
... non che cambi la logica, ma l'occupazione di memoria SI !

ciao...nel primo else, trascorsi i 10+3 secondi il led2 lo spegni tu...poi se nel primo if, che viene eseguito quasi istantanemanete al termine dei delay(), se non metti una seconda condizione che memorizza la prima pressione del bottone1, questa ti spegne il led1....

altra opzione è ragionare per "stati finiti"...crei una variabile che prende un valore specifico ad ogni azione e ti lascia eseguire, verificata con delle if, solo specifiche azioni...ritornandone altre.

Salve a tutti ragazzi, innanzitutto grazie per i vostri consiglio. Rileggendo la traccia dell'esercizio ho provato ad apportare delle modifiche, diciamo così, concettuali. La traccia dice: "Si deve automatizzare il nastro trasportatore di un magazzino che ha le seguenti caratteristiche: Premendo il pulsante S1 il nastro deve partire (simulazione con accensione di un LED1 verde). Al raggiungimento del finecorsa (tempo stimato 10s) un altro LED2 rosso si accenderà per circa 2s, simulando il conteggio. Premendo il pulsante S2, il nastro trasportatore si fermerà (simulazione con spegnimento del LED1 rosso).

Bene, ragionandoci (confermatemi se ho ragione) il Delay di 10s per tenere HIGH il LED1 è del tutto inutile, tanto trascorsi i 10s lo scatolo raggiunge il finecorsa. Il problema quindi è accendere il LED2 dopo 10s, tenerlo acceso per 2s e poi spegnerlo. Fatto questo, quindi trascorso questi 12s ma evidentemente anche di più siccome non c'è un automatismo perché il comando di S2 è manuale, spegnere il Led1.

Ho ripulito quindi il codice

//dichiaro i PIN dei componenti

int led1 = 2; //led rosso
int pulS1 = 3; //pulsante S1

int led2 = 4; //led verde
int pulS2 = 5; //pulsante S2

//variabili
int valS1 = 0; //stato del valore del pulsante S1
int valS2 = 0; //stato del valore del pulsante S2


void setup() { 
  pinMode(led1, OUTPUT); //led rosso come OUTPUT
  pinMode(led2, OUTPUT); //led verde come OUTPUT
  pinMode(pulS1, INPUT);  //pulsante S1 come INPUT
  pinMode(pulS2, INPUT);  //pulsante S2 come INPUT

}

void loop() {
  valS1 = digitalRead(pulS1); //leggiamo il val. di S1
  valS2 = digitalRead(pulS2); //leggiamo il val. di S2

  if (valS1 == 1) {
    digitalWrite(led1, HIGH); // Se S1 è premuto si accende il led1
    digitalWrite(led2, HIGH); 

// sopra ho messo led2 ma credo che non ci debba andare perché dovrebbe accendersi dopo 10s, restare HIGH per 2s e poi spegnersi... e NON SO COME FARE perché se uso Delay e poi lo spengo tutto si blocca in questo loop di If. Viceversa senza Delay, si accende ovviamente insieme a Led1!!!
  }
  else {
    digitalWrite(led1, LOW); //Se S1 non è premuto il led1 è spento
   }

  if (valS2 == 1) {
    digitalWrite(led1, LOW); //Se S2 è premuto il led1 si spegne
   }
  else { //
    digitalWrite(led1, HIGH); //Se S2 non è premuto il led1 resta acceso
  }
}

Ripeto, è un esercizio scolastico di 4 ITI elettrotecnico, quindi immagino dovrebbe esserci una soluzione meno ingegnosa e per dummies delle vostre che già mi avete proposto. Millis non lo abbiamo ancora studiata... Ma se è proprio indispensabile, mi potete dire come e dove dovrei inserirla?

Ah, dimenticavo. Venerdì devo portare la soluzione a scuola :confused: Help me! :roll_eyes:

nell'ultimo listato non hai messo i ritardi? Visto che non puoi usare mills c'è un altro sistema per avere ritardi di 10 secondi e poter leggere lo stesso lo stato di un pulsante senza bloccare tutto, in teoria ti devi creare un ciclo for dove hai un delay(500) che sarebbe mezzo secondo, e nel ciclo fai ad esempio 20 passaggi così hai un tempo di 10 secondi, dopo ogni delay leggi lo stato del pulsante e se cambia imposti una variabile ed esci con break da for e continui il programma. Più sarà basso il valore di delay e quindi maggiore i passaggi da fare con for più il "sistema" sarà veloce a leggere lo stato del pulsante, ma mezzo secondo è più che sufficiente

Vediamo, qualcosa del tipo da mettere subito dopo il digitalWrite(Led2,HIGH) nel primo If o proprio al suo posto?

for(int i=0; i<20;i++){
      int led2 =i;
      digitalWrite(led2, HIGH);
      delay(500);

ciao...dal mio punto di vista, rispetto alla traccia data, il tuo codice fa "troppe" cose in più...
il testo dice..in sintesi:

  • hai LED1 e LED2 spenti(stato di partenza)
  • premi il pulsante S1 e si accende LED1
  • LED1 resta acceso 10 secondi
  • si accende LED2 per 2 secondi
  • si pegne LED2
  • se premi il pulsante S2 deve spegnersi LED1

tutto il resto è in più...in pratica molti dei tuoi else dove metti low le uscite non ci vanno...sempre di non aver mal interpretato l'esercizio dato.

:o Ciao Orso, il problema è che se uso il Delay (10000) dopo l'accensione con S1 di Led1, accendo poi automaticamente Led2 con un Delay (2000) e poi lo spengo... resto imprigionato nel primo ciclo If del pulsante S1 e non riesco (o meglio Arduino non lo fa) ad attivare il secondo If, quello di S2 che mi serve a chiudere Led1. Pure a me la traccia pare banale, si sarebbe potuto fare tutto con un solo pulsante, per esempio S1 :smiling_imp: ma sto da ieri a non trovare soluzioni. Però sto imparando un sacco di cose nuove :smiley: solo che non mi portano a risolvere questo problema (ancora)... Ma ce dobbiamo fare! :grin:

scusa...provo a ragionare:

verifico stato pulsante S1
se ho premuto pulsante S1 {
alzo uscita led 1
attendo 10 secondi
alzo uscita led 2
attendo 2 secondi
resetto uscita led 2}
verifico stato pulsante S2
se ho premuto pulsante S2 {resetto uscita led 1}

>JuniorPI: ... come al solito chiedete aiuto "all'ultimo momento" ...
... ma per imparare ad usare bene millis() e riscrivere tutto il programma, perché con millis() cambia tutta la logica, dubito fortemente ti basti questa sera e domani ... ::slight_smile:

Fai come ti è stato suggerito e, per ora, continua ad usare la semplice delay(), poi, con calma ed il dovuto tempo, ti studierai i link che ti ho dato.

Guglielmo