Ecco un Timer programmabile basato sulla scheda Arduino che utilizza la shield TIL311 realizzata nell'articolo Termometro con Arduino e display TIL311
Il Timer ha tre modi di funzionamento:
- da 1 a 99 secondi (modo 0)
- da 1 a 99 minuti (modo 1)
- da 10 minuti a 9 ore e 50 minuti (modo 2)
Utilizza il trimmer per impostare il modo: modo 0 con trimmer tutto ruotato in senso antiorario; modo 1 con trimmer tutto ruotato in senso orario; modo 2 con trimmer a metà.
I pulsanti P1e P2 impostano i dati sui relativi display (nel modo 2 P1 imposta le ore e P2 i minuti a passi di dieci). Il pulsante P3 (start/reset) avvia il conteggio del Timer all'indientro. A fine conteggio una nuova pressione di P3 fa smettere il suono del cicalino (buzzer).
Nota: Per azzerare il conteggio alla rovescia prima che sia scaduto il tempo previsto utilizzare il pulsante di reset presente sulla scheda Arduino.
Ecco il codice del Timer programmabile
//Autore: Vincenzo Maida //Data: 4/04/2015 - Torino (Italy) //Timer programmabile a 2 cifre (1-99 sec) con due display TIL311 e tre pulsanti di comando (P1,P2,P3). Trimmer per programmare il modo //P1=Imposta decine (incrementa di uno ad ogni pressione); P2=Imposta Unità; P3=Avvia conteggio alla rovescia //A fine conteggio il display lampeggia. P3 premuto per più di un secondo resetta (spegne i display!!) int trimmer=A0; //TRimmer collegato all'ingresso analogico A0 di Arduino int valoreSensore=0; //Valore restituito dall'ADC proporzionale alla tensione letta dal trimmer (0..1023) int modo=0; //Progammazione dei tempi: modo 0=da 1 a 99sec; modo 1=1-99 minuti; modo 2=da 10 min a 9h e 50min int tb=1000; //Tempo base di 1 sec (1000ms) int p1=4; //pin pulsante P1 (set) Decine int p2=10; //pin pulsante P2 (set) Unità int p3=2; //pin pulsante P3 (Start) int buzzer=13; //Pin del buzzer int DD=0; //Display Decine int DU=1; //Display Unità //Display TIL311 (DP1 e DP2) int BL1=5; //Input Blank (8) di DP1 Decine su uscita PWM di Arduino. 0=Acceso; 1=Spento (attivo basso) //int pin1[] = {1,0,3,6};//Pin TIL311 Decina (Display 1 a sinistra). Segmenti A (3), B(2), C(13), D(12) del TIL 311 int BL2=11; //Input Blank (8) di DP2 Unità su uscita PWM di Arduino. 0=Acceso; 1=Spento (attivo basso) int pinTIL311[][4] = {{1,0,3,6},//Pin TIL311 Decina (Display a sinistra). Segmenti A (3), B(2), C(13), D(12) del TIL 311 {8,7,9,12}//Pin TIL311 Unità (Display a destra). Segmenti A(3), B(2), C(13), D(12) del TIL 311 }; //Tabella di codifica del display TIL311 riga0=A (LSB); riga1=B; riga2=C; riga3=D (MSB). Le colonne rappresentano i numeri sul display codificati in binario //Corrispondenza tra indice di colonna e numero visualizzato sul display. Es.: se indice di colonna=0 Verrà visualizzato lo ZERO cioè avremo A=0; B=0; C=0; D=0; //con indice colonna=9 verrà visualizzato il numero NOVE cioè A=1; B=0; C=0; D=1; con didice di colonna =10 verrà visualizzata la A (il 10 in esadecimale) int TIL[][16]={ {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}, //dato A (LSB) {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1}, //dato B {0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1}, //dato C {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1} //dato D (MSB) }; //Variabili per gestione display int d=0; //Contatore decine int u=0; //Contatore unità int i=0; //Variabili per gestione Timer int td=0; //Tempo decine int tu=0; //Tempo unità int tempo=0; //Tempo trascorso in TempoBase (tb) cioè 1 sec a ciclo // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. //Inizializza segmenti TIL311 di DP1 (Decine) for(i=0;i<4;i++){ pinMode(pinTIL311[DD][i], OUTPUT); } pinMode(BL1,OUTPUT); digitalWrite(BL1,LOW); //Accende il display decine //Inizializza segmenti TIL311 di DP2 (Unità) for(i=0;i<4;i++){ pinMode(pinTIL311[DU][i], OUTPUT); } pinMode(BL2,OUTPUT); digitalWrite(BL2,LOW); //Accende il display unità //Inizializza pulsanti con resistenza di pullup interna pinMode(p1,INPUT_PULLUP); pinMode(p2,INPUT_PULLUP); pinMode(p3,INPUT_PULLUP); } // the loop routine runs over and over again forever: void loop() { //Set modo valoreSensore=analogRead(trimmer); modo=2; if(valoreSensore<340)modo=0;//Valore del trimmer a circa 1/3 della corsa. 340=1,66 Volt di tensione sul trimmer if(valoreSensore>661)modo=1;//Valore del trimmer a circa 2/3 della corsa. 661=3,23 Volt di tensione sul trimmer //Parametri del modo switch (modo){ case 0: td=1; tu=1; break; case 1: td=1; tu=60;// 60 sec = 1 min break; case 2: td=1; tu=600;//600 sec=10 minuti break; } //Set display decine if(digitalRead(p1)==LOW){ delay(500); digitalWrite(BL2,LOW); //Accende il display unità digitalWrite(BL1,LOW); //Accende il display decine d++; if(d>9) d=0; } //Set display unità if(digitalRead(p2)==LOW){ delay(500); digitalWrite(BL2,LOW); //Accende il display unità u++; if(u>9) u=0; if(modo==2 && u>5) u=0; } //Aggiorna cife display aggDisp(DD,d);//Display decine aggDisp(DU,u);//Display unità //Gestione P3 (start/Reset) if(digitalRead(p3)==LOW){ tempo=0; while(u>0 || d>0){ //Aggiorna cife display aggDisp(DD,d);//Display decine aggDisp(DU,u);//Display unità tempo=0; do{ delay(tb); //tone(buzzer,500,50);//Abilitare per avere un beep ogni secondo tempo++; }while(tempo<tu); tone(buzzer,500,50);//Fa un beep ogni unità base (ogni secondo per modo=0; ogni minuto per modo=1 e ogni 10 minuti per modo=2). Commentarlo per togliere il beep if(u>=0) u--; if(u<0 && d>0){ d--; u=9; if(modo==2) u=5; } //Aggiorna cife display aggDisp(DD,d);//Display decine aggDisp(DU,u);//Display unità }//Fine conteggio alla rovescia //Gestione reset while(digitalRead(p3)!=LOW){ tone(buzzer,200,300); //I display lampeggiano finche non premo reset (P3) digitalWrite(BL1,LOW);// Accendo display decine digitalWrite(BL2,LOW);// Accendo display unita delay(500); digitalWrite(BL1,HIGH);// Spegne display decine digitalWrite(BL2,HIGH);// Spegne display unita delay(500); } }//Fine gestione P3 (start/reset) } //Routine aggiornaDisplay void aggDisp(int disp, int numero){ for(i=0;i<4;i++){ digitalWrite(pinTIL311[disp][i],TIL[i][numero]); } }
Una variante del precedente con un contasecondi per i modi 1 e 2 (così si vede che il Timer sta funzionando!). Anche la precisione è migliorata utilizzando la funzione millis() che rispetto alla delay() tiene conto dei tempi di ritardo introdotti dll'esecuzione del codice (aggiornamento display, calcoli, cicli, ecc.) riducendoli al minimo.
Codice Timer programmabile (rev. 1)
//Autore: Vincenzo Maida //Data: 30/04/2015 - Torino (Italy) //Timer programmabile (rev. 1) //Timer programmabile a 2 cifre con due display TIL311, tre pulsanti di comando (P1,P2,P3) e tre modi di funzionamento impostabili mediante un trimmer //P1=Imposta decine (incrementa di uno ad ogni pressione); P2=Imposta Unità; P3=Avvia conteggio alla rovescia //A fine conteggio il display lampeggia e sunona un allarme (buzzer). P3 premuto per più di un secondo resetta (spegne i display ed il buzzer) //Trimmer ruotato tutto in senso antiorario (modo 0) conta da 1 a 99 sec; Triimmer tutto in senso orario (modo 1) conta da 1 a 99 min. //Trimmer a metà (modo 2) conta da 10 min. a 9 ore e 50 min //Variante: Nel modo 1 e 2 parte un contasecondi (da 59 a 0 per ogni minuto). Per i primi 5 sec. viene visualizzato il valore impostato e poi parte il contasecondi. Così ad ogni ciclo int trimmer=A0; //TRimmer collegato all'ingresso analogico A0 di Arduino int valoreSensore=0; //Valore restituito dall'ADC proporzionale alla tensione letta dal trimmer (0..1023) int modo=0; //Progammazione dei tempi: modo 0=da 1 a 99sec; modo 1=1-99 minuti; modo 2=da 10 min a 9h e 50min long int tb=1000; //Tempo base di 1 sec (1000ms) int p1=4; //pin pulsante P1 (set) Decine int p2=10; //pin pulsante P2 (set) Unità int p3=2; //pin pulsante P3 (Start/Reset) int buzzer=13; //Pin del buzzer int DD=0; //Display Decine int DU=1; //Display Unità //Display TIL311 (DP1 e DP2) int BL1=5; //Input Blank (pin 8 del TIL311) del display Decine (DD) su uscita PWM di Arduino. 0=Acceso; 1=Spento (attivo basso) int BL2=11; //Input Blank (8) del display Unità (DU) su uscita PWM di Arduino. 0=Acceso; 1=Spento (attivo basso) int pinTIL311[][4] = {{1,0,3,6},//Pin TIL311 Decina (Display a sinistra). Latch data input A (3), B(2), C(13), D(12) del TIL 311 {8,7,9,12}//Pin TIL311 Unità (Display a destra). Latch data input A(3), B(2), C(13), D(12) del TIL 311 }; //Tabella di codifica del display TIL311 riga0=A (LSB); riga1=B; riga2=C; riga3=D (MSB). Le colonne rappresentano i numeri sul display codificati in binario //Corrispondenza tra indice di colonna e numero visualizzato sul display. Es.: se indice di colonna=0 Verrà visualizzato lo ZERO cioè avremo A=0; B=0; C=0; D=0; //con indice colonna=9 verrà visualizzato il numero NOVE cioè A=1; B=0; C=0; D=1; con didice di colonna =10 verrà visualizzata la A (il 10 in esadecimale) int TIL[][16]={ {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}, //dato A (LSB) {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1}, //dato B {0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1}, //dato C {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1} //dato D (MSB) }; //Variabili per gestione display int d=0; //Contatore decine int u=0; //Contatore unità int i=0; //Variabili per gestione Timer long int td=0; //Tempo decine long int tu=0; //Tempo unità long int ti,tc; //variabili gestione contasecondi int j; int u1,d1; long int ti1,tc1; // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. //Inizializza segmenti TIL311 di DP1 (Decine) for(i=0;i<4;i++){ pinMode(pinTIL311[DD][i], OUTPUT); } pinMode(BL1,OUTPUT); digitalWrite(BL1,LOW); //Accende il display decine //Inizializza segmenti TIL311 di DP2 (Unità) for(i=0;i<4;i++){ pinMode(pinTIL311[DU][i], OUTPUT); } pinMode(BL2,OUTPUT); digitalWrite(BL2,LOW); //Accende il display unità //Inizializza pulsanti con resistenza di pullup interna pinMode(p1,INPUT_PULLUP); pinMode(p2,INPUT_PULLUP); pinMode(p3,INPUT_PULLUP); } // the loop routine runs over and over again forever: void loop() { //Set modo valoreSensore=analogRead(trimmer); modo=2; if(valoreSensore<340)modo=0;//Valore del trimmer a circa 1/3 della corsa. 340=1,66 Volt di tensione sul trimmer if(valoreSensore>661)modo=1;//Valore del trimmer a circa 2/3 della corsa. 661=3,23 Volt di tensione sul trimmer //Parametri del modo switch (modo){ case 0: td=1; tu=1; break; case 1: td=1; tu=60;// 60 sec = 1 min break; case 2: td=1; tu=600;//600 sec=10 minuti break; } //Set display decine if(digitalRead(p1)==LOW){ delay(500); digitalWrite(BL2,LOW); //Accende il display unità digitalWrite(BL1,LOW); //Accende il display decine d++; if(d>9) d=0; } //Set display unità if(digitalRead(p2)==LOW){ delay(500); digitalWrite(BL2,LOW); //Accende il display unità digitalWrite(BL1,LOW); //Accende il display decine u++; if(u>9) u=0; if(modo==2 && u>5) u=0; } //Aggiorna cife display aggDisp(DD,d);//Display decine aggDisp(DU,u);//Display unità //Gestione P3 (start/Reset) if(digitalRead(p3)==LOW){ j=59; ti=millis(); ti1=millis(); while(u>0 || d>0){ tc=millis(); //legge tempo corrente if(modo>0){ //contasecondi(); tc1=millis(); if(tc1-ti1>=tb){ ti1=tc1; //tone(buzzer,500,50);//Abilitare per avere un beep ogni secondo if(j<56){//Aggiorna display contasecondi (dopo 5 sec ad ogni inizio ciclo x visualizzare i minuti rimanenti) d1=j/10; u1=j-(d1*10); aggDisp(DD,d1); aggDisp(DU,u1); }else { //Ripristina valori precedenti aggDisp(DD,d); aggDisp(DU,u); } j--; if(j<0) { j=59; ti1=millis(); } } }//Fine contasecondi if((tc-ti)>=(tb*tu)){ //inizio if tempo ti=tc; tone(buzzer,500,50);//Fa un beep ogni unità base (ogni secondo per modo=0; ogni minuto per modo=1 e ogni 10 minuti per modo=2). Commentarlo per togliere il beep if(u>=0) u--; if(u<0 && d>0){ d--; u=9; if(modo==2) u=5; } //Aggiorna cife display aggDisp(DD,d);//Display decine aggDisp(DU,u);//Display unità }//chiude if tempo }//Fine conteggio alla rovescia //Gestione reset while(digitalRead(p3)!=LOW){ tone(buzzer,200,300); //I display lampeggiano finche non premo reset (P3) digitalWrite(BL1,LOW);// Accendo display decine digitalWrite(BL2,LOW);// Accendo display unita delay(500); digitalWrite(BL1,HIGH);// Spegne display decine digitalWrite(BL2,HIGH);// Spegne display unita delay(500); } }//Fine gestione P3 (start/reset) } //Routine aggiornaDisplay void aggDisp(int disp, int numero){ for(i=0;i<4;i++){ digitalWrite(pinTIL311[disp][i],TIL[i][numero]); } }