Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Speed sensor calculation using Python

Tue Jun 14, 2016 6:25 am

There are 2 methods for calculating speed using Python.

The first method is using "pre-defined interval".
The second method is using "calculated interval".


Before we dive straight into the code let me show you the setup of this project. What we need are RaspberryPi, hall effect sensor or reed switch and small magnet. You can use either one of the sensor and the code would be pretty much the same.
The hall effect sensor that I'm using is of Unipolar type. Depending on how you setup the magnet on the spinning mechanism, it will decide which type of hall sensor is suitable for you. Unipolar sensor can only get triggered on one side of the sensor. Bipolar sensor has the ability to detect magnet in both directions.

Reed sensor is a much simpler device to use for this project . I will show you how to use both sensors.
As this project is just a prototype for the wheel of our motorcycle/car, I'm using a cpu fan as a replacement for the real wheel.
The magnet is mounted on the flat surface of the fan.

Hall effect sensor has 3 pins or legs. There are VCC, Ground and Output.
Connect the VCC to 3.3V . (correction! I wrote 5V earlier)
Ground as usual.
And output to any GPIO that you wish. If everything is connected, you are good to go.


CALCULATED INTERVAL METHOD

(CODE)

Code: Select all

#!/usr/bin/python3
import RPi.GPIO as GPIO
from time import sleep
import time, math

dist_meas = 0.00
km_per_hour = 0
rpm = 0
elapse = 0
sensor = 12
pulse = 0
start_timer = time.time()

def init_GPIO():					# initialize GPIO
	GPIO.setmode(GPIO.BCM)
	GPIO.setwarnings(False)
	GPIO.setup(sensor,GPIO.IN,GPIO.PUD_UP)

def calculate_elapse(channel):				# callback function
	global pulse, start_timer, elapse
	pulse+=1								# increase pulse by 1 whenever interrupt occurred
	elapse = time.time() - start_timer		# elapse for every 1 complete rotation made!
	start_timer = time.time()				# let current time equals to start_timer

def calculate_speed(r_cm):
	global pulse,elapse,rpm,dist_km,dist_meas,km_per_sec,km_per_hour
	if elapse !=0:							# to avoid DivisionByZero error
		rpm = 1/elapse * 60
		circ_cm = (2*math.pi)*r_cm			# calculate wheel circumference in CM
		dist_km = circ_cm/100000 			# convert cm to km
		km_per_sec = dist_km / elapse		# calculate KM/sec
		km_per_hour = km_per_sec * 3600		# calculate KM/h
		dist_meas = (dist_km*pulse)*1000	# measure distance traverse in meter
		return km_per_hour

def init_interrupt():
	GPIO.add_event_detect(sensor, GPIO.FALLING, callback = calculate_elapse, bouncetime = 20)

if __name__ == '__main__':
	init_GPIO()
	init_interrupt()
	while True:
		calculate_speed(20)	# call this function with wheel radius as parameter
  		print('rpm:{0:.0f}-RPM kmh:{1:.0f}-KMH dist_meas:{2:.2f}m pulse:{3}'.format(rpm,km_per_hour,dist_meas,pulse))
		sleep(0.1)
Using calculated interval method is better and more precise than pre-defined interval.
Here, we make use of the time.time() module in Python to precisely measure time duration of each interrupt interval.
We are using add_event_detect() to take advantage of the GPIO pin interrupt event handler.
Here we use one callback function called "calculate_elapse(channel)". This function will get called anytime interrupt event happens.

TRY to grab this concept in order to understand this code.

We are using ONE magnet mounted on one of the fan blade and ONE hall effect sensor
mounted on a static surface on our fan chassis.
Image

Therefore, we could come up with an assumption that 1 complete rotation will be made whenever 1 interrupt event occurs.

From that assumption, we could determine the time duration of 1 complete rotation in our callback function.

So, lets take a look at the callback function in the code. It is named "calculate_elapse(channel)". In that function, we have
3 main global variables. Global variables are made so that their values can be used outside that local function which
in our case, our local variable is the callback function named "calculate_elapse(channel)". The globals are:

- pulse
- start_timer
- elapse

1) pulse : a counter variable used to count the number of interrupts. it can also be used to calculate total distance travelled
by the wheel.
2) start_timer : a time variable that stores the initial timestamp before an interrupt occurs and stores the current timestamp
after the interrupt has occurred!
3) elapse : time duration of 1 complete rotation by subtracting the timestamp during interrupt instance with start_timer which holds
the initial timestamp before that interrupt occurred.

After we have calculated the elapse, we immediately set our new start_timer with the current timestamp so that it can be used to
calculate our next elapse value if new interrupt occurs.

Now that we have our global elapse value, we can move on to next function which is "calculate_speed(r_cm)". this function will be called
in our main loop. This function takes in one parameter which is the radius of wheel in centimeter (you could use meter if you wish).
As the global elapse value is now accessible in this function, we can calculate the speed of the wheel using simple mathematical
formula.

First, we have to make sure that our elapse value is not Zero to avoid DivisionByZero error.

Round Per Minute (rpm) can be calculated using : rpm = 1/elapse * 60
where 1 is referring to 1 complete rotation and 60 is referring to 60 seconds.

circ_cm (wheel circumference) can be calculated using : 2 x pi x radius

dist_km (distance moved in km) can be calculated using : dist_km = circ_cm/100000

km_per_sec (speed in KM/s) calculated using: km_per_sec = dist_km / elapse

km_per_hour (speed in KM/h) calculated using: km_per_hour = km_per_sec * 3600


That's all for the CALCULATED INTERVAL METHOD! You can try it with your Raspberry Pi and get the result printed on the terminal. Good luck!
Last edited by Yazidapple on Tue Jun 14, 2016 9:32 am, edited 1 time in total.

Massi
Posts: 1637
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: Speed sensor calculation using Python

Tue Jun 14, 2016 8:17 am

Yazidapple wrote: Hall effect sensor has 3 pins or legs. There are VCC, Ground and Output.
Connect the VCC to 5V .
Ground as usual.
And output to any GPIO that you wish. If everything is connected, you are good to go.
This is ok only if the hall has a OC output. If it's a RC output you can damage your pi powering it with 5V
Here, we make use of the time.time() module in Python to precisely measure time duration of each interrupt interval.
probably if you want to "precisely measure time duration of each interrupt interval" you should use pigpio.
Pigpio timestamps interrupts when they occurr, in your code you use the (not so) precise python time.time() when the callback is executed.

Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Tue Jun 14, 2016 9:15 am

Massi wrote:
Yazidapple wrote: Hall effect sensor has 3 pins or legs. There are VCC, Ground and Output.
Connect the VCC to 5V .
Ground as usual.
And output to any GPIO that you wish. If everything is connected, you are good to go.
This is ok only if the hall has a OC output. If it's a RC output you can damage your pi powering it with 5V
Here, we make use of the time.time() module in Python to precisely measure time duration of each interrupt interval.
probably if you want to "precisely measure time duration of each interrupt interval" you should use pigpio.
Pigpio timestamps interrupts when they occurr, in your code you use the (not so) precise python time.time() when the callback is executed.
thanks for the feedback bro. i'll try to improve this code and the setup! still learning anyway :D

User avatar
joan
Posts: 12820
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Speed sensor calculation using Python

Tue Jun 14, 2016 9:21 am

http://abyz.co.uk/rpi/pigpio/examples.h ... ead_RPM_py shows a method using pigpio.

You might be interested in viewtopic.php?f=37&t=90243

Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Tue Jun 14, 2016 9:35 am

joan wrote:http://abyz.co.uk/rpi/pigpio/examples.h ... ead_RPM_py shows a method using pigpio.

You might be interested in viewtopic.php?f=37&t=90243
Thanks so much! Thats really what I was looking for before I started working with this project.

am3u
Posts: 1
Joined: Tue Jul 26, 2016 6:22 pm

Re: Speed sensor calculation using Python

Wed Jul 27, 2016 4:40 am

but how much accurate is it

Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Wed Dec 07, 2016 5:40 am

am3u wrote:but how much accurate is it
the accuracy is quite acceptable for small and simple project where you just wanna create a simple speedometer to calculate the speed of your bike / motobike. as mentioned our friend above, pigpio method is the most accurate implementation.

Onkarb68
Posts: 2
Joined: Mon Jan 23, 2017 1:23 pm

Re: Speed sensor calculation using Python

Mon Jan 23, 2017 1:28 pm

Can anyone please tell which RPM sensor has got best accuracy for Raspberry pi3 model B?

ilman
Posts: 22
Joined: Wed Mar 08, 2017 5:08 am

Re: Speed sensor calculation using Python

Mon Apr 10, 2017 5:12 am

i've tried the code and i get a normal result overall. but reading can't back to 0 if rotation get stopped. how did it happen?

Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Tue Apr 11, 2017 12:37 pm

ilman wrote:i've tried the code and i get a normal result overall. but reading can't back to 0 if rotation get stopped. how did it happen?

actually its just because there's simply no logic for it in the code :lol:
i just found a speed sensor (rotary disc) for Arduino on this website.
https://brainy-bits.com/blogs/tutorials ... th-arduino

i think you can use that code as reference to modify the Python code.

Code: Select all

#include <OneWire.h>
unsigned int counter=0;

void docount()  // counts from the speed sensor
{
  counter++;  // increase +1 the counter value
} 

void timerIsr()
{
  Timer1.detachInterrupt();  //stop the timer
  Serial.print("Motor Speed: "); 
  int rotation = (counter / 20);  // divide by number of holes in Disc
  Serial.print(rotation,DEC);  
  Serial.println(" Rotation per seconds"); 
  counter=0;  //  reset counter to zero
  Timer1.attachInterrupt( timerIsr );  //enable the timer
}

void setup() 
{
  Serial.begin(9600);
  
  Timer1.initialize(1000000); // set timer for 1sec
  attachInterrupt(0, docount, RISING);  // increase counter when speed sensor pin goes High
  Timer1.attachInterrupt( timerIsr ); // enable the timer
} 

void loop()
{
  // just leave it empty if you have nothing else to do in your program
}


Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Tue Apr 11, 2017 12:39 pm

Onkarb68 wrote:Can anyone please tell which RPM sensor has got best accuracy for Raspberry pi3 model B?
are you asking for devices that could be used as speed sensor for Raspberry Pi?
any hall effect sensor or even a simple reed switch would suffice.

gurudattakr123
Posts: 2
Joined: Wed Mar 15, 2017 4:07 pm

Re: Speed sensor calculation using Python

Wed Apr 19, 2017 6:15 pm

How can we change this code so that rpm and kmph must come back to 0 when wheel is not rotating?

Yazidapple
Posts: 23
Joined: Wed Mar 23, 2016 3:06 pm

Re: Speed sensor calculation using Python

Mon Jul 03, 2017 12:12 pm

gurudattakr123 wrote:How can we change this code so that rpm and kmph must come back to 0 when wheel is not rotating?

will work on that. as for now you could try to search for other alternatives. i would recommend you to use Arduino for speedometer project instead of Pi.

Massi
Posts: 1637
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: Speed sensor calculation using Python

Mon Jul 03, 2017 1:40 pm

gurudattakr123 wrote:How can we change this code so that rpm and kmph must come back to 0 when wheel is not rotating?
well probably the program works based on callback, so if no signal is received, no calculation is done.
You can try playing with pigpio's watchdogs
http://abyz.co.uk/rpi/pigpio/python.html#set_watchdog
you should setup, in the callback, a watchdog on the GPIO so that if no callback is called within the timeout, the watchdog will call it and you'll return 0
Obviously in every callback you should cancel the previous watchdog and setup the new one.

RaMaSen
Posts: 1
Joined: Sun Jun 11, 2017 7:55 pm

Re: Speed sensor calculation using Python

Wed Sep 27, 2017 9:26 pm

Hi,

The calculation methods I can comprehend,
however........ I want to use a ble sensor instead of an GPIO sensor for my project (I have a Major dislike towards Cords when it can be done Wireless).
I get data from my ble sensor but can't use it nor calculate the RPM from it.
The point for me is:
I have my sensor mounted Under my bike pedal, it sends data to my Rpi3 on my bikes handlebar.
My Rpi3 has a Blinkt! hat on it and I want it to respond to my pedling stance.
example:
20-45 Rpm on my pedal/crank -->> Blinkt! goes Red flashing
46-60 Rpm on my pedal/crank -->> Blinkt! goes Green flashing.
60-90 Rpm on my pedal/crank -->> Blinkt! goes Blue flashing

I wish to use it for a Constant stance in biking.

can you please help me out with this?
I Really don't know where y missing link is.

thnx in advance.
Life is not just "good' when you open your eyes, it's Really GOOD when you realize you have another day to LIVE!

Return to “Teaching and learning resources”

Who is online

Users browsing this forum: No registered users and 1 guest