Speedometer project
I am on my college’s SAE Mini-Baja team. I really like it, even though I don’t know too much about car design. Building shit that moves is so righteous. I f you don’t know, a Baja car is a single passenger car designed for offroading. It gets its name from the Baja rally in Mexico, where a number of vehicles of all types race across really rough terain in the desert. We don’t go down to Mexico, but we do go to SAE competitions around the country, usually one per year. Some competitions emphasize rock crawling, some flotation. We usually go to the East one, which has a water component, for which the car has to not only float, but propel itself through water, which is pretty cool. This year we are going west to Oregon, for a more hill climbing, possibly rock crawling experience.
I have been tasked with building a sweet speedometer. My basic plan is to build the main function (sensing how quickly the rear wheels are turning) with an Arduino, a reed switch and some magnets on the sprocket. Output will be to three 7-segment LED displays, probably using either a 7-segment driver or LED driver. Then, provided that that goes well, record the time of each magnet trigger onto some kind of external storage device. Provided all of that goes well, I would like to add a lap button, to let the driver try to record laps as well. If all of that goes well, then I’d also like to have a 2 line LCD inside the cockpit giving average lap time.
So I think that this is my overall pseudocode for the ideal realization of the project. Don’t worry about millis() overflowing; that takes 49.7 days.
setup
Constantly check for interrupts on the reed switch pin
Ditto lap button
loop
use mayfly loop to check the logging button as I may have used all my interrupts.
another mayfly loop for the lap button
Interrupt block for the reed switch:
current millis() minus last millis() is elapsedTime.
tireCircumpherence/numMagnets/ellapsedTime is speed
send current millis() to storage if logging is true
half or one or two second block
send speed to LED displays
currentLapTime = millis() - lastLapTime
write the current lap time to the lcd display
if it hasn't detected the reed switch in the second, set speed to zero
lap button block
write some code indicating a lap has passed to the storage
make the lastLapTime equal to the current millis()
increment the lapNumber
averageLapTime = lastLapTime/lapNumber
write the average lap time to the display
This is all subject to change, of course. I need to get the speed accurate first; I think a photodetector (aka slot sensor) across the brake disk might be better. The brake disk has evenly space vent holes, meaning that there is an equal amount of steel and space in there. That means I can trigger the interrupt on change across the slot sensor. Disadvantage is if there is any prospect of mud getting in there. The brake disc is on the main frame, and not at the end of a suspension component, so the wiring is basically the same as having magnets on the sprocket.
The storage is pretty huge; I don’t know if I’ll be able to figure out writing to some kind of memory card, which this would definitely need. And if we do that, I think I’ll want to use text, not raw hex, as text lets me indicate laps pretty easily and visually debug lines with errors. On the other hand, maybe it won’t be so bad if each line is really well structured, i.e. 4 bytes for each datapoint, with 0xFACEBEEF or some other very high control code to indicate a lap is done.
Interface is sort of an issue. If I want to use 7 segment drivers, I will need 4 bits per digit, as I think they use BCD. I think I want to have a decimal for speed, because hey, why not, right? So that will mean 12 pins, which is impossible. Instead, I will have to use a shift register to output 12 bits to the 7-segment drivers. If I do that, I might not even need the 7-segment drivers. What I maybe will need is one big set of AND gates, one gate per LED on the speed display. This is to make sure that the LEDs aren’t turned on while they are being written to over serial, as the flashing could be distracting to the driver. The top left line on the leftmost 7-segment is never lit, but the decimal point on the middle one is, so that’s 21 AND gates, meaning six 7408s. However, since all of these AND gates share an input, I can maybe use a transistor instead, albeit one that can handle a not insignificant amount of current. OK never mind, LED drivers have an Enable Output pin that does exactly that. I can even use PWM with it. It also needs 4 pins, because it sends the data from the shift register to internal storage using the Strobe pin.
The other thing is the number of interrupts; the Arduino language does not have a pretty way of setting up timer interrupts, so that’s annoying to make that play nice between stuff written at the Arduino level, and stuff written in AVR C, a similar but slightly shaggier beast. The only critical (as in timing) interrupt is the one sensing the wheel speed. Everything else is pretty loose, as button presses are rather long, and the second is not really used for any critical timekeeping.
So my current tally is:
- 1 pin for serial display (TX, which is digital pin 1)
- 4 pins for Speed display
- 1 pin with interrupt for speed sensor (photogate or hall effect or reed switch)
- 1 pin with or without interrupt for logging button
- 1 pin with interrupt for lap counter
- 4 pins for interface with SD card
- external interrupts
- time interrupts
- logging to an SD card
- interface with a serial LCD display
- serial LED interface
And my parts list:
- 4 × 4794 LED Driver
- 1 × Sparkfun Serial LCD module
- 1 × Arduino Duemilanove
- 1 × Secure Digital Socket
- 4 × 2 Pin Screw Terminals
- 22 × 100Ω Resistors for LEDs
- 3 × 1.8kΩ Resistors for SD card voltage divider
- 3 × 3.3kΩ Resistors for SD card voltage divider
- 3 × 7 Segment LED display
- 2 × Push button for logging
- 1 × LED to indicate logging
- 1 × Optical Slot or Reed Switch
