Programming I2C Digital Compass

For Flowcode users to discuss projects, flowcharts, and any other issues related to Flowcode 5.
To post in this forum you must have a registered copy of Flowcode 5 or higher.

Moderator: Benj

Post Reply
airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Programming I2C Digital Compass

Post by airforcejeesh »

I am trying to program an HMC5883L 3-Axis Digital Compass IC** on the 16F887. There are several hurdles that I haven't figured out how to code, but it's also possible I'm not even looking in the right direction. Guidance on any step would be appriciated.

First, I don't understand how to convert the six sensor readings (MSB & LSB for X, Y, & Z axes). After the "recieve byte" read macro is sent, the instructions say to "Convert three 16-bit 2’s compliment hex values to decimal values and assign to X, Z, Y, respectively."

This confuses me. Do I make the return output a variable? If so, how do I assign a variable to "X,Z,Y". What exactly is "X,Z,Y" I am confident the answer involves using the registers, but the instructions don't explain this (at least not at my level), and I am not sure what to do. I do know that each axis letter has two registers assigned to it, if that helps.

Also, I have hit a wall on converting the hex values to decimal values. I have a working hex-to-decimal macro, but it only takes strings, and the reading only produces bytes. My first solution was to try the "ToString$()" function, but it won't work. Any ideas on how to convert to decimals here?

To illustrate my sitution, I've added the relavant instrution from the manuel and part of my flowcode to compare it. Again, deep thanks for any assistance.

**PDF: http://dlnmh9ip6v2uc.cloudfront.net/dat ... 3L-FDS.pdf
Below is an example of a (power-on) initialization process for “single-measurement mode”:
1. Write CRA (00) – send 0x3C 0x00 0x70 (8-average, 15 Hz default or any other rate, normal measurement)
2. Write CRB (01) – send 0x3C 0x01 0xA0 (Gain=5, or any other desired gain)
3. For each measurement query:
Write Mode (02) – send 0x3C 0x02 0x01 (Single-measurement mode)
Wait 6 ms or monitor status register or DRDY hardware interrupt pin
Send 0x3D 0x06 (Read all 6 bytes. If gain is changed then this data set is using previous gain)
Convert three 16-bit 2’s compliment hex values to decimal values and assign to X, Z, Y, respectively.
Attachments
I2C compass code.fcf
The part of my project where I try to read the compass.
(258.64 KiB) Downloaded 527 times

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: Programming I2C Digital Compass

Post by Benj »

Hello,

I've had a quick go at sorting things out for you.

I have made three macros,

WriteReg - Writes a byte to a register
ReadReg - Reads a byte from a register
ReadX - Reads the X registers and combines into a 16-bit variable

The LCD print number function takes the 16-bit number and prints out as decimal for you. You will need to re-do the init process but the WriteReg macro should make this very easy.
Attachments
I2C compass code.fcf
(264.94 KiB) Downloaded 537 times

airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Re: Programming I2C Digital Compass

Post by airforcejeesh »

Thanks for the help, Benj.

I tried your suggestion, and in the simulation, X equaled a 32-bit row of F's (I assume FlowCode always simulates sensor readings with 0xFF). I'm not sure how to use this information. My end goal is to get the compass to display a simple decimal reading on a four-digit 7seg display. I only need one axis of rotation for this. Do you know how I can parse a 32-bit hex value into a heading I can use?

I tried a few variations on my code, but I could only get it to answer FFFF repeated.
Attachments
I2C compass code2d.fcf
(268.28 KiB) Downloaded 479 times

airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Re: Programming I2C Digital Compass

Post by airforcejeesh »

Benj, I worked at it more and I think I've narrowed down my problems to this :where does WriteReg go? Is it before, after, or inside ReadX()? Also, what do I fill in for its value and address perimeters? None of the obvious variations I've tried work.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: Programming I2C Digital Compass

Post by Benj »

Hello,

I've added the initialise code and a loop to take the X reading and show it on a LCD. If you can do this then splitting it up and showing on 7-segs should be easy.

Your config settings don't seem to match your clock speed. You have selected the internal RC oscillator which by default is 4MHz on the 16F887.
Attachments
I2C compass code.fcf
(266.44 KiB) Downloaded 470 times

airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Re: Programming I2C Digital Compass

Post by airforcejeesh »

Thank you very much Benj. It works great. I can take it from here.

BTW, what does adding a period before a variable do? I see it in your code a few times but I can't find that on any of the command lists online.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: Programming I2C Digital Compass

Post by Benj »

Hello,

That's great glad your all up and running now.

A .variable is a local variable or parameter and so only exists for the macro your currently in. Just a nice clean way of creating things that only exist while you use them. The macros tab of the project explorer window has a nice way of viewing all the local variable and parameters.

billduck
Posts: 159
Joined: Thu Jul 01, 2010 1:57 am
Has thanked: 23 times
Been thanked: 16 times
Contact:

Re: Programming I2C Digital Compass

Post by billduck »

I could have not stated the challenges better. I am not able to get a response from the HMC5833L. Are you? I am using a device address of 0x1E.

billduck
Posts: 159
Joined: Thu Jul 01, 2010 1:57 am
Has thanked: 23 times
Been thanked: 16 times
Contact:

Re: Programming I2C Digital Compass

Post by billduck »

I re purposed the code for an uno and a serial display, showing X,Y,Z. I assume the #'s are the values of the field. I want to get a compass heading.
Thanks so much for sorting through this. I Note that the device address is not used at all. Am I correct that this is so because not using a software I2C?
Attachments
Compass1_17.fcf
For a UNO with a serial display
(38.72 KiB) Downloaded 477 times

billduck
Posts: 159
Joined: Thu Jul 01, 2010 1:57 am
Has thanked: 23 times
Been thanked: 16 times
Contact:

Re: Programming I2C Digital Compass

Post by billduck »

I normalized the X and Y values by dividing by the sqrt(X*X+Y*Y), Then computed a heading based on the quadrant. Seems to work, right or wrong. North is 0 degrees. E is 90.....
Thanks to those who hammered it out.
Attachments
Compass_HMC5883L.fcf
UNO_R3 with Serial Diaplay. Showung compass heading.
(42.34 KiB) Downloaded 512 times

airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Re: Programming I2C Digital Compass

Post by airforcejeesh »

Billduck, I'm trying to transfer your program to Flowcode 5.

Does anyone know how to process atan() without the numeric function built-in? It doesn't seem to be in Flowcode 5.

billduck
Posts: 159
Joined: Thu Jul 01, 2010 1:57 am
Has thanked: 23 times
Been thanked: 16 times
Contact:

Re: Programming I2C Digital Compass

Post by billduck »

see the following for an approximation of the tangent function.
http://en.wikipedia.org/wiki/Taylor_series

airforcejeesh
Flowcode v5 User
Posts: 11
Joined: Tue Dec 30, 2014 10:03 pm
Has thanked: 5 times
Contact:

Re: Programming I2C Digital Compass

Post by airforcejeesh »

I've used a Taylor series to approximate an atan() equation while keeping the rest of Billduck's template*. However, my compass still doesn't seem to work. Can anyone find an error with it?

I had to break the code to a very simple form down to save file space (e.g., using one long equation instead of several variables). If that has made the attached version too confusing, I can upload a cleaner file.



*As far as I can tell, the Taylor series for atan() is: Y = X - (X^3/3) + (X^5/5) - (X^7/7) + (X^9/9) ...
Attachments
basic compass.fcf
(24.88 KiB) Downloaded 406 times

Post Reply