Un altro esempio di codice per contare il numero di giri al minuto (RPM) di un motore. Gli impulsi devono provenire da un sensore ottico o magnetico con uscita digitale a 5V.

In questo esempio viene utilizzato sia un LCD che la porta seriale per visualizzare il valore dei giri al minuto e il numero di impulsi contati durante il periodo del segnale in ingresso al pin 2 del micro arduino.

Il codice è ampiamente commentato e non dovrebbe essere complicato.Come sempre potete contattarmi per eventuali chiarimenti.

//---------- Inclusione librerie ----------------------------
#include<LiquidCrystal.h> //Include librerie  display LCD
#include <TimerOne.h>//Include librerie TimerOne

//---------- Definizione costanti  ----------------------------
#define InSensor 2 //Definizione di costante pari a 2
#define INT0   0
#define Time_4500_msec 4500
#define RS 12
#define EN 11
#define D4 6
#define D5 5
#define D6 4
#define D7 3
LiquidCrystal lcd(RS,EN,D4,D5,D6,D7);//RS,EN,D4,D5,D6,D7 RW=massa


//---------- Definizione variabili globali   -----------------

long  CountedPulse=0;
long RPM=0;
long RPM2;
int Cycle,media = 0; 
bool Timeout=false;
unsigned long myTime,Tim_elapsed;
unsigned int Counter=0;

void setup()
{
 //---------------------Inizializzazione porta seriale ------------------------
    Serial.begin(115200); // Imposta la velocità della porta seriale a 115200 bps
    
    lcd.begin(16,2);//Display 16x2
    lcd.setCursor(0,0);//Posiziona cursore  nella posizione (0,0)
    lcd.print("ARDUINO RPM");//Visualizza su LCD ARDUINO RPM
    delay(2000);//Attendi 2 sec
    lcd.clear();//Pulisce schermo
   
    cli();//Disabilita tutti gli interrupt
    
//------------------------Inizializazzione TIMER0----------------------------------

    //Imposta timer0 interrupt ad 1 msec
    TCCR0A = 0;// Imposta il registro TCCR0A a 0
    TCCR0B = 0;// Imposta il registro TCCR0B a 0
    TCNT0  = 0;//Inizializza il contatore a 0
    // Imposta il registro OCR0A per avere un interrupt a 1 msec
    OCR0A = 249;// = (16*10^6) / (1000*64) - 1 (deve essere <256)
    // Abilita CTC 
    TCCR0A |= (1 << WGM01);
    // Imposta CS01 and CS00 bits per avere un prescaler di 64
    TCCR0B |= (1 << CS01) | (1 << CS00);   
    // Abilita l'interrupt del timer compare
    TIMSK0 |= (1 << OCIE0A);
    
    Counter=Time_4500_msec;//Imposta la variabile Counter per un ritardo di 4.5 sec
    
    Timer1.initialize(10); //Imposta il timer1 per interrupt ogni 10 usec
    Timer1.attachInterrupt(timerIsr); // attach the service routine here
     
    attachInterrupt(INT0, RPMPulse, RISING); //Interrupt sul fronte di salita sul Pin 2 (INT0)
    sei();//Abilita interrupts
    
    pinMode(InSensor, INPUT);    // Imposta pin 2  come input
}
//---------------------------------------------------------------------------
/*Timer0 usato per azzerare RPM dopo 4,5 sec che il micro non riceve più impulsi
 sul pin 2 */
      ISR(TIMER0_COMPA_vect){
      
       if(Counter>0){
        
        if(--Counter==0){//Dopo 4,5 sec
          RPM=0;//Azzera valore di RPM
          Timeout=true;//Imposta timeout a true
        }
       }
    }
  //------------------------------------------------------------------------------
 /*Ogni volta che arriva un fronte di salita sul pin 2 viene ricaricata la variabile  Counter.
 Se non arrivano impulsi su INT0 (pin 0) per più di 4,5 sec , il valore di RPM viene azzerato
 dal timer 0 */  
void RPMPulse()
{
   Counter=Time_4500_msec;//Carica un timeout di 4,5 sec
     
     if (Cycle == 0)                // Controlla se è l'inizio del ciclo
      {
          CountedPulse=0;//Azzera il numero d'impulsi
          Timer1.start(); //Abilita la partenza del timer 1 con interrupt ogni 10 usec per conteggio impulsi
          Cycle = 1;           // Imposta la variabile Cycle=1
          return;                     // non esegue l'if successivo
      }
     
     if (Cycle == 1)  // secondo fronte di salita (Inizio nuovo ciclo)
     {
         Cycle = 0;//Azzera la variabile Cycle
         Timer1.stop();//Disabilita il conteggio degli impulsi
         detachInterrupt(INT0);         // Disabilita l'interrupt su INT0
         noInterrupts();//Disabilita gli interrupt     
         ShowCountedPulse();// Visualizza impulsi contati e RPM
     }
     
}
//-----------------------------------------------------------------------------

void timerIsr()
{
    ++CountedPulse;
}
//-----------------------------------------------------------------------------

 void ShowCountedPulse(){
      
    media+=1;
   
     if(media<6){//Calcola la media dopo 5 misure
           
            RPM+=(60*100000)/CountedPulse;//da 1Hz=60 RPM segue 1Hz/60 RPM=(10^5/CountedPulse)/x
            //segue x=(10^5/CountedPulse)*60 RPM
  
         }else{
    
        media=0;
        RPM=RPM/5;
        
      // Visualizza su porta seriale
        Serial.print("Impulsi contati =");           
        Serial.print(CountedPulse);                   // Pulse debug output 
        Serial.println();
    
        Serial.print("RPM= ");
        Serial.print(RPM);
        Serial.println();
        
       // Visualizza su LCD
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Impulsi=");
        lcd.print(CountedPulse);
        
        lcd.setCursor(0,1);
        lcd.print(RPM);
        lcd.print("  RPM");
        lcd.print("");
        RPM=0;
   }
 
  attachInterrupt(INT0, RPMPulse, RISING);      // Interrupt sul pin 2 INT0
  interrupts(); 
     
 }
//------------------------------- Timeout ----------------------------------
void loop()
{

  if(Timeout){//Se non arrivano impulsi per più di 4,5 sec
    
        Serial.print("Impulsi contati =0");  
        Serial.println();
        Serial.print("RPM=0");
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Impulsi=0");
        lcd.setCursor(0,1);
        lcd.print("RMP=");
        lcd.print(0);
        lcd.print("   ");
        Timeout=false;
    }
 
}

Grazie per l'attenzione al prossimo progetto.

 

Primok_V

No comments

Leave your comment

In reply to Some User