Monitor your road speed using the Arduino. This project uses a magnetic switch (also called a reed switch) to measure the speed of one of the bike's wheels.  The Arduino calculates the mph, and send this information out to the LCD screen on the handlebars as you ride.  It is compatible with any kind of bike/wheel, simply enter the radius of the wheel in the firmware to calibrate the device for your setup.

Parts List:

(1x) Arduino Uno REV 3 Radioshack 276-128
(1x) Switch-Magnetic Reed Radioshack 55050593
(1x) 10K Ohm 1/4-Watt Carbon Film Resistor Radioshack #271-1335
(1x) 9V Alkaline Battery Radioshack #23-866
(1x) Heavy-Duty 9V Snap Connectors Radioshack #270-324
(1x) PC Board with Copper Radioshack #276-147
(1x) Parallax 27977-RT Serial Backlit LCD Radioshack 276-120
(x2) SPST PC-Mountable Submini Toggle Switch Radioshack #275-645
(2x) Male Header Pins Jameco 103393
(1x) Female Pin Sockets Jameco 308567

Additional Materials:
22 Gauge Wire Radioshack #278-1224
Solder Radioshack #64-013
sand paper
wood glue
hot glue
zip ties

Download Arduino IDE

Step 1: Schematic

The schematic for this project is shown above.

It consists of three switches:
-one to connect to a 9V power supply
-one to switch the backlight of the LCD on and off
-a magnetic switch (called a reed switch) which closes each time the wheel completes one full rotation.

The Parallex LCD is designed to connect to the arduino using only three pins (ignore the labels and the other pins int his schematic).  One to 5V, one to ground, and a third to serial out (TX)- on the arduino, serial out is digital pin 1.

10kOhm resistors are connected to the reed and backlight switches to prevent excess current between 5V and ground (you should never directly connect 5V and ground on the arduino!)

Step 2: Protoboard

Solder three rows of header pins on the protoboard so that the arduino will snap to it as shown in the images above.

Step 3: Reed Switch

The reed switch is comprised of two pieces, a switch and a magnet. The switch has two wires extending out from it, when a magnet comes near the switch it causes a small mechanical piece to move and close the switch momentarily.

Solder a 10kOhm (current limiting) resistor between A0 and ground on the protoboard. Connect long pieces of stranded wire to A0 and 5V- these wires will wrap around the bike and attach to the reed switch.

Step 4: Mount Reed Switch on Wheel

Secure both the magnet and reed switch to your bike wheel with electrical tape (either wheel is fine).  As shown in the images above, the magnet connects to one of the tire spokes and the reed switch connects to the frame of the bike.  This way, each time the bike wheel turns the magnet moves past the switch. Connect the leads form the reed switch to the long wires from your protoboard (orientation does not matter here- it's just a switch)

Use the code below to test your reed switch. When the magnet on the wheel moves past the switch, the arduino should print ~1023, otherwise it will print ~0. Open the serial monitor (Tools>>Serial Monitor) in Arduino IDE to test for your own setup.  If the magnet does not seem to be affecting the reed switch, try repositioning it or even adding a stronger magnet if you have one.

Step 5: Test Switch

Load the code below onto the Arduino. Turn on the serial monitor. It should output 0.00. Start turning the bike wheel, you should see a print of the current mph each second.

Step 6: LCD

Solder a row of female header sockets on the copper side of the protoboard- three of these will be used to connect to the LCD screen. The LCD should fit nicely on top of the protoboard.

Step 7: Install Parallax LCD Library

Connect Arduino 5V, Ground, and TX (Arduino digital Pin 1) to the LCD socket. Read the labels on the LCD pins to make sure you have everything oriented correctly.

Step 8: Parallax LCD

The underside of the Parallax LCD has two switches and a potentiometer. The pot controls the contrast of the display- you can adjust this to what you like. The switches must be set as they are shown in the image above for proper functioning.

Step 9: Test LCD

Test the following code. For some reason my LCD starts making noise and displaying random characters when I first upload, but works fine once I unplug and reconnect the usb connection. I think this may have something to do will interference from the arduino communicating with the computer via digital pin 1 (TX) during the upload.

The LCD should display "Hello World" when it is turned on.

Step 10: Backlight Switch

Wire a switch as shown in the image above. Connect a 10kOhm resistor and a green wire to one lead, and a red wire to the other.

Connect the red wire to Arduino 5V, the other side of the resistor to ground, and the green wire to D2.

Step 11: Final Speedometer Code

Upload the following code onto the Arduino. Test to make sure the backlight switch works and the speed displays properly.  (Again, you may have to unplug the board after loading the firmware and plug it back in again to get it to work properly.)

Measure the radius of your tire wheel (in inches) and insert it in the line: float radius = ''''';
I used timer interrupts in this piece of code to keep the variable "timer" incrementing at 1kHz.  More info about interrupts and an explanation of how I set it up can be found here.

Step 12: Battery

Wire the battery connector and switch in series as shown in the first image above. Connect the read lead from the switch to Arduino Vin and the black wire from the battery connector to Arduino ground.

Step 13: Enclosure

I cut my project enclosure from 1/4" ply on an epilog 120Watt laser cutter.  The dimensions of the enclosure are 3.5"x4"x2".  I modeled the box in AutoCAD and generated the laser cut files (with finger joints) in Autodesk 123D Make.  Then I added two holes for the switches and a rectangular opening for the LCD screen.  I also added some holes on the bottom of the enclosure to make attaching it to the bike easier.

I glued the project enclosure together with wood glue and sanded the edges down. I finished the enclosure with some clear polycrylic.

Step 14: Install Components in Enclosure

Secure the switches onto the enclosure with nuts. Glue or screw the lcd to the underside of the front panel.
Fit the Arduino and Protoboard as well as the battery into the enclosure and secure with velcro or glue.
Screw or fasten the enclosure shut.

Step 15: Attach to Bike

Wrap the reed switch wires around the bike frame, away from any moving bike parts. I used sugru and some zip ties to attach the speedometer to the handle bars.

Step 16: Take It Out on the Road

You should be ready to hit the road. Don't let the awesomeness of your new bike speedometer distract you from road hazards!
<p>For those asking about the mph calc:</p><p><strong>mph = (56.8*float(circumference))/float(timer);</strong></p><p>"circumference" is measured in inches</p><p>time per revolution of the wheel ("timer") is measured in milliseconds (0.001s)</p><p>miles/hr = 1/(inches per mile) * (miliseconds per hr) * (circumference / timer)</p><p>there are 63360 inches in a mile and 1000*60*60 = 3,600,000 ms in an hr:</p><p>mph = 1/63360*3600000*circumference/timer</p><p>mph = 56.8*circumference/timer</p><p><strong>to do this in km/hr:</strong></p><p>km/hr = 1/(inches per km) * (miliseconds per hr) * (circumference / timer)</p><p>km/hr = 1/39370*3600000*circumference/timer</p><p>km/hr = 91.4*circumference/timer</p>
<p>Instead of using a Parallax LCD, can i use an LCD with a I2C module attached to it?</p><p>Like this one: http://www.ebay.com/itm/IIC-I2C-TWI-SPI-Serial-Interface-Board-Module-Port-for-Arduino-1602LCD-Display-/161245616356?hash=item258afcd8e4:g:nf0AAOSwZQRYgIMA</p>
<p>Instead of using a Parallax LCD, can i use an LCD with a I2C module attached to it?</p><p>Like this one: http://www.ebay.com/itm/IIC-I2C-TWI-SPI-Serial-Interface-Board-Module-Port-for-Arduino-1602LCD-Display-/161245616356?hash=item258afcd8e4:g:nf0AAOSwZQRYgIMA</p>
<p>here's a short video of the installation, to give you a better idea of what it is</p>
<p>Hi, I used this code to use my bike as a light switch (speed higher than 3mph, lights on, lower, lights off). It is an art installation, so the bike is static and a 5v relay acts as a switch for 40 3w led bulbs. Initially it worked fine, but after a while the lights didn't go off when people stopped pedalling. I know nothing about programming and posted this problem on the arduino forum. Tweaked a few things (made the variables in the interrupt volatile and declared the reed pinmode as INPUT_PULLUP. This made the thing more stable, but eventually the error happens anyway. The worst part is I can&acute;t predict whether it will happen after 3 or 6 hours or 2 or 20 users. If any of you guys have ANY clues as to what might be going on here, I'd really appreciate the help- THANKS!!!</p>
<p>hi amanda i will built like yours but i'am using magnetic sensor, can it work? </p>
<p>I modified the Schematic and Sketch for use with 128 x 64 Graphics LCD (with blue Background), I am using it with my Motor Cycle. It is giving good result. Further testing it, And seeking permission from Amanda to upload it as instructable on this site. Image of the final Display is attached. I am currently using it with the reed switch, but I have tested it with hall effect sensor, and it is working perfectly, (a little change will be made in sketch and schematic to use it with hall effect sensor).</p><p>Amanda!!! Can i upload it as instructable on this site?</p>
<p>awesome! yeah go for it!</p>
<p>I'm curious if someone could answer this question for me (outside the OP) I use the code above from Step 11. if my reed makes just 1 contact (1 iteration) the MPH displayed is 47 mph. Even if I slowly move the wheel it is always 47 or 50 mph. Can someone explain why and how I can make it more realistic?</p><p>I noticed in her console outputs that those figures are about what I am getting.</p>
<p> I commented out the first time this line was used and it seemed to fix it.</p><p>reedCounter -= 1;//decrement reedCounter</p><p>I don't think you won't to drop the counter if the reed sensor is closed and the bike is not moving.</p>
gotta say thanks for the great idea and the code. used a 12c lcd, added a smoothing section of the code to average out some of the results. put it on my four wheeler and love it.
<p>Could I use 3 x 7 segment led digits for my read out as these are large (5&quot;) </p>
<p>What things should i change to use it in km/h? And whats that 56.8 in the code?</p>
<p>Hi, have you figured out what 56.8 is? I also want to use it in km/h, but don't have no idea what this is.</p>
<p>Change it to 91.44 for km/h.</p><p>Calculation: 1 inch/second = 2,54 cm/s = 0.09144 km/h = 91.44 inch/ms.</p><p>Or just multiply 56.8 by 1.6090712742981 (= 19.40)</p>
<p>Hi, have you figured out what 56.8 is? I also want to use it in km/h, but don't have no idea what this is.</p>
<p>1 inch/second is 0.0568 mph therefore 1 inch/millisecond = 56.8 mph</p>
<p>Hi Amanda ! I Made it, but I just to know how did you madethe calcul for mph?( </p><p>mph = (56.8*float(circumference))/float(timer);//calculate miles per hour ) ) I don't understand ?!! :(</p><p>And Ihave another question : how can I do if I only want to print RPM on the screen ?</p>
<p>can anyone explain the purpose of the reed counter ? </p>
<p>It is working like a rpm sensor. Every time wheel makes one turn, magnet closes the reed switch and this pulse goes to input pin of arduino. Arduino counts every pulse and convert it to speed with built-in code.</p>
<p>Hi Amanda, very helpful tutorial! Question for you... I'm trying to use this for measuring speed and distance of my son's hamster wheel. And will try to use a light sensor and LED to measure the revolutions of the wheel (no wires for the hamster to chew). For now just testing the code with a pushbutton switch to simulate RPMs. The radius of the wheel is 4.25 inches. With low RPMs (between 1 and 2 revs per second), I get a fixed speed of 15.02mph. Higher revs start to give me fluctuating speeds as expected. When RPMs drop to 0, it shows a speed of 0.002 mph (never 0.00). Any suggestions on how to fix it? Thanks in advance!</p>
<p>A light sensor sends a HIGH signal when there is no light. So, you need to add a &quot;!&quot; somewhere. I think if (!reedVal</p>
<p>Made it, not exactly the same but still working. Great!!</p>
<p>Hello,</p><p>i am workind on something similar, he differences are:</p><p>- i have a line follower sensor on digital pin 2</p><p>- i have a black and white stripe with 20 mm between 2 white stripes</p><p>- i need the output on the serial monitor, and not on the lcd.</p><p>i have put up a sketch, but i have some issues with the time.</p><p>i need to:</p><p>- start the counting every time the pin 2 changes (the sensor has moved) and count the millis until next pin 2 changes, and have the speed. at the end, if the pin 2 does not changes for 1 sec, the program stop's</p><p>can someone help me?</p><p>i have this sketch until now:</p><p>// Constante:</p><p>const int buttonPin = 2; // pinul digital pentru senzorul de linie</p><p>// Variabile:</p><p>int buttonPushCounter = 0; // counter numar impulsuri (1 sau 0)</p><p>int buttonState = 0; // starea actuala a senzorului de linie (1 sau zero)</p><p>int lastButtonState = 0; // starea anterioara a senzorului de linie (1 sau zero)</p><p>long time = 0;</p><p>void setup() {</p><p> // inititalizeaza intrarea pentru senzorul de linie:</p><p> pinMode(buttonPin, INPUT);</p><p> // initializeaza comunicatia seriala:</p><p> Serial.begin(115200);</p><p> Serial.println(&quot;________________________&quot;);</p><p> Serial.println(&quot;Program test&quot;);</p><p> Serial.println(&quot;________________________&quot;);</p><p>}</p><p>void loop() {</p><p> // citeste intrarea senzorului de linie:</p><p> buttonState = digitalRead(buttonPin);</p><p> time = 0; </p><p> // compara starea butonului actuala cu cea anterioara</p><p> if (buttonState != lastButtonState) {</p><p> // if the state has changed, increment the counter</p><p> if (buttonState == HIGH) {</p><p> // if the current state is HIGH then the button</p><p> // wend from off to on:</p><p> buttonPushCounter++;</p><p> time++;</p><p> }</p><p>Serial.print(&quot;Deplasare [mm]: &quot;);</p><p>Serial.println(buttonPushCounter*20);</p><p> Serial.print(&quot;Timp [s]: &quot;);</p><p> time = millis();</p><p> //prints time since program started</p><p> Serial.println(time/1000);</p><p> Serial.print(&quot;Viteza [mm/s]: &quot;);</p><p> Serial.println((buttonPushCounter*20)/(time/1000));</p><p> Serial.println(&quot;________________________&quot;);</p><p> // Delay a little bit to avoid bouncing</p><p> delay(1);</p><p> }</p><p> // save the current state as the last state,</p><p> //for next time through the loop</p><p> lastButtonState = buttonState;</p><p> time = 0;</p><p>}</p>
<p>can anyone explain the purpose of the reed counter and max reed counter? is it the max time for one rotation or something to that effect? </p>
<p>I've tried using this code to measure windspeed on an anemometer for a project of mine. it's a rotating magnet and a reed switch so it's the same principle. The reed test works fine. i've changed the radius (0.87 inches) to fit with my windspeed sensor. However when i upload the code, the serial port view just gives me 0's for MPH for the first reading then a steady steam of 28.21 MPH. Any ideas?</p>
<p>Did you manage to work this out in the end b3nz1? I'm doing similar.</p>
<p>I had the same problem. What i found was that my reed switch was dong one of 3 things; 1.chattering when the magnet was passed over it. To fix this I just increased the maxreedcounter value to 150 or 200ms. The original 100ms wasnt enough to sstop the second switch cycle induced when the switch left the magnetic field. 2. If i passed the magnet too slowly over the switch the switch would stay closed for more then 1 sample cycle, so the maximum speed reading would output. ;so eithur move the magnet faster over the switch or find a mag with a more concentrated field. 3. My first reed switch was normally closed, my own stupitidy there... get one thats n/o. goodluck</p><p>have u found out what that 56.8 value is? im tryna chang the code and lost where that comes from.</p>
<p>hi,have you figured out what the 56.8 value is? I am also doing a similar project, but I want to show the speed in km per hour. I have changed something, but still have no idea what 56.8 is.</p>
<p>Hello Amanda! Im trying to do something similar to your project, but I would like to use a hall effect sensor as it can be used at higher frequencies, how would the code change to accomodate the Hall Effect sensor?</p>
<p>for me the code is not correct. The pulse should be captured when reedVal and reedcounter=maxreedcounter not when reedcounter=0</p>
<p>Hi Amanda, I have a problem with your's code on my stationary bike. Speed calculated by arduino is very low (sth like 1 - 5 km/h max) and I don't know what is wrong :/ I changed only radius for 0.12 m (this is radius of my stationary bike wheel). Is that any problem with fact then my bike have a belt drive ? Something like this electronics.stackexchange.com/questions/140063/measure-the-speed-of-a-stationary-bike-with-belt-drive ? Please help!</p>
<p>A little late, but FYI the wheel size should be in Inches not meters</p>
<p>Hi Amanda</p><p>Great instructable! I'm trying to use the same principles in a slightly different project in which I am importing a library what already uses the Timer1 interrupt - what would be the implications of using Timer 2 as the interrupt in the code to measure the speed of the wheel in terms of accuracy of measurement? And is it simply a case of amending the timer setup to use TCCR2A etc.?</p>
<p>Hello! <br><br>Can anyone share code for this but with classic display? I dont have experience with programming so i need some help. Thanks for helping.</p>
<p>hi</p><p>which other lcd is available to use?</p>
<p>I have a similar code. Initially, I was using the capacitive sensor technique but I realized that it is severely affected by external conditions. I am thinking of using the reed switch. For measuring distances, has anyone faced problems with the reed switch method ?</p>
<p>I have a similar code. Initially, I was using the capacitive sensor technique but I realized that it is severely affected by external conditions. I am thinking of using the reed switch. For measuring distances, has anyone faced problems with the reed switch method ?</p>
<p>I have a similar code. Initially, I was using the capacitive sensor technique but I realized that it is severely affected by external conditions. I am thinking of using the reed switch. For measuring distances, has anyone faced problems with the reed switch method ?</p>
<p>hahaha amazing!! Thanks for sharing!</p>
hello..<br> <br> im using this LCD<br> <a href="http://www.engineersgarage.com/electronic-components/16x2-lcd-module-datasheet" rel="nofollow">http://www.engineersgarage.com/electronic-components/16x2-lcd-module-datasheet</a><br> <br> is there anything i have to modify?
<p>this lcd does not support serial communication, you can get it to work, but you will have to read the datasheet and make some changes to the code.</p>
<p>Could you please help me with the code for this LCD display??? Please (Serial communication 16x2 display) Thank You</p>
<p>See this article:<br>https://www.instructables.com/id/Connecting-an-LCD-to-the-Arduino/</p>
<p>Hi. Can I still use the code for reed if I change the reed switch to hall effect sensor? Because my reed switch can't get accurate mph(double / triple of the actual speed) when the speed is slow</p>
but it does work when it's fast?

About This Instructable




Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei:OTCA Metapixel - Conway's Game of Life "9 Degrees of Freedom" IMU Twitter Controlled Pet Feeder 
Add instructable to: