Measuring the speed/rpm of a Vehicle or a motor has always been a fascinating project for us to try. So, in this project we are going to build one using the Industrial ready PIC microcontrollers. We will use a piece of magnet and a Hall Sensor to measure the speed. There are other ways/sensors to measure the speed but, using a hall sensor is cheap and also can be used on any type of motor/Vehicle. By doing this project we will also enhance our skills in learning PIC16F877A since the project involves the use of Interrupts and Timers. At, the end of this project you will be able to calculate the speed and distances covered by any rotating object and display them on a 16x2 LCD screen. Lets start with this Digital Speedometer and Odometer Circuit with PIC.
Materials Required:
- PIC16F877A
- 7805 Voltage Regulator
- Hall Effect Sensor (US1881/04E)
- 16*2 LCD display
- A small piece of magnet
- Connecting wires
- Capacitors
- Breadboard.
- Power supply
Calculating Speed and Distance Covered:
Before we actually start building the circuit, let us understand how we will be using a Hall sensor and a magnet to calculate the speed of a wheel. Previously we have used same Technique to build Arduino Speedometer which displays readings on Android Smart Phone.
A Hall sensor is a device which can detect the presence of a magnet based on its polarity. We stick a small piece of magnet on the wheel and place the hall sensor near it in such a way that every time the wheel rotates the hall sensor detects it. We then use the help of timers and Interrupts on our PIC Microcontroller to calculate the time taken for one complete rotation of the wheel.
Once the time taken is known we can calculate the RPM by using the below formulae, Where 1000/time taken will give us the RPS and further multiplying it with 60 will give you the RPM
rpm = (1000/timetaken) * 60;
Where (1000/timetaken) gives the rps (Revolutions per second) and it is multiplied by 60 to convert rps to rpm (Revolutions per minute).
Now to calculate the velocity of the vehicle we have to know the radius of the wheel. In our project we have used a small toy wheel which has a radius of just 3cm. But, we assumed the radius of wheel is to be 30cm (0.3m) so that we can visualize the readings.
The value is also multiplied with 0.37699 since we know that Velocity = (RPM (diameter * Pi) / 60). The formulae is simplified down to
v= radius_of_wheel * rpm * 0.37699;
Once we calculate the velocity we can also calculate the distance covered by using a similar method. With our Hall and magnet arrangement we know that how many times the wheel have rotated. We also know the radius of the wheel, using which we can find the circumference of the wheel, assuming the radius of the wheel to be 0.3m(R) the values of circumference Pi*R*R will be 0.2827. This means that for every time the hall sensor meets the magnet a distance of 0.2827 meters is covered by the wheel.
Distance_covered = distance_covered + circumference_of_the_circle
Since, now we know how this project will work lets proceed to our circuit diagram and start building it.
Circuit Diagram and Hardware Setup:
The Circuit Diagram of this Speedometer and Odometer Project is very simple and can be built on a breadboard. If you have been following the PIC tutorials then you can also reuse the hardware that we used for learning PIC microcontrollers. Here we have used the same perf Board which we have built for LED Blinking with PIC Microcontroller, as shown below:
The pin connections for the PIC16F877A MCU are given in the table below.
S.No: |
Pin Number |
Pin Name |
Connected to |
1 |
21 |
RD2 |
RS of LCD |
2 |
22 |
RD3 |
E of LCD |
3 |
27 |
RD4 |
D4 of LCD |
4 |
28 |
RD5 |
D5 of LCD |
5 |
29 |
RD6 |
D6 of LCD |
6 |
30 |
RD7 |
D7 of LCD |
7 |
33 |
RB0/INT |
3rd pin of Hall sensor |
Once you build your project it should look something like this in the picture below
As you can see I have used two boxes to place the Motor and a hall sensor in nearby position. You can fix the magnet on your rotating object and intact the hall sensor close to it in such a way that it can detect the magnet.
Note: Hall sensor have polarities, so make sure which pole it is detecting and place it accordingly.
Also make sure you use a Pull-up resistor with the output pin of the hall sensor.
Simulation:
The Simulation for this project is done using Proteus. Since the project involves moving objects it is not possible to demonstrate the complete project using simulation but the working of the LCD can be verified. Simply load the hex file to the Simulation and simulate it. You will be able to notice the LCD working as shown below.
To check of the speedometer and odometer are working I have replaced the Hall sensor with a Logic state device. During the simulation you can click on the logic state button to trigger the Interrupt and check if the speed and distance covered is getting updated as shown above.
Programming your PIC16F877A:
As said earlier we will be using the help of timers and interrupts in the PIC16F877A Microcontroller to calculate the time taken for one complete rotation of the wheel. We have already learnt how to use Timers in our pervious tutorial. I have given the complete code of the project at the end of this article. Further I have explained few important lines below.
The below lines of code initializes the Port D as output pins for LCD interfacing and RB0 as input pin for using it as external Pin. Further we have enabled internal pull-up resistor using the OPTION_REG and have also set 64 as presale. WE then Enable Global and Peripheral Interrupt to enable Timer and External Interrupt. To define RB0 as external interrupt bit INTE should be made high. The Overflow is value is set to be 100 so that for every 1 millisecond the timer interrupt flag TMR0IF will be triggered. This will help to run a millisecond timer to determine the time taken in millisecond:
TRISD = 0x00; //PORTD declared as output for interfacing LCD TRISB0 = 1; //DEfine the RB0 pin as input to use as interrupt pin OPTION_REG = 0b00000101; // Timer0 64 as prescalar // Also Enables PULL UPs TMR0=100; // Load the time value for 1ms; delayValue can be between 0-256 only TMR0IE=1; //Enable timer interrupt bit in PIE1 register GIE=1; //Enable Global Interrupt PEIE=1; //Enable the Peripheral Interrupt INTE = 1; //Enable RB0 as external Interrupt pin
The below function will get executed each time an Interrupt is detected. We can name the function as per our wish so I have named it as speed_isr(). This program deals with two interrupts one is Timer Interrupt and the other is External Interrupt. Whenever a Timer Interrupt occurs the flag TMR0IF goes high, to clear and reset the interrupt we have to make it low by defining TMR0IF=0 as shown in code below.
void interrupt speed_isr() { if(TMR0IF==1) // Timer has overflown { TMR0IF=0; // Clear timer interrupt flag milli_sec++; } if (INTF==1) { rpm = (1000/milli_sec) * 60; speed = 0.3 * rpm * 0.37699; // (Assuming the wheel radius to be 30cm) INTF = 0; // clear the interrupt flag milli_sec=0; distance= distance+028.2; } }
Similarly when External Interrupt occurs the flag INTF will go high, this also should be cleared by defining INTF=0. The time taken is kept in track by the Timer Interrupt and the External Interrupt determines when the wheel has completed one full rotation. With this data the speed and distance covered by the wheel is calculated during every external Interrupt.
Once the speed and distance is calculated they can be simply displayed on the LCD screen using our LCD functions. If you are new to LCDs then refer our interfacing LCD with PIC16F877A MCU tutorial.
Working Explanation:
After you get the Hardware and software ready, simply upload the code to your PIC16F877A. If you are completely new to PIC then you should have to read few tutorials on knowing how to upload the program to a PIC16F877A Microcontroller.
I have used a variable POT to adjust the Speed of the Motor for demonstration purpose. You can also use the same of find a real time application. If everything works as expected then you should be able to get the Velocity in Km/Hr and Distance covered in terms of meters as shown in the Video below.
Hope you enjoyed the project and got it working. If not you can use the comment section below or the forum to post your doubt.
Comments
Aug 21, 2017
there is some error in the code .... iam not getting the output.. pls kindly help me
Aug 21, 2017
Hi amirt,
I just compiled the code and dint find any error. What kind of error are you getting. I will be able to help only if I know what error you are facing.
Dec 11, 2017
Can you please give me the hex code of your c file
Mar 15, 2018
did u get the hex file
Jan 25, 2018
16f1946 circuit diagram and data in or data out pin number and mamory flash system
Jan 28, 2018
Hey Ashwin, I was wondering if this project is viable in real life application or not. because there we have tire is connected to bike with iron type material instead of plastic material.
Jan 30, 2018
Yes its very much possible to use this in real time. I have seen this concept being used in cycles speedometer kits. You can also buy one from ebay. I am sure it would also work for a bike be it plastic or metal
Feb 15, 2018
before thanks you for the project we have given us completly.now i wish if it is possible having the code in asm .thank you
Feb 19, 2018
The distance covered is calculated using circumference whose formula is 2*pi*r not pi*r*r therefore the disance covered should be 1.884m
Mar 26, 2018
Does this project works? I'm at last stage of submissions. Can i go for this project ? Reply asap plz
Mar 29, 2018
Which power supply is needed ? 5v or 12v ?
Apr 10, 2018
I want to edit the program but I can not create an old hex file
It shows me a line in (#include <xc.h>) where this file exists
If you delete it, the error appears at d4
Note that I use the micr c of Virgin 6.6.1. I also tried the hex file on the simulation program and it works well but the distance is up to 998 and starting from the first, what is the solution to make the distance meter reach more than this and how can I keep it With this value even after the power outage and when the operation again follows the count after the last number
thank you very much
Apr 15, 2018
Please use MPLAPX with XC8 compiler. You cannot use mickroC with this program
Apr 12, 2018
can you please compile once more the program,as there are errors in the lcd fuctions and interrupt fuctions
Apr 15, 2018
sir can I ask why rpm = (1000/milli_sec) * 60; what (1000) stands for. Can i use this algorithm to calculate speed in the interrupt: SPEED=(3600*2*PI*0.3)/milli_sec; /////0.3m radius, 3600 to exchange m/ms to km/h
Apr 15, 2018
Haii aswinth
Iam USING mplabx v3.35& xc8 compiler v1.45
Iam getting so many errors regarding LCD commands&
int c1,c2,c3,int distance,int d1,int d2,int d3
I checked all ur tutorials interfacing LCD,
In that no code is bulid without errors.
Could you please give me any suggestions to overcome all errors.
Errors are appearing as
->Warning:(373 ) implicit signed to unsigned conversion
->Arithmetic overflow in constant expression
->Illegal conversion between pointer variables
Apr 22, 2018
can i get the hex file ..plz.its urgent
Apr 26, 2018
Velocity = (RPM (diameter * Pi) / 60)
how the value 0.37699 is obtained if, v = (RPM * 2R * 3.14) / 60
= RPM * R * 0.104
Apr 27, 2018
Can i get the hex file please
Jun 13, 2018
frequency please? at what frequency microcontroller will run the hex file?
Jun 18, 2018
it runs on 20MHz
Sep 08, 2018
How the value 0.37699 obtained? and why RPM is (1000/TT)*60 what this 1000 means or stands for?
Sep 12, 2018
Velocity = (RPM (diameter * Pi) / 60)
how the value 0.37699 is obtained if, v = (RPM * 2R * 3.14) / 60
= RPM * R * 0.104 m/s
= RPM * R * 0.376 km/hr
Oct 26, 2018
please hex file
May 27, 2019
Can you please provide a mikroC code or hex file of this code.
MikroC code would be preferred.
Thank You
Jul 13, 2019
sir,how i make a digital speedmetter circuit without using ardiuno or mcu