This is simple Arduino based project to build a module for your car to provide a digital compass heading as well as an internal and external thermometer. Often when I’m driving it is inconvenient to whip out Google Maps to get directions somewhere and a simple compass can be enough to get where I’m going.
The project is based on the HMC5883L 3-Axis Digital Compass IC. This IC module provides low-field magnetic sensing through a digital interface (I2C) doing the conversion with a 12-bit ADC. It is based on the magnetoresistive effect whereby certain materials (in the case of the HMC5883L a patterned strip of nickel-iron) change their resistance in an externally applied magnetic field. The resistive bridge element is excited to produce a corresponding voltage related to magnetic field intensity. One is used for each axis, X Y Z. The PDS indicates it can achieve 1° to 2° compass heading accuracy. While I can’t qualitatively confirm the accuracy, once I got this thing setup and calibrated in my car it worked quite well and was plenty good for any sort of driving navigation.
Since my car also doesn’t have a thermometer, I might as well I’ll throw a couple temperature sensors in it. A 16×2 LCD screen was used as the interface and a rotary encoder for control.
I used a barebones Arduino board with the ATMEGA328P I made but you can use an Arduino Pro Mini or a standard Arduino UNO (although this would require a larger hobby box than in my design).
I used an old phone USB cable for power connection (which is nice as I don’t need a voltage regulator.) I can then just plug it into a 12V to 5V USB cigarette lighter converter for a phone. You could always modify a 12V cigarette lighter instead but make sure you add a 5V regulator to your design.
- Bare bones Arduino board (with crystal oscillator).
- ABS Plastic Hobby Box. I couldn’t find the exact one I used but something like this or this would work.
- Old windshield suction cup phone mount or other mounting method
- 2x DS18B20 Waterproof Temperature Sensors
- 16×2 Backlight LCD 5V
- HMC5883L 3-axis Magnetic Field Sensor Module
- 10kΩ Potentiometer
- Rotary Encoder 18 Pos w/ button
- Wires/Ribbon cables (thinner helps with fitting in the enclosure, I’d say 26AWG is good)
- 2x pullup resistors (4.7kΩ or 10kΩ)
- 0.1uF cap
- Hot glue, super glue, screws and other related hardware for assembly
Important note on pin numbering:
I don’t actually use an Arduino UNO, I use an ATMEGA328P (with crystal oscillator and reset circuit) loaded with the Arduino bootloader (effectively an Arduino UNO) so be aware that the pin numbers used in the above schematic reference the ATMEGA328P pins, however since I’m using the Arduino IDE the pins in the provided code refer to the UNO pinout.
Unfortunately I don’t have many other pictures to walk through the build process but I will highlight the steps I took and some things to consider.
I started with positioning the barebones Arduino board, LCD display, potentiometer and rotary encoder in the enclosure. I used a drill, Dremel and various files to create the void regions for these components as well as fitting the other parts in. Depending on the component I’ll typically try to not permanently fix it to the enclosure (using screws, connectors and such rather then gluing it) which affords some flexibility if things break or you need it for another project. However, since I hopefully use this awhile and have limited space I glued many parts and soldered wiring directly between components without using connectors. I used M3 screws and nuts for the display but elsewhere I just used hot glue, super glue and my barebones Arduino board fit snuggly in the bottom.
When cutting wire or ribbon cable length find a balance in length which doesn’t take up so much room but is long enough to allow you to open the enclosure to work on things while not over stressing the solder connections.
The magnetic sensor should have an axis indicator on the board silkscreen, with X and Y in the board plane and Z perpendicular. Make sure you orient the board in your enclosure such that the XY plane is in the same plane as the ground. I’ve added a feature in the software to allow offset increments of 90° to correct for however you orient it (as long as its laying flat with respect to the ground).
The two temperature sensors are wired in parallel so I cut a small piece of perfboard to solder them to, along with their pull-up resistor, and then soldered them to the main board. I cut the wires on one of the sensors short to hang of the back of the device for internal temp and needed to add some extra length to the to external one.
The USB phone charger cable was cut, retaining the USB Type A connector, and wired to the system. Typically red is 5V and black is GND. For any external wiring of the device (USB, temperature sensors) I will also use a liberal amount of hot glue around the cable connection exiting the enclosure to secure it and not stress the solder connection.
I ripped apart an old car suction cup car phone mount and screwed it to the rear of the enclosure for mounting.
That’s really all to it on the hardware side. What I struggled with was getting it all fitted and wired in the small project box I had; it was a mess in there. I wanted to keep it low profile but getting a slightly larger hobby box may ease assembly, or you could always make your own PCB.
For the external car temperature sensor, I found a convenient place to situate it was in the side paneling above the passenger side front wheel, accessible when the door is opened. This minimized influence of the cabin temperature as well as wind.
If you’re having issues with the magnetic sensor giving weird compass headings, even after calibration, try to place the device as far up on your windshield as possible to further minimize the effects of the engine.
I used code from these libraries for this project:
- Rotary Encoder with Arduino
- Adafruit HMC5883 Unified Library and Compass Header Example
- OneWire and DallasTemperature library for DS18B20 sensors
- LiquidCrystal Library
Code and Libraries:
Menu Features (accessed by pressing the encoder button):
- Change between Degrees C or F
- Heading Offset
- Reset Magnetic Sensor Gain and Offset
- This sets the gain and offset of the compass heading to zero
- Calibrate Magnetic Sensor Gain and Offset
- This commences calibration of the magnetic sensor and will I request that you drive slowly in a tight circle repeatedly until it finishes (so its recommended to find an empty parking lot to do so). Since the measurements taken as you drive in circles are all commonly influenced by the magnetic effects of your vehicles engine they can ideally be compensated out.
- Show Degrees: Display heading in degrees in addition to cardinal directions
You’ll also need to add the magnetic declination of where you live (declaration found in the setup function of the code). This can be determined here, based on your location. Note: I did not add a feature in the interface to allow active change of the magnetic declination so if you go on a long road trip, be aware that there will be an associated error. You can always add a interface feature yourself to allow active adjustment of it.
This is pretty simple build and is great addition to your car if you don’t have one integrated already. It’s always nice to know the temperature and the compass works perfectly well for car navigation. Hope this was helpful and have fun with the build!