The Finished Product
The original goal of the project
One idea of a bike computer seemed like a great way to experiment with the power of an arduino. I could easily program the arduino to calculate a multitude of useful information using the wheel motion as input. I decided to use a sensor at the front fork, that could detect every time the wheel made one rotation. Using those detections and some simple math, it was easy to calculate many useful data values such as: Distance traveled, Speed, and Acceleration. I also included the following features: Trip time, Average trip speed, and the ability to store data for multiple trips. Another included value was the TOTAL distance traveled in the lifetime of the bike (a value that saves data even when turned off using the chip’s flash memory).
Breaking the project up
It became clear early on that This project, although seemingly simple, would require multiple disciplines that were vastly different from each other, and could easily be considered projects of there own. The main breakdown for this, and probably many other arduino projects, was:
This alone included multiple steps and parts. It was probably where most of the time got spent. This included breadboard prototyping, configuring schematics, configuring board layout, board manufacturing, and soldering.
This Was the most fun part for me. Working in a high level language for the arduino, yet knowing that you are controlling individual pins and voltages directly is a powerful thing. Yes, the display board has libraries and functions that do a lot behind the scenes, but most of the work was dealing with inputs/outputs and making calculations.
In this case, I actually mean all hardware other than electronic hardware. This included a attaching a bike mount to the project, mounting the sensor to the fork/spokes, and usually would have necessitated an enclosure, but in this case i got around that.
Step By Step Process (concept to completion):
The main software implications of an arduino odometer seemed simple enough. So one of the first questions became: what to use as a sensor. I didn’t want to buy an expensive part, because that would dilute my bottom up approach, and I realized one of the most basic principles of electricity would provide a cheap and easy solution: Pushing a magnet past an solenoid creates a voltage. I would put a magnet on a wheel spoke, and attach a solenoid to the side of the front fork. Thus every time one wheel rotation is made, the magnet would pass the solenoid, causing a “blip” or voltage transient across its 2 terminals. The terminals would then be wired to the arduino’s analog input where a main software loop would constantly poll the input triggering a set of actions every time a voltage threshold was reached.
I first made a solenoid with a sewing bobbin, wrapped in magnet wire, and tested by swinging the magnet past the solenoid while monitoring the voltage on my friend’s oscilloscope. We were getting voltage spikes of maybe only a millivolt or 2, when I decided to try testing an off-the-shelf 100mH inductor instead of the homemade solenoid. The voltage spikes were much higher. I think they were about 10-20 mV. This made the project even simpler, because you can just buy an inductor for about 20 cents.
When it came to the software portion of the input, I used a polling loop that looked for voltage spikes above a certain threshold. I also applied a capacitor in a low-pass-filter configuration and a pull down resistor (see schematic) to eliminate spurious input. When a blip was triggered, the code would not look for one again for a few milliseconds (to discourage multiple triggers during a pass).
At this point All I had was an arduino, and the one circuit specified, on a breadboard. I was coding the main loop with magnet in hand and I was temporarily monitoring results though a serial out window on my Macbook.
Once I was satisfied with the stability, and accuracy of the main polling loop, I set out to calculate the statistics. Distance was first, simply the total number of blips * wheel circumference. Next came speed: Wheel circumference divided by the time between the last two blips. I did some fancier stuff to take the average of the last few seconds rather than just using immediate data for some of the calculations though. I thought this would improve accuracy and readability slightly.
Then came time to add the display… back to hardware. I pulled up the arduino hitachi display example and began plugging it all in on the breadboard. After successfully uploading the example code, I began copying over the code into my odometer project. Then it was time to display some info o my own, instead of on the computer screen this on the actual display. The hitachi libraries make it easy to display numbers, letters, and symbols, but there’s not much you can do to change the size of the text, or draw pixel by pixel. I’m sure you can do both of these things, but the main problem is the display itself has spaces in its pixel matrix in-between where each symbol pretty much has to go (the space between the dark rectangles on the bottom left exist because there are no pixels here).
I constructed a few different display “modes” in software. One for speed and distance, another for acceleration and trip time, and another for wheel diameter. Then i realized I wanted buttons to switch between the modes, and to change the wheel diameter (for use on different bikes). For the buttons, I chose 3 momentary ones, and I used the interrupt pin to trigger a button press. I’ll get more into the wiring challenges of this later but first I’d like to discuss I problem I came across at this point pertaining to multitasking, which I’m sure is universal to many software challenges.
The Idea of multitasking became quickly apparent with this project because the fundamental polling loop, was set to check the analog input constantly, waiting for a transient. The problem was, that the second I wanted to use the arduino to do any other task, I couldn’t do it. If I took program flow away from the blip monitor, for even 5 milliseconds, I could potentially miss a rotation.
All I can say, is that I have since found solutions to my specific project, which I will lay out, but I still have no real understanding of the subject of multitasking, And any “universal” principles used to tackle these types of challenges, which I’m sure must be very common.
The solution I was able to use was to make all calculations happen right after a blip is triggered, so by the time the wheel comes back around for the second rotation, the calculations have been long since finished, and the main polling loop is back in play.
Next I added the buttons. There were more buttons than interrupt pins, so I attached each button to the same interrupt pin (through a logic gate that essentially caused all three to be “OR”ed with each other), as well as to its own unique digital input. The interrupt would trigger a function, that checked the other 3 inputs to determine which button exactly was pressed. Each button also needed an electrolytic capacitor to filter out noise, and a resistor to preventing floating inputs. The buttons have a little bit of software de-bounce as well.
The next software hurtle was to enable a display of the “total distance” traveled ever on the bike. To do this I needed access to permanent storage (that could store data while turned off) Luckily Arduino’s ATMEGA328 chip has permanent storage. The only problem is, its a little hard to use. Its made to store 4 bit numbers at a time. And I needed a value that could go from .1Mile – 10,000.0 Miles. I had to create a special function that did this. I found this great Arduino chat room where some friendly people helped me out (Connection details – freenode Web IRC). Another notable challenge with this permanent storage is that you have to create some code that sets the value of “total distance” to zero. But then, before you complete the final product, you have to erase that line of code (or it will reset the value to zero every time you turn it on). Lastly under the data specs of the chip, you should not write to this permanent flash storage more than 100,000 times.
Now comes a very Important step that applies to many many arduino projects, switching to just the pre-programmed ATMEGA chip and a battery. There are a few more parts needed to do this, but You don’t want that whole arduino development board. You don’t need the headers, the USB connection, or the power outlet. But what do you need for an arduino to stand alone? Basically everything you need to include for powering the chip with a 9 volt battery is explained here Arduino – Setting up an Arduino on a breadboard. When I got to the USB stuff, I was done because I used the arduino board to program the chip instead of their expensive breakout board. The pieces I had to order online were the 16MHz crystal ($1), a narrow 28 pin socket ($.19) and a boot-loaded ATMEGA328 chip ($3). The rest of these parts were available at Fry’s electronics.
Once I had this breadboard arduino, I just had to incorporate my project so far, with it. Instead of rewiring everything, I went directly to the schematic, including all the connections from both breadboards. When working with the Chip directly it was important to reference the pin layout (seen above), which has a very different numbering scheme than the arduino does.
The next step was to build all of this on a permanent board. I had the choice to use a protoboard, but the wiring was rather extensive and I would have gotten very messy. Therefore I decided to make my own printed circuit board. I did this with the help of a friend using the toner-transfer method. In order to do this, first the board had to be designed, which meant downloading a program called Eagle Cad, and rebuilding the schematic within it (also required importing a specific arduino library to the program). Below is a picture of that digitalized schematic.
Once the schematic is complete. You then set dimensions and place the parts around the board. There is an “autoroute” feature that creates all the traces and pads in a format that can be sent out or printed. To print this board, I bought double sided “copper clad boards” online.
The board layout is printed on glossy paper and then ironed on to the copper board. The toner then transfers to the board.Next the board is dipped in an acid mixture and the copper covering on the board dissolves everywhere the toner in not. The toner is then removed using acetone, revealing the copper traces and pads underneath.The board then had to be drilled using a dremmel tool mounted with a drill press, and tiny (very fragile bits). I had real problems with this method, especial during the ironing step because the toner wasn’t transferring perfectly, and a single hairline break in any trace, makes that trace useless. I would recommend spending slightly more doing the UV copper board method instead.
Next it was time to solder the pieces on. This went pretty well but all the breaks in the traces
caused the finished product not to even turn on. About 6 more hours of debugging and it finally worked!
Mounting and Hardware:
I already explained about the magnet on the wheel and the inductor at the fork of my bike. I glued the wires up toward the handlebars, and put a plug connector at the end which could be attached to the computer board. The computer board had to be mounted securely on the handlebars of my bike, but also be removable for when I left the bike locked up, or in the rain. To do this I used a piece of hardware from an old bike light. It’s a handlebar mount, with a slotted groove. The light would slide into this groove. The next stepped involved some creativity. I put plastic wrap over the slotted grove, and mushed epoxy putty into it. Then once it was starting to harden, I pulled it out, and basically had the detachable slide piece as needed. I removed the plastic wrap, and glued the new piece to the back of my board. It paid off. Now I can mount the board, plug in the inductor, and turn on the switch, and I’m good to go!
The final product has 3 buttons. One that switches between display modes, one that brings you back to the main display mode (for ultra simple use), and one that, when held down for 1.5 seconds, does rarly used tasks (depending on which display you are on). There is info for a trip A and a trip B. holding down the 3rd button resets whichever trip you are viewing. There is a display mode for acceleration and RPMs, and another for wheel diameter. By holding down button three while viewing wheel diameter, you enter a mode where you can change the diameter. There is one display for Lifetime distance. I’ve gotten the bike up to about 26 miles per hour. The distance tracker seems to agree well with google maps.
Issues with the Final Product:
I should have picked a screen that lights up (I know one of the pictures used shows a lit up screen, but mine didn’t have that feature).The device is useless after dusk. I would have loved an e-paper display, they are not yet cheaply available to the hobbyist programmers. Another problem is the position of the main switch. It occasionally can get switched off by my knee while riding. Its rare but On a very long trip, when it gets turned off halfway through, its disappointing because you want to know exactly how far your long journey has been. Granted this has only happened twice ever, and I have since moved the position of the mounting bracket.