Introduction: Interfacing Digital Compass (HMC5883L) With Raspberry Pi 2 Using Python3

Initially, I was working on a maze solving robot. Instead of using ultrasonic and infrared on Arduino Mega for wall following like my friends did, I try to do something different using the digital compass and Raspberry Pi 2. This experience is totally new for me as I'm now using Python instead of C++ (well we still have WiringPi which uses C Language) and figuring how Linux system works is not a one day tasks (can't always remember the syntax like "df" and others).

Anyways, I bought the digital compass without considering how I was going to interface it. When I got my RPi2, I was looking everywhere for tutorials. This tutorial is merely a compilation of the tutorials that I used to interface my digital compass. I just thought that it would be a great idea to post in one place where everyone would look for. After all, this is my first post.

This tutorial uses:

1. Raspberry Pi 2 (and whats necessary to power it up, I'm using headless setup on Raspbian)

2. HMC5883L Digital Compass (from electronic flea market)

3. Female to female jumper cables (4 pieces)

4. Your computer (with SSH client program such as "putty")

Step 1: Configuring RPi2

In order to use the RPi2's I2C, we have to first enable it. Boot up and login into the RPi.

Enter the RPi Configuration menu using "sudo raspi-config". Under "Advance Options" you can find "I2C" configuration. Select the option and it will prompt an option to enable or to disable I2C function in RPi2 (which is disabled by default). Select yes when prompted to load I2C kernel module by default. Exit the RPi configuration menu by selecting "Finish".

Returning to the terminal, we will need to modify the file called "modules". Using the text editor program called "nano", we can edit the file under superuser permission. Use, "sudo nano /etc/modules" and add these two lines

i2c-bcm2708#BCM2708 is the family of processors used by RPi, BCM2836 is the specific processor name of the RPi2
i2c-dev

To exit, press "CTRL+X" and select "Y" to save and press Enter to overwrite the previous file. (Actually I don't quite understand why I need to do perform this step since we've already prompted and enable I2C kernel module to load by default. I am still searching for answers, please post in comments if you know)

Step 2: Getting Necessary Libraries and Packages

This step is very straight forward. Just needed some typing skills and an internet connection.

We will need this few packages and raspbian upgrade which is i2c-tools, python-smbus and python3(smbus only works in python3). Type in the following commands in the terminal (everything after "#" symbol is just comments for you to read):

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install i2c-tools
sudo apt-get install python-smbus
sudo apt-get install python3 #if you have the latest Raspbian, python3 should be pre-installed

After getting all the packages, reboot the RPi2 using "sudo reboot"

Then it is time to get the libraries. Among the libraries we will be needing is "quick2wire" and "i2clibraries" for python from Think-Bowl. Make a folder for your project, lets say the folder's name is "project", type in the following commands. (everything after "#" symbol is just comments for you to read)

mkdir ~/project#make a folder named 'project' at ~ (home) directory
cd project#change directory into the 'project folder

git clone https://github.com/quick2wire/quick2wire-python-ap...#get quick2wire from github.com

#if don't have git, try "sudo apt-get install git"

mv ./quick2wire-python-api ./code #renaming the quick2wire library folder to code for tidiness, you can skip this if you prefer keeping it original

nano setup.env#create a setup file, basically to point out where the quick2wire library is situated for your python

after this line, terminal will enter text editing mode, type in these lines

export QUICK2WIRE_API_HOME=~/project/code #change the directory address if different than what i'm using
export PYTHONPATH=$PYTHONPATH:$QUICK2WIRE_API_HOME

after that CTRL+X, Y, ENTER to quit, save and overwrite

back in terminal mode

. ./quick2wire.env#run the environment setup, run this once every time after reboot, running twice will append the address directory

#for checking, use "env |grep quick2wire", address shown must be the same with the directory where you install your quick2wire library

cd code #go into the quick2wire folder, this will be where you put your python code

git clone https://bitbucket.org/thinkbowl/i2clibraries.git #getting library files containing functions for i2c devices such as HMC5883L, ITG-3205, ADXL345 and LCD

Now you can shut it down with "sudo shutdown -h now" so that we can do the wiring

Step 3: Hardware Wiring

The schematic is simple, its not rocket science to wire this baby up.

There are 4 basic connections we need to make, VCC (3.3V), GND, SDA and SCL, colors of the jumpers I used in the pictures are as below

VCC => RED => pin #1
GND => BLACK => pin #6
SDA => WHITE => pin #3
SCL => GREY => pin #5

So the VCC pin of compass connects to pin #1 of RPi2, GND to pin #6, SDA to pin #3 and SCL to pin #5. If you have trouble figuring out which pin on RPi2 is GND, VCC 3.3, SDA and SCL you can refer to the GPIO Pinout for RPi2 model B from Element14.

After connecting the compass, fire up the RPi2 again. To check if the connection is correct, type in:

i2cdetect -y 1 #RPi2 model B uses port 1 i2c, other models may use port 0 of i2c

The result should show a grid with the address '1e' on one of the grid blocks

Step 4: Coding

To test if this works, you can type in this codes in "nano" and name it as whatevernameyouwant.py

from i2clibraries import i2c_hmc5883l

hmc5883l = i2c_hmc5883l.i2c_hmc5883l(1) #choosing which i2c port to use, RPi2 model B uses port 1

hmc5883l.setContinuousMode()

hmc5883l.setDeclination(0,6) #type in the magnetic declination of your location in the bracket (degrees, minute)

print(hmc5883l)

Run the code using "sudo python3 whatevernameyouwant.py". This should output a series of measurement in terms of x, y and z axis and the calculated angle with reference to your true north.

Happy making!


Comments

author
JamesGeddes made it! (author)2017-07-18

*TL;DR*

Solved! Do not purchase PCBs from Amazon! Always purchase from reputable sources that check what they are selling is actually legitimate. I ardently recommend RS Components. This one works.

http://uk.rs-online.com/web/p/interface-developmen...

I used code from Bitify to test.

http://blog.bitify.co.uk/2013/11/connecting-and-calibrating-hmc5883l.html

*Full Story*

I initially purchased what I thought was an HMC5883L from Amazon, but it did not work. I thought I had damaged it during soldering, so purchased another only to get the same results. I spent days trying to get it working, then did some research and found that a knockoff chip had been used. Apparently, it should still have worked, but I did not want to waste any more time. I, therefore, contacted the Amazon seller who immediately apologised and gave me a full refund for both items without asking for a return. I then went to RS and purchased a real HMC5883L. Yes, it did cost a little extra money (not much though), but I would gladly have paid it in the first place if I had known about the difficulties that the fakes would cause. Don't make the same mistake that I did, purchase the real item. Apparently, the fashion industry is not alone in being plagued with forgeries.

2017-07-18 10.16.05LQ.jpg
author
SaiM18 (author)2016-02-23

Traceback (most recent call last):

File "digital_compass.py", line 3, in <module>

hmc5883l = i2c_hmc5883l.i2c_hmc5883l(1)

File "/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py", line 29, in __init__

self.setScale(gauss)

File "/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py", line 76, in setScale

self.setOption(self.ConfigurationRegisterB, self.scale_reg)

File "/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py", line 87, in setOption

self.bus.write_byte(register, options)

File "/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c.py", line 14, in write_byte

writing_bytes(self.addr, *bytes))

File "/home/pi/digital_compass/quick2wire-python-api/quick2wire/i2c.py", line 78, in transaction

ioctl(self.fd, I2C_RDWR, ioctl_arg)

IOError: [Errno 5] Input/output error

Liam getting this error

author
MargaritaK5 (author)SaiM182017-03-26

Hi, I am getting this same error. Did you figure out what was wrong?

author
MargaritaK5 (author)MargaritaK52017-03-26

The i2c detect returns 0d instead of 1e. Then if I cange the hmc = i2c.i2c_hmc58831.i2c_hmc58831(0), I get the error "..../i2c.py line48, in init File not founderror no such file or dir '/dev/i2c-0'

author
JamesGeddes (author)MargaritaK52017-05-26

You may find this thread helpful https://www.raspberrypi.org/forums/viewtopic.php?f...

TL;DR, In short, you (as I) have likely purchased a fake chip. Apparently, it should still work, just on entirely different addresses. Take a look at the actual data sheet for more info. https://github.com/luckypm/commn-informations/blob/master/%E5%9C%B0%E7%A3%81%E6%96%87%E6%A1%A3/%E8%88%AA%E7%BA%AC5983%E6%9B%BF%E4%BB%A3%E6%96%99%E8%B5%84%E6%96%99/QMC5883L%20Datasheet%201.0%20.pdf

author
Bou___bou (author)JamesGeddes2017-06-11

I've played a little bit with the addresses and I'm starting to get something else than zeros.
I'm not sure that values are good, but it's a beginning..
Here is the mods I've made on the code:

import math
from i2clibraries import i2c
from time import *

class i2c_hmc5883l:

ConfigurationRegisterA = 0x09
ConfigurationRegisterB = 0x10
ModeRegister = 0x06
AxisXDataRegisterMSB = 0x01
AxisXDataRegisterLSB = 0x00
AxisZDataRegisterMSB = 0x05
AxisZDataRegisterLSB = 0x04
AxisYDataRegisterMSB = 0x03
AxisYDataRegisterLSB = 0x02
StatusRegister = 0x06
IdentificationRegisterA = 0x10
IdentificationRegisterB = 0x11
IdentificationRegisterC = 0x12


MeasurementContinuous = 0x01
MeasurementSingleShot = 0x03
MeasurementIdle = 0x00

def __init__(self, port, addr=0x0d, gauss=1.3):
self.bus = i2c.i2c(port, addr)

author
JamesGeddes (author)JamesGeddes2017-05-26

This link to the datasheet should actually work http://bit.ly/2qqna3E

author
MargaritaK5 (author)MargaritaK52017-03-26

Only the file named i2c-1 is in the dev folder. Why is there no i2c-0 file? What could be the problem? Can someone help?

author
mexptal (author)MargaritaK52017-04-06

Maybe your sensor is QMC5833 ,the address is 0d, the Register Map is different.

author
MargaritaK5 (author)mexptal2017-04-08

Thanks for the suggestion. It says HMC5883L printed on the compass so I guess it is that. Any other tips to check/lookup? I am still stuck.

author
mexptal (author)MargaritaK52017-04-13

I have the same issue , and I don't think i2clibraries support QMC5833L

I have to read the data sheet of this IC ,and finally get it done. You must read and write the registers yourself . I can send the datasheet to you.

author
houndini (author)mexptal2017-04-25

Hi

I had this problem. I cured it by editing the i2c_hmc5883l.py file in the i2clibraries folder. Change "addr=0x1e" to "addr=0x0d" (approx line 21) and the pi can now interact with the module. However, all my readings are returning zero - anyone have any ideas?

author
DiegoS184 (author)houndini2017-04-27

did you already find a solution for the zeroes in your readings? I have the same problem

author
MargaritaK5 (author)DiegoS1842017-05-02

Diego, any fixes for the zero readings? Maybe the sensor could be faulty? I got mine for kinda cheap.

author
MargaritaK5 (author)houndini2017-04-26

Hi, Yep, I got to that point too of changing the i2c_hmc5883l.py file to include 'addr=0x0d' but I am getting zero readings too. Seems like we have the same problem. Did you figure out something?

author
VineethP1 (author)MargaritaK52017-04-27

I am getting zero readings too. Did you find a fix to solve this?

author
MargaritaK5 (author)VineethP12017-05-02

nope. I`m still stuck on the zero readings. You?

author
SachaB5 (author)VineethP12017-04-30

Same problem here. Any solutions yet?

author
VineethP1 (author)SachaB52017-05-01

I went to the electronics store and bought a MPU 9250 9DOF accelometer, gyroscope and magnetometer. Works perfect!

author
Muhammad UmarA1 (author)2016-10-15

. ./quick2wire.env after that it says no such file or directory

author
rpva81 (author)Muhammad UmarA12017-02-08

Tiny error in the instructable. try './setup.env' instead. You probably need to run 'chmod a+x setup.env' too.

author
asmiantia1 made it! (author)rpva812017-04-14

I can't acces chmod a+x setup.env, can someone help me?

989899.jpg
author
rpva81 (author)asmiantia12017-04-14

This error occurs because the file doesn't exist at this location. Either you are in the wrong folder, or you didn't download the code.

Probably it is in a subfolder of where you are in your example.

If you want to find the file, try "sudo updatedb && locate setup.env" and use common sense.

ps. I don't have access to the RPi where I installed it right now, so i don't know exactly where the file could be.

author
adlfurball (author)rpva812017-02-08

gosh its been so long since ive been here ?? thx rpva81 for helping out these peepz

author
rpva81 (author)2017-02-08

Had 2 problems (solutions mentionted below) but got it working in under 30 minutes. Thanx for making my life easier!

I used a Rpi Zero. This will probably work for the Rpi3 too.

author
adlfurball (author)rpva812017-02-08

I think generally the procedure should be the same. Unless Rpi2, Pi0 and Rpi3 have different processor models..

author
SaiM18 (author)2016-02-23

Traceback (most recent call last):

File "digital_compass.py", line 5, in <module>

print(hmc5883l)

UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in position 62: ordinal not in range(128)

This is the error iam getting now

previously there was soldering problem..

which lead to i/o error

author
adlfurball (author)SaiM182016-02-23

sorry saim18. I have never get this error b4 so I am not able to help u out here. however, heres what u can do. Since Raspbian is linux, maybe u can try askin linux forum for the meaning of the error. Then maybe u can figure out the solution. is that okay? :D

author
SaiM18 (author)adlfurball2016-02-23

Cool, thanks for the response mate.

cheers

author
rpva81 (author)SaiM182017-02-08

I had this problem too. Probably the code from the library has changed a little. Here's a workaround:

Instead of print(hmc5883l) do the following:

(x, y, z) = hmc5883l.getAxes()
print("X: "+str(x))
print("Y: "+str(y))
print("Z: "+str(z))
print("Declanation: "+str(hmc5883l.declinationDeg) + " degrees, " + str(hmc5883l.declinationMin)+" minutes")
(headingDegrees, headingMinutes) = hmc5883l.getHeading()
print("Heading: "+str(headingDegrees) + " degrees, " + str(headingMinutes)+ " minutes")

This will pretty much do the same, but without the non-ascii character...

author
madflower (author)2016-09-24

Worked perfect! I used like a hobby king ublox neo-m8n gps plus
magnometer. It only had the sda, and scl wires on the 4-pin
ardupilot/pixhawk i2c connector for the mag (which i cut off) but it
worked! :)

author
adlfurball (author)madflower2017-01-20

glad it helped.. not really posting anything now, guessed i lost my motivation =(

author
SaiM18 (author)2016-02-22

Iam getting io error

author
adlfurball (author)SaiM182016-02-22

what kind of error?

author
FaisalC (author)2015-11-18

thanks for posting this, working nicely

Curious how did you go on to use this for your Maze solving ?

author
adlfurball (author)FaisalC2016-01-04

I'm sorry for the late reply! :D basically maze solving can have many methods, but by simply adding a magnetometer, the robot has an extra "sense". In my testing, i find that with this extra sense, my robot can have more accurate turning. Eg: a 90degree turn can be accurate to 2 to 3 degrees. It does help the maze solving directly, but it helped keeping the robot properly oriented as motor slips is always an annoying problem.

author
signal3 (author)2015-12-29

Hi tanx , I've tested it ,,,very cool

author
adlfurball (author)signal32016-01-04

Thx, glad to have helped! :D

author
tomatoskins (author)2015-04-26

So cool! Thanks for sharing and welcome to the community!

author
adlfurball (author)tomatoskins2015-04-26

thank you very much! i'd like to keep doing this, but good n creative materials are hard to find these days.. xD

About This Instructable

33,661views

31favorites

License:

Bio: If there is any question for me, write to me via my FB page or email. FB: https://www.facebook.com/adlfurball Email: elys.1993a ...
More by adlfurball:Interfacing Digital Compass (HMC5883L) with Raspberry Pi 2 using Python3
Add instructable to: