/*
Programmed by Peter Bell
Speedometer to display speed and pulse parameters
of a tachograph V-pulse output on connector B pin 7
*/
#include <LiquidCrystal.h> // declare the lcd library
LiquidCrystal lcd(12, 11, 10, 9, 8, 7); // the pins used for the lcd display
// vareiables used
long cval=0; // stores the counter value when the pulse input changes state
bool value; // the state of the pulse input imediately after it has changed state
long plse; // the duration of the V pulse
long period; // the period of the V pulse
float frequency; // the pulse frequency
float speed; // the speed
long K;
int oflo; // how many times did the timer overflow
ISR(TIMER1_OVF_vect) // timer 1 overflow interrupt vector
{
oflo++; // the timer has overflowed so increment the overflow timer
if (oflo>=7) // test if it has overflowed 5 or more times
{
period=0; // if yes then the speed is considered to be zero so set
plse=0; // pulse period, pulse duration and speed to
speed=0; // zero
}
}
// timer 1 is clocked at 2 MHz
void pulse() // interrupt procedure when pulse input changes state
{
cval=TCNT1; // get the value fof timer coounter 1
TCNT1=0; // then immediately reset it to 0
value = digitalRead(2); // get the state of port pin 2 (V pulse input pin)
if (value) // test if true or false
{
period=cval/2+plse+oflo*32768+1; // true so input has just gone high so calculate the pulse period
// Pulse high time + pulse low time (cval is 2*pulse low time)
// add 2^15 for each time the timer overflowed (32768) 16 bit timer clocked at 2MHz
// add 2 to compensate for interrupt latency(time between pulse occuring and timer being cleared)
oflo=0; // reset the overflow counter
}
else{
plse=cval/2+1; // false so input has just gone low so calculate the pulse width as cval divided by 2
}
}
void setup() // setup procedure
{
noInterrupts() ; // turn off all interrupts
lcd.begin(20,4); // initialize the lcd
lcd.clear(); // clear the lcd
lcd.setCursor(0,0); // set the lcd cursor to the start of the top line
lcd.print("V Pulse Speedometer"); // display the initial message on the lcd
TCCR1A = 0; // set timer 1 control register A to 0
TCCR1B = (TCCR1B & B11111000) | B010; // set timer 1 control register B to use the prescaler of 8
// clocks timer 1 at 16/8 Mhz (2 MHz)
pinMode(2, INPUT_PULLUP);
// digital pin 2 is ser as an input with an internal pullup resistor
attachInterrupt(digitalPinToInterrupt(2), pulse, CHANGE);
// setup external interupt to occur on pin 2 change of state
TIMSK1=B00000001; // start timer 1
interrupts(); // enable the interrupt system
delay(4000); // delay to let the user see the initial message
}
void loop() // main program loop, repeat indefinitely
{
lcd.clear(); // clear the display
lcd.setCursor(0,0); // set the cursor to the start of the display
lcd.print("Pulse=");
lcd.print(plse); // print the pulse duration in microseconds
lcd.print("uS K="); // print microseconds
if (plse!=0)
K= (float)16000000/plse+.5;
else
K=0;
lcd.print (K);
lcd.setCursor(0,1);
lcd.print("Period ="); // then 2 spaces
lcd.print(period); // then print the pulse perioid in microseconds
lcd.print("uS"); // print microseconds
if (period!=0) // test if period is 0 to avoud divide by zero error
{
speed = (float)plse/period*225; // period is non zero so calculate speed
// speed is 225 times the percentage of pulse in the period
// i.e. if pulse is 20% of period then speed is 225*20% or 45 Km/h
frequency=(float)1000000/period;
}
else
{
speed=0;
frequency=0;
}
lcd.setCursor(0,2);
lcd.print("Frequency =");
lcd.print (int(frequency+.5));
lcd.print( "Hz ");
lcd.setCursor(0,3); // set the cursor to the start of the fourh line of the display
lcd.print("Speed ="); // print Speed =
lcd.print(int(speed+.5)); // print the speed
lcd.print ("Km/h"); // then print Km/h on the display
delay(1000); // delay for 1 second to prevent screen flicker
} // all done so g and do it again