Diesel motorcycle speedometer

For the Royal Enfield  diesel motorcycle project, I wanted a 120 kmh speedometer.

I found a KUS 120 kmh speedometer that needs a square wave signal with a frequency proportional to the displayed speed value.

The speedometer needs a 500 Hz signal at 30 kmh and at 60 kmh a 1000 Hz signal is and so on. I placed a Hall-effect sensor along with a small magnet at the motorcycle front wheel to measure wheel rotation speed.

The challenge is to add a piece of electronics to convert the front wheel speed signal to the signal required by the speedometer.

For this purpose a microcontroller is needed to do the calculations for the signal conversion. I used the Attiny85 with an external 8 MHz crystal to do the job and ended up with this circuit:

The Hall-effect sensor is supplied with 5 V DC at the SV1 connector, and Hall-effect signal is provided at SV1 connector pin 2. I used theAtmel Studio software development program to compile the AVR GCC C code and to flash the Attiny85 microcontroller. The flash device is the AVR-ISP MKII. The speedometer conversion/interface PCB looks like this:

I did a conversion table to cope with the lack of a 16 bit counter in the Attiny85, it helps to understand the C code In the table ;). Note: Rulleon=Rulleomkreds ~ Wheel Circumference.

The C code is listed here:
/* Speedometer pulse converter program using an ATTINY25.
Converts a pulse per
wheelrotation to a KUS speedometer signal that provides 1000 Hz
at 60 km/h.
3 Attiny25 interrupts are in use:
INT0 ISR starts measuring the next wheel rotation period
Timer0 ISR counts the wheel period using 0.25 msec increments
Timer1 ISR toggles the output pin at the required speedometer
Conversion table and calculations are provided in an spread
sheet !
Erik Henneberg – 2013.11.23
2014.04.27 – Increased wheel sensorpulses by 4 % ( 1 + 26 / 25 )
to achieve higher Timer1 counter/prescale values to lower the
output signal frequency to the speedometer by 4 %
2014.04.30 – adjusted wheel circumference to 2040 mm
*/ #include <avr/io.h>
#include <avr/interrupt.h>
#define WheelCircumference 2040 // wheel circumference in mm
#define MaxSpeed 120 // max. speed is 120 kmh
#define MinSpeed 4 // min. speed is 5 kmh
// define wheel period limits in 0.25 msec resolution, 4 KHz ticks
#define MinPeriod 244 // WheelCircumference *36 / 10 / MaxSpeed
/ 0,25 msec
#define MaxPeriod 7344 // WheelCircumference *36 / 10 /
MinSpeed / 0,25 msec
#define TACHO PORTB0 // tacho signal output attiny pin 5
#define INT0_PIN PORTB2 // wheel signal attiny pin 7
static unsigned int WheelTimer; // 4 KHz tick counter
int main(void)
WheelTimer = 0;
DDRB |= _BV(TACHO); // set the TACHO pin as an output
DDRB &= _BV(INT0_PIN); // set the INT0_PIN pin as an input
PORTB |= _BV(INT0_PIN); // pull up resistor on INT0_PIN input
GIMSK |= _BV(INT0); // Enable external interrupt INT0
MCUCR |= (1<<ISC01) | (1<<ISC00); // INT0 on rising edge
// timer0 controls the 4 khz interrupt to measure the wheel sensor
GTCCR |= _BV(TSM) | _BV(PSR0); // stop and clear
TCCR0A |= _BV(WGM01); // enable ctc
TCCR0B |= _BV(CS01); // clk/8
TIMSK |= _BV(OCIE0A); // enable output compare a interrupt
TCNT0 = 0;
OCR0A = 31; // 4 khz timer0 interrupt
TCCR1 = 0; // Stop Timer1, no output signal
sei(); // enable global interrupts
while(1) { }
} ISR(INT0_vect) {
// handles the external INT0 (
wheel sensor
) interrupt
unsigned int temp;
if ((WheelTimer < MaxPeriod) && (WheelTimer > MinPeriod))
{ TCCR1 =
0; // Stop Timer1
TCCR1 |= _BV(CTC1); // clear timer1 when it matches the
value in OCR1C
TIMSK |= _BV(OCIE1A); // enable interrupt when OCR1A
matches the timer value
if (WheelTimer < 985) { // 985 = 1024 / 1.04
temp = WheelTimer * 26; //.. to keep calculation within 1024
temp = temp / 25; // adds 4 % to wheel pulse timer count
temp = temp/4; // OCR = ( WheelPeriodTemp * 1.04 ) / 4
OCR1A = temp; // set the match value for interrupt
OCR1C = temp; // and the same match value to clear the
TCCR1 |= _BV(CS10) | _BV(CS11); // set prescaler to divide by 4
and restart timer 1
} else {
// (
WheelTimer <
MaxPeriod and WheelTimer >
temp = WheelTimer / 4; // divide by 4 ..
temp = temp * 26; // .. to keep calculation within an unsigned
temp = temp / 25; // adds 4 % to wheel pulse timer count
temp = temp/8; // OCR = ( (WheelPeriodTemp/4)*104% ) / 8
OCR1A = temp; // set the match value for interrupt
OCR1C = temp; // and the same match value to clear the
TCCR1 |= _BV(CS11) | _BV(CS12); // set prescaler to divide by 32
and restart timer 1
WheelTimer = 0; // reset WheelTimer
// 4 kHz timer0 interrupt running continously. Provides ticks to
measure wheel rotation time.
if (WheelTimer >= MaxPeriod) { // if Wheelrotation low or zero
TCCR1 = 0; // Stop Timer1
WheelTimer = MaxPeriod;
} else WheelTimer++;
// Outputs the signal to the speedometer. Toggles output pin.
ISR(TIMER1_COMPA_vect) { // handles the Timer1 Compare Match
A interrupt
PORTB ^= _BV(TACHO); // just toggle the TACHO output signal

11 thoughts on “Diesel motorcycle speedometer

  1. I do not even know how I ended up here, but I
    thought this post was good. I do not know who you are but definitely you’re going to a famous blogger if you aren’t
    already 😉 Cheers!

  2. Ahaa, its nice conversation on the topic of this post here at this website, I have read
    all that, so at this time me also commenting here.

  3. I lіke the valuable info you provide for yоur articleѕ.
    I will b᧐okmark yuг blog and teѕt ɑgain right hегe frequently.
    I’m fqirly sure I will be informed many neeѡ stguff proper riht here!
    Good luck for the following!

  4. This dеsіgn is spectacular! You certainly know how to
    keep a reader amused. Betwеen your wit and your ѵideoѕ,
    I was ɑlmost moved to start my own blog (well, almost…ΗaHa!) Gгeat jоb.
    Ι really loved what yoou had to say, and more than that, how you presented it.
    Тoo cool!

  5. Excellent blog! Do you have any suggestions for aspiring writers?
    I’m planning to start my own blog soon but I’m a little
    lost on everything. Would you propose starting with a free platform like WordPress or go for a paid option? There are so many options
    out there that I’m completely confused .. Any ideas?
    Appreciate it!

  6. Terrific article! This is the type of info that are meant to be shared across
    the web. Shame on the search engines for now
    not positioning this post higher! Come on over and
    talk over with my website . Thank you =)

  7. Greetings! Very helpful advice within this post!
    It is the little changes that will make the biggest changes.
    Thanks a lot for sharing!

Leave a Reply

Your email address will not be published.