Need advise! Scooter speed calculation.

raits999

Member
I have scooter derbi hunter with digital speedo that went nuts and shows me max 30 km/h. Input is from reed switch that gives 1 pulse per revolution. Brain is PIC16C822 as seen in the picture.
IMG023.jpg

My idea is to use picaxe and seven segment leds, but the problem is how to calculate the speed.

1. read impulses in some time period, it would be easy but very inaccurate.
2. read time between pulses, it would be accurate but hard to calculate.
3. use of gps, it would be accurate and easier to implement in the program, but i do not have any gps module and dont know where to get good module that would be easy to use with picaxe.

So can anybody give me good advise, i would be very graceful.
 
Last edited:

hippy

Ex-Staff (retired)
Would measuring pulses in some time period really be that inaccurate ?

How complex the maths is may depend on what distance one revolution / pulse represents, but I'm sure forum members would be up to the challenge of converting pulse count or period between pulses to a speed for you if you were struggling with that yourself.

Have a search through the forum for other speedometer / tachometer projects as there's probably some useful information on the forum already.
 

raits999

Member
Driving 50km/h gives about 9 revs per second and i want display to update once per second. Not very good idea.

Measuring time is different challenge as speed increases, time decreases and time does not decrease linearly:
1 km/h= 5616 ms
2 km/h= 2808 ms
3 Km/h= 1872 ms
4 km/h= 1404 ms
5 km/h= 1123 ms
10 km/h= 561 ms
20 km/h= 280 ms
30 km/h= 187 ms
40 km/h= 140 ms
50 km/h= 112 ms

As seen above its quite difficult to calculate the speed. My math is not that strong do to that.
 

oracacle

Senior Member
the first thing you need to know but have not mentioned is the rolling circumfrence of the wheel (with tyre). find that in meters, count the pulses over a period of time and - (number of pulses x rolling circumfrence) / measurment time = distance traveled (if meaasure over 1 second ,ultiply by 27.778 to kmh)
the problem is going to be based entirely on the number for the rolling circumfrence, and the period of time you are going to measure the pulses over.
 

bluejets

Senior Member
Apparently a magnet placed directly on the rear face of a hall effect switch will count the spokes, assuming they are steel and not a mag wheel.

As far as GPS, I was told they were only accurate to within a metre or so.
 

raits999

Member
Wheel circumfence is 156 cm and its magnesium alloy. The magnet is built inside hub and the reed switch goes in with plastic capsule, so its not easy to add magnets to it.
 

AllyCat

Senior Member
Hi,

The maths really isn't very difficult. Speed = distance divided by time.

You know the distance for a revolution (156cm) and you can measure the time for one revolution (in us or ms, e.g. using pulsin), so you only have to get the "scaling" correct to do the division.

You can probably get the calculation done (and displayed) before the next revolution is complete (but it's not essential). If you actually want an update only (approximately) each second then you could keep averaging measurements until a second has elapsed (indicated for example by time incrementing).

Cheers, Alan.
 

oracacle

Senior Member
was i just checking my numbers, 1m/s = 3.6 kmh (dunno where i got 27.778 from), so if there is one revolution of the wheel in the space of 1 second you will be doing 5.616kmh = (distance / time) x 3.6. which is about the speed of a brisk walk for most people. how ever you are going to have to get the picaxe to deal with the decimal - maybe try x10 on everything and go from there.

remembered where i got 27.778 from. divide cm/s by 27.778 to kmh so you could do (number of rotations * 156) / 28, this should give you something fairly accurate without the need for moving decimal places around
 

hippy

Ex-Staff (retired)
Driving 50km/h gives about 9 revs per second and i want display to update once per second. Not very good idea.
That's a fair point. It looks then that measuring time between pulses is best ...

Measuring time is different challenge as speed increases, time decreases and time does not decrease linearly:
The relationship 'speed = distance / time' is however inverse linear proportionate so it's simply a case of converting distance in cm, time in milliseconds, to a speed of km per hour ...

speed (cm.ms-1) = distance (cm) / time (ms)

speed (cm.s-1) = ( distance / time ) * 1000

speed (cm.h-1) = ( distance / time ) * 1000 * 3600

speed (m.h-1) = ( ( distance / time ) * 1000 * 3600 ) / 100

speed (km.h-1) = ( ( distance / time ) * 1000 * 3600 ) / ( 100 * 1000 )

speed (kph) = ( distance / time ) * 3600000 / 100000

speed (kph) = ( distance / time ) * 36

If circumference is 156cm then that's -

speed (kph) = ( 156 / time ) * 36

speed (kph) = ( 156 * 36 ) / time

speed (kph) = 5616 / time

Then it's just a matter of scaling so you don't lose resolution with integer maths, eg to get kph to one decimal place multiply by 10 ...

speed (kph) = 5616 / time (ms)

speed (kph) *10 = ( 5616 / time ) * 10

speed (kph) *10 = 56160 / time

Now let's test that with your calculations earlier, ie "5 km/h= 1123 ms", "50 km/h= 112 ms" ...

speed (kph) *10 = 56160 / 1123 = 50 => 5.0 kph

speed (kph) *10 = 56160 / 112 = 501 => 50.1 kph

So looks like we've cracked it :)
 
Last edited:

raits999

Member
I finished my speedo today and it was total success. Only two problems, first was that we didn't take into account pulse length, i made the program so that i can change wheel size on the run. Working circumference is 120 cm . Second problem was that i couldn't use seven segment led's because you cant see it outside. Solution was to use original LCD with PCF8566.

My code if anybody in the future needs it!
Code:
#picaxe 08m2
#no_data
#terminal off

symbol PCF8566=$7C
symbol in=4
symbol menu=pin3
symbol light=0
symbol speed=w0
symbol counter=b2
symbol nr1=b3
symbol nr2=b4
symbol nr3=b5
symbol wheel=b6
symbol distance=w4
symbol paus=100

read 0,wheel
distance=wheel*36*10

hi2csetup i2cmaster,PCF8566, i2cfast, i2cbyte
gosub init_display
setint $0,$10

main:
	if pin4 = 1 then gosub back
	gosub display_animation
	goto main
	
interrupt:
	gosub clear_display
	hi2cout 0,(%00001000)
	hi2cout 4,(%11010111)
	hi2cout 6,(%11011111)
	hi2cout 8,(%11010111)
read_speed:
	pulsin in,1,speed
	pulsin in,1,speed
	if speed=0 then show_speed
	speed=speed/100
	speed= distance/speed
	if speed>1000 then:speed=0
	endif
	if speed=0 then show_speed
	counter=0	
	
show_speed:	
	if speed=0 then: counter=counter+1
	endif
	if counter=>2 then back1
	if speed=0 then read_speed
	let nr1=speed/100 		
	let nr2=speed//100/10       
   	let nr3=speed//10
	lookup nr1,(%11010111,%000000110,%11100011,%10100111,%00110110,%10110101,%111110101,%00000111,%11110111,%10110111),nr1
	lookup nr2,(%11011111,%000001110,%11101011,%10101111,%00111110,%10111101,%111111101,%00001111,%11111111,%10111111),nr2
	lookup nr3,(%11010111,%000000110,%11100011,%10100111,%00110110,%10110101,%111110101,%00000111,%11110111,%10110111),nr3
	hi2cout 0,(%00001000)
	hi2cout 4,(nr1)
	hi2cout 6,(nr2)
	hi2cout 8,(nr3)
	goto read_speed
	
back:
	setint $0,$10
	counter=0
	gosub clear_display
	return
	
back1:
	gosub clear_display
	setint off
	return	
	
calib:
	setint off
	gosub clear_display
calib1:
	let nr1=wheel/100 		
	let nr2=wheel//100/10       
   	let nr3=wheel//10
   	lookup nr1,(%11010111,%000000110,%11100011,%10100111,%00110110,%10110101,%111110101,%00000111,%11110111,%10110111),nr1
	lookup nr2,(%11010111,%000000110,%11100011,%10100111,%00110110,%10110101,%111110101,%00000111,%11110111,%10110111),nr2
	lookup nr3,(%11010111,%000000110,%11100011,%10100111,%00110110,%10110101,%111110101,%00000111,%11110111,%10110111),nr3
   	hi2cout 4,(nr1)
	hi2cout 6,(nr2)
	hi2cout 8,(nr3)
	wheel=wheel+1
	if wheel=>181 then:wheel=100
	endif
	pause 200
	if menu=0 then calib1
	
store:
	pause 500
	write 0,wheel
	distance=wheel*36*10
	gosub clear_display
	return			
	
display_animation:
	hi2cout 2,(%11100110) 'D
	pause paus
	if menu=0 then gosub calib
	hi2cout 4,(%11110001) 'E
	pause paus
	if menu=0 then gosub calib
	hi2cout 6,(%01100000) 'R
	pause paus
	if menu=0 then gosub calib
	hi2cout 8,(%11110100) 'B
	pause paus
	if menu=0 then gosub calib
	hi2cout 10,(%00000110) 'I
	pause 400
	if menu=0 then gosub calib
	hi2cout 2,($0)
	pause paus
	if menu=0 then gosub calib
	hi2cout 4,($0)
	pause paus
	if menu=0 then gosub calib
	hi2cout 6,($0)
	pause paus
	if menu=0 then gosub calib
	hi2cout 8,($0)
	pause paus
	if menu=0 then gosub calib
	hi2cout 10,($0)
	pause paus
	if menu=0 then gosub calib
	return	
	
clear_display:
	hi2cout 0,($0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0)
	return
	
init_display:
	high light
	hi2cout (%11001000,%10000000,%11100000,%11111000,%01110000)
	pause 10
	gosub clear_display
	pause 10
	hi2cout 0,($FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF)
	wait 2
	gosub clear_display
	return
Its not pretty but does the job for now.
Maybe in the future i add more functions like clock, temp, odo, max speed...

Thank everybody who helped me especially to hippy :)
 
Top