TIme for an overhaul
My original Arduino speedometer was created back in November 2015 and I was very pleased with it at the time. It received a lot of interest via this website and YouTube. However, the perfectionist in me was never happy with how the original version turned out, The construction was a bit hacked together and the code was far from elegant.
The mini shell being away for restoration for such a long time, fast approaching a year as I type, gave me the perfect opportunity to revisit some of my earlier work. It was time for an overhaul.
I am including everything here so you can create your own version of my speedometer. During my research I would often find examples of what I was trying to achieve that were lacking in detail or incomplete. I hope this resource proves useful to someone and saves you some time.
Everything offered here is to be used at your own risk. I do not accept responsibility for any mistakes I might have made that cause you to make the same mistakes.
If there is enough interest I would consider supplying the circuit boards and components in kits so you can create your own. Get in contact if interested.
- Classic looking centre speedometer
- Electronically controlled using a programmable micro controller
- Keep track of miles covered and display them
- Accurate and road legal speed reading
- Choice of speed input; GPS or Frequency
- Professional looking installation using PCB's. Minimal visible wires to connect components
- Safely powered by car battery supply
- Built-in protection for stepper motor
A long time has passed since I created the original version. I've picked up new skills within that period as well as new tools; 3D printer, CNC mini mill to name a few. It was time to make version 3.0!
Taking my design brief into account I decided to do a little research. I quickly stumbled across similar projects using a GPS module as the speed input. These can be purchased inexpensively and an Arduino library exists called TinyGPS to control them. I settled on purchasing a VK2828U7G5LF GPS module that is typically used in drones.
Some testing was conducted and I was quickly able to interface with the GPS module to pickup a speed reading. Success! onto the circuit board design.
I posted a preview of my speedo on the Madd Old Mini's Facebook group. The response was fantastic and a couple of people suggested the option to detect speed using a frequency input. So, that was added back into the design brief.
- GPS and Frequency speed input
- Built-in regulated power supply
- Two part PCB construction
- Mode button to toggle between GPS or Frequency input
- Pulses Per Mile calibration via a toggle button and variable resistor and saved to memory
- Re-purposed original speedo needle
- Almost all components contained within mini speedo housing (GPS module external to improve signal detection and space was limited)
- Odometer saved before power off
- Memory wear levelling implemented to avoid excessive wear of Arduino EEPROM chip (limited to 100,000 writes)
If there is enough interest I will make kits available for purchase so you can build your own. Please get in contact to let me know.
- 1No. Retromini Main Board PCB
- 1No. Retromini Stepper Board PCB
- 1No. Arduino Nano
- 1No. VK2828U7G5LF GPS Module
- 1No. SSH1106 1.3" OLED
- 1No. Switec X27.168 Stepper Motor
- 8No. 1N4148 Schottky Diodes
- 1No. 100k potentiometer (6mm trimmer)
- Regulated Power Supply
- 1No. 1N4002 Diode
- 1No. 1000uF, 25v Capacitor
- 1No. 100uF, 16v Capcitor
- 1No. LM7805 Regulator
- Various wire, shrink wrap, soldering equipment etc....
- Various sizes - Brass PCB stand-offs
- 1No. 3-way SM Connector for Frequency input
- 1No. 2-way SM Connector for Power input
I designed the circuit boards so that they fit inside the mini speedo housing maximising the space available to house all the components. The two boards stack together via jumpers and are secured using brass stand-offs.
The main board features a regulated power supply that can have 12-14v input which will be safely stepped down to 5v to safely power the Arduino, Stepper, GPS module and a speed sensor if utilised.
Two DIP switches are present on the main board along with a potentiometer. They are positioned so they can be accessed from the back of the speedometer via some holes that need to be drilled. The intent here is to avoid having to take everything a part each time an adjustment is required.
The Mode DIP switch toggles between Frequency and GPS speed input. The PPM DIP switch toggles the calibration mode on/off to allow adjustment of the Pulses Per Mile via the potentiometer.
The code has gone through countless iterations to arrive at what I consider to be complete and functioning as desired. I am self-taught software developer so I am sure my code can be refined by someone who know what they are doing!
I will attempt to explain the main functions here. The code is well commented (perhaps too much) so should guide you through how it works.
- FreqCount - Used to measure frequency of input from speed sensor
- TinyGPSPlus - Interface with GPS module
- MicroLCD - Interface with OLED module (I'm now using U8G2LIB in other projects)
- SoftwareSerial - Interface with GPS module
- SwitecX25 - Interface with stepper motor
- EEPROMWearLevel - optimises writing to EEPROM to avoid excessive wear
Lots of variables are used throughout the code. Too many to explain here so please refer to code comments.
- The mode pins are initialised as inputs.
- The GPS module is enabled.
- The frequency count library is enabled
- The EEPROMWear levelling library is enabled
- The stepper motor is zero'd and the needle is swept
- The OLED is enabled
- The Pulses Per Mile calibration routine is called. It is skipped if the mode pin is off
- Distance and Pulses Per Mile are recalled from EEPROM
- The mode pin is checked to toggle between GPS or Frequency input.
- If GPS is selected;
- getgps function called to obtain GPS speed from satellites
- milesPerHour variable is updated with speed obtained from GPS. A 3% buffer is added
- odoMph variable is updated
- Needle position is updated.
Note. my dial reads from 10 - 150mph. I subtract 10mph from the speed to correct the needle position. A variable dialCorrection contains the number of steps equal to 10mph to subtract from the stepper motor movement.
- The odometer is updated every 1 second (1000ms)
- Odometer is displayed if calibration is false and satellites are available.
- "NO GPS SIGNAL" warning displayed if satellite signal is lost
- If Frequency input is selected;
- Frequency of pulse input is counted over 1 second sample period
- Formula converts number of pulses to mph
- Needle position is updated
- Odometer is updated every 1 second
- Odometer values are written to EEPROM everytime speed drops below 3mph and only if the value has changed.
Time for some road tests!
In GPS mode it takes approx 30 seconds for the GPS module to find a satellite signal. This could be an issue if you want to start the car and drive straight away.
I am conducting the tests by having the speedo on my passenger seat in my daily driver. The speed matches the indicated speed on my car speedo through all speed ranges tested.
The assembly was fairly straightforward except for a couple of mistakes I made during the PCB design stage. More below
Before soldering any components. It's a good idea to use the Main board PCB as a drill guide for the holes that need inserting into the speedo housing. I simply laid it inside the housing and used a centre punch to mark the 4x corner mounting holes. These were drilled out to 2.5mm
Next, I laid a piece of paper over the PCB and marked the centre of the two DIP switches and the potentiometer. I then transferred these markings to the speedo housing and drilled out with a 5mm drill bit.
I also added an optional 10mm hole in-line with the USB input on the Arduino so I could have a USB cable connected at all times to allow updating of code without disassembly of the speedo.
It's vital that the stepper diodes are soldered to the PCB on the opposite side to the stepper motor before soldering the stepper motor in place.
I managed to get the connections the wrong way around for OLED. To fix I had to cut the copper tracks and solder two jump wires to the correct locations. I will correct this on the next version of the PCB.
I sized the pads incorrectly for the potentiometer resulting in it being unable to sit flush against the PCB. I will correct this on the next version.
Note. If there is enough interest I will consider doing an assembly YouTube video. Let me know.
Speedo Needle Modification
The original speedo needle needs to be modified so that it will fit the new diameter of the stepper motor shaft. The shaft measures just under 1mm so I located some carbon fibre tubes on eBay that have an ID of .8mm and an OD of 2mm.
The centre of the needle is drilled out with a 2mm drill and then a piece of the carbon tube is bonded in using Araldite. Once the adhesive has cured the carbon tube was cut off flush and sanded smooth.
I happen to have some watch making tools including some broaches so I was able to broach the ID of the carbon tube to perfect fit. The broaches are fairly inexpensive and worth purchasing if you want to achieve a really good fit.
Frequency Input Calibration
If frequency input mode is selected it is necessary to tell the Arduino micro-controller how many pulses per mile are going to be generated in order for the code to calculate the actual speed being travelled.
I have created the calculator below to help determine the number of pulses per mile based on the wheel size and the number of pulses per rotation of a wheel. I am designing my own speed sensor that will pulse 4x per wheel rotation.
The final part of the calculator allows you to select a speed and it will show the frequency of pulses based on the parameters selected. This is useful for testing if you use a frequency generator as the input like I have done. If everything is setup correctly, selecting 71Hz on a frequency generator should move the speedo needle to 60mph. The odometer should also increment 1 mile every 60 seconds.
Note. The tyre size is often found on the sidewall and will look something like 165/70 R10. Those numbers are entered into the calculator below.