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

Raspberry Pi based Speedometer using Hall Effect Sensor

Sat May 21, 2016 11:23 am

Hello again for the third time.
THIS PROJECT REQUIRES A FEW DEPENDENCIES IN ORDER TO WORK PROPERLY.
THE DEPENDENCIES ARE:
-FLASK (MUST INSTALL)-YOU COULD RUN THIS PROJECT WITHOUT ANY PROBLEM WITH JUST FLASK :lol:
-SOCKETIO (OPTIONAL SINCE I'M NOT REALLY USING MUCH SOCKETIO METHOD. I'M STILL USING FLASK SERVER SENT EVENT FOR THE MOST PART)
-PYTHON3
THESE TWO ARE REQUIRED TO HANDLE THE SERVER SENT EVENT AND JAVASCRIPT/JQUERY CODE IN THE HTML CODE! TO MAKE THINGS EASIER, GO TO ADAFRUIT CHANNEL, WATCH A VIDEO BY TONY DI COLA FOR THE INSTALLATION OF ALL DEPENDENCIES.

This time things get real.
I've found the most efficient way of manipulating the pulse obtained from the hall effect sensor (43A547). https://my.rs-online.com/web/p/hall-eff ... s/1811441/

The setup of my project is still the same as it was in my previous post. So to get straight to the point, let me share the 2 codes which would be required for this project.

Image

Image

Video DEMO:
https://www.youtube.com/watch?v=Cz4agPF690Q

Code: Select all

from flask import *
from flask_socketio import SocketIO
import RPi.GPIO as GPIO
import time
import json

app = Flask(__name__)
socketio = SocketIO(app)

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

pulse = 0
distance = 0
rpm = 0.00
speed = 0.00
wheel_c = 2
multiplier = 0
LED0 = 23
LED1 = 24
hall = 18
elapse = 0.00
addme = 0
start = time.time()

GPIO.setup(LED0, GPIO.OUT)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(hall, GPIO.IN, pull_up_down = GPIO.PUD_UP)

@app.route("/")
def index():
        return render_template('speedo.html')

@app.route('/thing')
def thing():
        def read_thing_state():
            while True:
                thing_state = { 'rpm' : get_rpm(),
                                'speed' : get_speed(),
                                'distance' : get_distance(),
                                'elapse' : get_elapse(),
                                'multiplier' : get_multiplier()  }

                yield 'data:{0}\n\n'.format(json.dumps(thing_state))
        return Response(read_thing_state(), mimetype='text/event-stream')


def get_rpm():
    return rpm

def get_speed():
    if speed < 80 :
        GPIO.output(LED0,False)
        GPIO.output(LED1,False)
    if speed < 90 and speed > 80 :
        GPIO.output(LED0,True)
        GPIO.output(LED1,False)
    if speed < 100 and speed > 90 :
        GPIO.output(LED0,True)
        GPIO.output(LED1,True)
    return speed

def get_distance():
    return distance

def get_elapse():
    return elapse

def get_multiplier():
    return multiplier

def get_pulse(number):
    global elapse,distance,start,pulse,speed,rpm,multiplier
    cycle = 0
    pulse+=1
    cycle+=1
    if pulse > 0:
        elapse = time.time() - start
        pulse -=1
    if cycle > 0:
        distance += wheel_c
        cycle -= 1

    multiplier = 3600/elapse
    speed = (wheel_c*multiplier)/1000
    rpm = 1/elapse *60

    start = time.time()

if __name__ == '__main__':
    GPIO.add_event_detect(hall,GPIO.FALLING,callback = get_pulse,bouncetime=20)
    socketio.run(app, host='0.0.0.0', port=9000, debug=True)

Code: Select all

<!doctype html>
<html lang="">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
        <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
        <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.12.0.min.js"><\/script>')</script>

        <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
        <script src="{{ url_for('static', filename='js/Chart.min.js') }}"></script>
        <script src="{{ url_for('static', filename='js/gauge.js') }}"></script>
        <script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
        <script src="{{ url_for('static', filename='fonts/digital-7-mono.ttf') }}"></script>

        <!-- <script src="https://rawgit.com/Mikhus/canv-gauge/master/gauge.min.js"></script> -->

        <!-- Place favicon.ico in the root directory -->
    </head>
    <body>
        <!--[if lt IE 8]>
            <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <!-- Add your site or application content here -->
        <div class="jumbotron">
          <div class="container">
            <h1>SPEED + RPM Meter!</h1>
            <h2>Python + JSON</h2>
          </div>
        </div>

        <div class="container">
            <!-- Example row of columns -->
            <div class="row">

              <div class="col-md-4">

                <canvas id="gauge2" width="300" height="300"
                  data-type="canv-gauge" data-title="RPM" data-min-value="0" data-max-value="1800"
                  data-major-ticks="0 200 400 600 800 1000 1200 1400 1600 1800"
                  data-minor-ticks="100" data-stroke-ticks="true"
                  data-units="RPM" data-value-format="3.2"
                  data-glow="true" data-animation-delay="0.1"
                  data-animation-duration="100"
                  data-animation-fn="bounce"
                  data-colors-needle="#f00 #00f"
                  data-colors-title="#00f"
                  data-highlights="20 30 #eee, 30 60 #ccc, 60 90 #aaa, 90 220 #eaa">
                </canvas>

             </div>

             <div class="col-md-4">

              <canvas id="gauge1" width="350" height="350"
                data-type="canv-gauge" data-title="Speed" data-min-value="0" data-max-value="240"
                data-major-ticks="0 20 40 60 80 100 120 140 160 180 200 220 240"
                data-minor-ticks="10" data-stroke-ticks="true"
                data-units="KM/H" data-value-format="3.2"
                data-glow="true" data-animation-delay="0.1"
                data-animation-duration="100"
                data-animation-fn="bounce"
                data-colors-needle="#f00 #00f"
                data-colors-title="#00f"
                data-highlights="20 30 #eee, 30 60 #ccc, 60 90 #aaa, 90 220 #eaa">
              </canvas>


            </div>

            <div class="col-md-4">

              <h1>RPM: <span class="label label-warning" id='rpm'></h1>
              <h1>KM/H: <span class="label label-danger" id='speed'></h1>
              <h1>DISTANCE: <span class="label label-primary" id='distance'></h1>
              <h1>ELAPSE: <span class="label label-info" id='elapse'></h1>
              <h1>MULTIPLIER: <span class="label label-info" id='multiplier'></h1>



              <!--  {{ 'ON' if switch else 'OFF'}} originally in <h2> above-->

            </div>
          </div>
        </div>

        <script>
                  $(document).ready(function(){

                  function updateThing(thingState){
                    $('#distance').text(thingState.distance)
                    $('#elapse').text(thingState.elapse.toFixed(4))
                    $('#multiplier').text(thingState.multiplier.toFixed(4))

                    $('#rpm').text(thingState.rpm.toFixed(4))
                    $('#speed').text(thingState.speed.toFixed(4))

                  };

                  //set up switch server sent event endpoint !!! these are the final data ready to be sent
                  var thingSource = new EventSource("{{ url_for('thing')}}");
                  thingSource.onmessage = function(e) {
                  var data = $.parseJSON(e.data);
                  updateThing($.parseJSON(e.data));
                  // console.log(e.data);
                  Gauge.Collection.get('gauge1').setValue(data.speed);
                  Gauge.Collection.get('gauge2').setValue(data.rpm);
                }
              });

        </script>
    </body>
</html>
Ok now to the discussion part!

FIRST PART: HARDWARE SETUP

Refer to the picture below.
Image

Ok, thats how simple the setup would be. Just attach a magnet (round/rectangle) at the spoke of the rim with the hall effect sensor being positioned as near as possible to the magnet. Be careful not to put it too near to avoid the magnet hitting the sensor. Then, connect the VCC, GND and Data(Output) of the sensor to the GPIO pins of the Raspberry Pi. VCC will be connected to the +5V and GND to well, GROUND. Data pin can be connected to any GPIO that you would like to use. For my example, I'm using GPIO18.

SECOND PART: MATHEMATICS

The main objective is pretty simple. Every time the magnet passes the sensor, it will produce a pulse signal. The signal is actually a fluctuation in the analog voltage reading from HIGH to LOW or from 3.1V (approx) to 0V. The data pin of hall effect is set to be HIGH all the time (whenever there is no magnet) with the help of Pi's internal pull-up resistor. Whenever the magnet is located directly in front of the sensor, this will trigger the circuit inside the sensor and changes the state of data pin to LOW.
The changes of state at GPIO18 from HIGH to LOW will be used to calculate a variable called "pulse".

The main thing that we need to do here is to figure out how long does it take for the wheel to make one complete rotation. One complete rotation means (look at the figure), as the wheel spin, the magnet will move out of its initial position (at the hall effect sensor) and come back to that same spot after one complete cycle. That will be considered as the value of "1 pulse" in the code. The time it takes to get 1 pulse will be denoted by a variable called "elapse" with a unit of second. The faster the wheel rotates, the smaller the elapse (milli-second) and vice versa.

Elapse variable is the only variable that matters in this code :lol: This is because we will be calculating the RPM and SPEED variable based on the ever-changing (dynamic) elapse timing. The following shows how elapse is obtained.

Code: Select all

def get_pulse(number):
    global pulse,start,elapse
    pulse+=1
    if pulse > 0:
        elapse = time.time() - start
        pulse -=1
        start = time.time()
"get_pulse(number)" is a callback function. This function will get called whenever an interrupt is detected from the changes of states of GPIO18. Oh did I forget to tell you that we are using interrupt? ;) We will be setting up GPIO18 as interrupt pin.

Code: Select all

GPIO.add_event_detect(hall,GPIO.FALLING,callback = get_pulse,bouncetime=20)
"hall" variable is by the way, GPIO18. Interrupt will occur whenever a FALLING edge is detected at the input signal. FALLING here refers to a voltage value that falls from 3.1V to 0V. When interrupt occurs, get_pulse function will be called again and again and again and again! Bouncetime is used to help the GPIO pin ignoring multiple interrupts which happens less than 20ms between the old interrupt trigger and the new trigger. I can't explain it in a better word but this process is called "Debouncing". :roll:

To calculate RPM, its so simple. Just use this formula:
rpm=1/elapse *60
.

So, rpm is equivalent to 1 rotation divided by the time taken for it to complete that one rotation and then multiplied by 60, as 1 minute equals to 60 seconds. For instance, if elapse equals to 1 second, then:
rpm = 1/1*60
rpm=60 round per minute
In math, the lower the value of elapse, the higher RPM would be. And vice versa. Cool?

In order to calculate speed, you need to take out your calculator, get a pen and a paper. We will be doing simple linear equation to create the formula for speed. Just refer to the 2 pictures below. You will get the idea of how it was done! :lol: GOOD LUCK! Any questions? Just throw some replies!

Image

Image

killa
Posts: 1
Joined: Mon Jun 13, 2016 8:58 am

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Mon Jun 13, 2016 9:02 am

hello , im trying to make same thing . is your code open source and available for sharing ;) ? im facing some issu to find this files
<script src="{{ url_for('static', filename='js/Chart.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/gauge.js') }}"></script>
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
<script src="{{ url_for('static', filename='fonts/digital-7-mono.ttf') }}"></script>

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Mon Jun 13, 2016 9:55 pm

killa wrote:hello , im trying to make same thing . is your code open source and available for sharing ;) ? im facing some issu to find this files
<script src="{{ url_for('static', filename='js/Chart.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/gauge.js') }}"></script>
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
<script src="{{ url_for('static', filename='fonts/digital-7-mono.ttf') }}"></script>
Actually you could load the script sources directly from their respective servers. But I'm using 'static' because I wanted to have my Pi loaded all the scripts while offline (not having Internet access).
You need to create a folder named "static" and copy+paste all the js files required into that folder. Then your program could access it. This is how your project folder should look like.

Image

You can download the full project folder here. You could copy and paste the "static" and "template" folder to your own project directory. Or simply run it directly from your downloaded folder.
https://www.dropbox.com/s/y1hyvvrzie94v ... r.zip?dl=0

P/S: actually I've changed my template a little bit. Now I'm no longer using gauge.js and it has been replaced with amcharts.js.
chart.min.js is also not required since I'm not using it too at the moment. But you could leave it loaded in your template in case you wanna plot some fancy graphs using that script source in future.

juliediazin
Posts: 4
Joined: Fri Aug 05, 2016 2:06 pm

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Fri Aug 05, 2016 2:12 pm

Hi,
I am trying to do the same thing, but when i launch the html page, i only get the text, the guages are not showing, any advice?

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Sat Aug 06, 2016 7:31 am

juliediazin wrote:Hi
I am trying to do the same thing, but when i launch the html page, i only get the text, the guages are not showing, any advice?
it might have something to do with ur javascript dependencies such as:
-jQuery.js
-socketio.js
-amcharts.js

did u use the same exact project folder that i've uploaded? if thats the case, there should be no issue in rendering the gauge because everything is there already inside the project folder.
but when i launch the html page, i only get the text, the guages are not showing, any advice?
what did you meant by "launch the html page"?
how did you run your project? i'm assuming that you ran your webpage by running the python script "fast_perfect_clean.py" in your terminal/PuTTY .... right? :?

juliediazin
Posts: 4
Joined: Fri Aug 05, 2016 2:06 pm

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Mon Aug 08, 2016 5:51 pm

Thanks for the reply, I had to start over as due to my fumbling around, the OS crashed. now though, i guess i am being impatient, launch fast_perfect_clean.py using python (rather Dash.py - renamed the file) is not launching the html file. tried mentioning the path of the file in your code (although the html is in the same folder). I am sure i am missing something somewhere. tried updating jQuery.js, socketio.js. no go.

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Tue Aug 09, 2016 2:27 am

juliediazin wrote:Thanks for the reply, I had to start over as due to my fumbling around, the OS crashed. now though, i guess i am being impatient, launch fast_perfect_clean.py using python (rather Dash.py - renamed the file) is not launching the html file. tried mentioning the path of the file in your code (although the html is in the same folder). I am sure i am missing something somewhere. tried updating jQuery.js, socketio.js. no go.
ok i hope you're doing this correctly. i presumed that you're not hoping the webpage to popup automatically after you run the script. :lol:

Step 0: I hope you have installed the "web server modules" required which are Flask and Flask-socketio!
Step 1: You have downloaded the folder at place it anywhere in Pi's home directory. i.e: ~/home/pi/
Step 2: change directory 'cd' into that folder
Step 3: run the python script inside your terminal.
Step 4: open up your web browser and go to your Pi's IP (i'm using 42 as an example) address with port 9000 at the end. i.e: 192.168.0.42:9000
Step 5: you will be able to see the webpage now.

juliediazin
Posts: 4
Joined: Fri Aug 05, 2016 2:06 pm

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Tue Aug 09, 2016 11:36 am

thanks again for the reply, as you can see i am a newbie, :D :oops: but although the webpage is now being loaded using the ip:9000 I still only see the text. I think the problem is with the way i installed amcharts. i followed online instruction and simply extracted amcharts to my project folder. that does not seem right, but cant find any other instructions. :x

juliediazin
Posts: 4
Joined: Fri Aug 05, 2016 2:06 pm

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Thu Aug 11, 2016 3:25 pm

It works!!!! :lol: The issue was with the download i made from your dropbox, I downloaded this on my work (enterprise) network so i guess the amcharts.js file was not downloaded correctly. did it again at home and it works just fine now. corporate security!!! :lol:

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Sat Aug 13, 2016 4:31 am

juliediazin wrote:It works!!!! :lol: The issue was with the download i made from your dropbox, I downloaded this on my work (enterprise) network so i guess the amcharts.js file was not downloaded correctly. did it again at home and it works just fine now. corporate security!!! :lol:
i see. congratz then! now you have the freedom to tinker around the code and proceed with your own version of IoT projects! :lol:

MrBulp
Posts: 11
Joined: Wed Dec 07, 2016 2:45 am

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Wed Dec 07, 2016 2:53 am

hi Yazid... can i have your email please..

thanks

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Wed Dec 07, 2016 5:35 am

MrBulp wrote:hi Yazid... can i have your email please..

thanks
hi mr blurp!
my email : yazidapple13@gmail.com

ashish_sutariya
Posts: 3
Joined: Sun Jun 05, 2016 5:38 am

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Wed May 10, 2017 7:22 pm

can you please show the pin set up and the directory setup for html files also the images that have bees used in the html fike

ashish_sutariya
Posts: 3
Joined: Sun Jun 05, 2016 5:38 am

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Fri May 12, 2017 8:04 am

hey i am not able to open the drop box link it shows crashed could you jst guide me through the dropbox files as i am unable to download them.

ashish_sutariya
Posts: 3
Joined: Sun Jun 05, 2016 5:38 am

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Fri May 12, 2017 9:19 am

anybody can provide me link to the dropbox that works.
The above mentioned link is corrupted and not opening.

User avatar
DougieLawson
Posts: 29790
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Fri May 12, 2017 9:26 am

Try sending an email to the owner of that expired Dropbox stuff.

viewtopic.php?p=1078433#p1078433
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

Since 2012: 1B*5, 2B*2, B+, A+, Zero*2, 3B*3

Please post ALL technical questions on the forum. Do not send private messages.

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Fri May 12, 2017 9:58 am

ashish_sutariya wrote:hey i am not able to open the drop box link it shows crashed could you jst guide me through the dropbox files as i am unable to download them.
sorry the dropbox account is no longer exist. if you really want the project folder i could try to share it again.
but it is such an old project and i'm pretty sure some of the stuff doesn't run properly by now.
especially the HTML page and Flask event.

falent
Posts: 2
Joined: Sat Sep 05, 2015 3:47 pm

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Wed Sep 20, 2017 12:20 pm

hey, is it possible to test your code? Could you please send it to me? Tomasz.patronowicz@gmail.com

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

Re: Raspberry Pi based Speedometer using Hall Effect Sensor

Wed Sep 20, 2017 2:45 pm

falent wrote:
Wed Sep 20, 2017 12:20 pm
hey, is it possible to test your code? Could you please send it to me? Tomasz.patronowicz@gmail.com
Sure, will give you the code once i get a hold of my Pi.

Return to “Teaching and learning resources”

Who is online

Users browsing this forum: No registered users and 2 guests