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