Stampa
Categoria: Elettronica
Visite: 3537

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:

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]);
        }
}