A compass is an invaluable orientation aid, especially when you’re traveling by foot or bicycle. Some smartphones and navigation systems do not have built-in compasses, so they can determine direction only if you move fairly quickly. Old-fashioned hiking or cycling maps also still have their place, since they provide a much better overview than any display. Accordingly, the author went looking for a robust compass, and it quickly became clear that what he wanted was an electronic model — and of course, of his own design. The implementation of this sort of project is simplified by the fact that compass models with simple interfaces are available commercially. The author decided on a module with the designation HDMM01, which can be obtained from Pollin Electronic .
It incorporates a type MMC2120MG two-axis magnetic field sensor from Memsic. All you need to do is provide the module with a 5 V supply voltage, and you can read out the compass data from a two-pin I²C port (most easily done with a microcontroller). The compass circuit is built around an ATtiny84, which communicates with the compass module over the I²C bus. The two pull-up resistors R5 and R6 have standard values. The circuit can be powered from a 9 V battery, among other options. The voltage regulator reduces the input voltage to 5 V. The compass direction is indicated by a set of 16 LEDs, divided into in four groups of four LEDs each. The cathodes of the LEDs in each group are connected together, and the common cathode lead is connected to a port pin via a series resistor. Sets of four LED anodes are also connected to common port pins. If suitable signals are generated on the port pins, only one LED at a time will be lit, and this arrangement needs only eight port pins instead of sixteen.
The intelligence of the circuit is vested in the microcontroller firmware, starting with the I²C interface. This is necessary because the ATtiny84 does not have a hardware I²C interface (which Atmel calls ‘Two Wire Interface’ or TWI), but instead only a ‘Universal Serial Interface’ (USI). The I²C functionality must, therefore, be emulated using the USI, in the manner described in an Atmel application note . The compass module supplies the X and Y components of the magnetic field assigned numbers. The corresponding quadrant can be determined from the signs of the numbers, and the angle within the quadrant can be obtained using the expression Angle = arctan(abs(Y/X)), where the function abs() returns the absolute value of the quotient of Y and X. The average values of X and Y are calculated from a set of eight samples in an endless loop in the main routine of the firmware and are used to compute the angle.
From this the LED that points to the north can be determined. To allow the direction to be indicated with sufficient precision, the LEDs should be arranged in a circle with equal spacing and in the same sequence as shown on the schematic diagram. LED D1 must be aligned to the top edge of the module (oriented so that the IC marking can be read normally). For best results, you should use another compass to calibrate the assembly and adjust the orientation of the module (connected to the circuit by loose wires) accordingly. Then secure the module to the PCB with a drop of heat-melt glue. The firmware (source code for WinAVR and hex code) can be downloaded from the Elektor website. The main routine is contained in the file tiny_compass.c; the routine USI_TWI_Master.c handles I²C communication and the routine led_driver.c drives the LEDs. The microcontroller can be programmed directly on the PCB via connector K1. The fuse bits must be configured as follows: EXT = 0xFF, HIGH = 0xDF, LOW = 0xE2. If you don’t want to program the microcontroller yourself, you can buy a pre-programmed device from the Elektor Shop  (order number 120045-41).