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

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

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.setDeclination(0,6) #type in the magnetic declination of your location in the bracket (degrees, minute)


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!

<p>Traceback (most recent call last):</p><p> File &quot;digital_compass.py&quot;, line 3, in &lt;module&gt;</p><p> hmc5883l = i2c_hmc5883l.i2c_hmc5883l(1)</p><p> File &quot;/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py&quot;, line 29, in __init__</p><p> self.setScale(gauss)</p><p> File &quot;/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py&quot;, line 76, in setScale</p><p> self.setOption(self.ConfigurationRegisterB, self.scale_reg)</p><p> File &quot;/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c_hmc5883l.py&quot;, line 87, in setOption</p><p> self.bus.write_byte(register, options)</p><p> File &quot;/home/pi/digital_compass/quick2wire-python-api/i2clibraries/i2c.py&quot;, line 14, in write_byte</p><p> writing_bytes(self.addr, *bytes))</p><p> File &quot;/home/pi/digital_compass/quick2wire-python-api/quick2wire/i2c.py&quot;, line 78, in transaction</p><p> ioctl(self.fd, I2C_RDWR, ioctl_arg)</p><p>IOError: [Errno 5] Input/output error</p><p>Liam getting this error</p>
<p>Hi, I am getting this same error. Did you figure out what was wrong?</p>
The i2c detect returns 0d instead of 1e. Then if I cange the hmc = i2c.i2c_hmc58831.i2c_hmc58831(0), I get the error &quot;..../i2c.py line48, in init File not founderror no such file or dir '/dev/i2c-0'
<p>You may find this thread helpful <a href="https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=184556" rel="nofollow">https://www.raspberrypi.org/forums/viewtopic.php?f...</a></p><p>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</p>
<p>I've played a little bit with the addresses and I'm starting to get something else than zeros. <br>I'm not sure that values are good, but it's a beginning..<br>Here is the mods I've made on the code: <br></p><p>import math<br>from i2clibraries import i2c<br>from time import *<br><br>class i2c_hmc5883l:<br> <br> ConfigurationRegisterA = 0x09<br> ConfigurationRegisterB = 0x10<br> ModeRegister = 0x06<br> AxisXDataRegisterMSB = 0x01<br> AxisXDataRegisterLSB = 0x00<br> AxisZDataRegisterMSB = 0x05<br> AxisZDataRegisterLSB = 0x04<br> AxisYDataRegisterMSB = 0x03<br> AxisYDataRegisterLSB = 0x02<br> StatusRegister = 0x06<br> IdentificationRegisterA = 0x10<br> IdentificationRegisterB = 0x11<br> IdentificationRegisterC = 0x12<br> <br><br> MeasurementContinuous = 0x01<br> MeasurementSingleShot = 0x03<br> MeasurementIdle = 0x00<br> <br> def __init__(self, port, addr=0x0d, gauss=1.3):<br> self.bus = i2c.i2c(port, addr)</p>
<p>This link to the datasheet should actually work http://bit.ly/2qqna3E</p>
<p>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?</p>
Maybe your sensor is QMC5833 ,the address is 0d, the Register Map is different. <br>
<p>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.</p>
<p>I have the same issue , and I don't think i2clibraries support QMC5833L </p><p>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.</p>
<p>Hi</p><p>I had this problem. I cured it by editing the i2c_hmc5883l.py file in the i2clibraries folder. Change &quot;addr=0x1e&quot; to &quot;addr=0x0d&quot; (approx line 21) and the pi can now interact with the module. However, all my readings are returning zero - anyone have any ideas?</p>
<p>did you already find a solution for the zeroes in your readings? I have the same problem</p>
<p>Diego, any fixes for the zero readings? Maybe the sensor could be faulty? I got mine for kinda cheap.</p>
<p>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?</p>
<p>I am getting zero readings too. Did you find a fix to solve this? </p>
<p>nope. I`m still stuck on the zero readings. You?</p>
<p>Same problem here. Any solutions yet?</p>
I went to the electronics store and bought a MPU 9250 9DOF accelometer, gyroscope and magnetometer. Works perfect!
<p>. ./quick2wire.env after that it says no such file or directory</p>
<p>Tiny error in the instructable. try './setup.env' instead. You probably need to run 'chmod a+x setup.env' too.</p>
<p>I can't acces chmod a+x setup.env, can someone help me?</p>
<p>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.</p><p>Probably it is in a subfolder of where you are in your example.</p><p>If you want to find the file, try &quot;sudo updatedb &amp;&amp; locate setup.env&quot; and use common sense.</p><p>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.</p>
gosh its been so long since ive been here ?? thx rpva81 for helping out these peepz
<p>Had 2 problems (solutions mentionted below) but got it working in under 30 minutes. Thanx for making my life easier!</p><p>I used a Rpi Zero. This will probably work for the Rpi3 too.</p>
I think generally the procedure should be the same. Unless Rpi2, Pi0 and Rpi3 have different processor models..
<p>Traceback (most recent call last):</p><p> File &quot;digital_compass.py&quot;, line 5, in &lt;module&gt;</p><p> print(hmc5883l)</p><p>UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in position 62: ordinal not in range(128)</p><p>This is the error iam getting now </p><p>previously there was soldering problem..</p><p>which lead to i/o error</p>
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
<p>Cool, thanks for the response mate.</p><p>cheers</p>
<p>I had this problem too. Probably the code from the library has changed a little. Here's a workaround:</p><p>Instead of print(hmc5883l) do the following:</p><blockquote>(x, y, z) = hmc5883l.getAxes()<br>print(&quot;X: &quot;+str(x))<br>print(&quot;Y: &quot;+str(y))<br>print(&quot;Z: &quot;+str(z))<br>print(&quot;Declanation: &quot;+str(hmc5883l.declinationDeg) + &quot; degrees, &quot; + str(hmc5883l.declinationMin)+&quot; minutes&quot;)<br>(headingDegrees, headingMinutes) = hmc5883l.getHeading()<br>print(&quot;Heading: &quot;+str(headingDegrees) + &quot; degrees, &quot; + str(headingMinutes)+ &quot; minutes&quot;)</blockquote><p>This will pretty much do the same, but without the non-ascii character...</p>
<p>Worked perfect! I used like a hobby king ublox neo-m8n gps plus <br>magnometer. It only had the sda, and scl wires on the 4-pin <br>ardupilot/pixhawk i2c connector for the mag (which i cut off) but it <br>worked! :)</p>
glad it helped.. not really posting anything now, guessed i lost my motivation =(
<p>Iam getting io error</p>
<p>what kind of error?</p>
<p>thanks for posting this, working nicely </p><p>Curious how did you go on to use this for your Maze solving ?</p>
<p>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 &quot;sense&quot;. 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. </p>
<p>Hi tanx , I've tested it ,,,very cool</p>
<p>Thx, glad to have helped! :D</p>
<p>So cool! Thanks for sharing and welcome to the community!</p>
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




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: