Digital Compass
Moderator: Benj
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Digital Compass
Digital Compass
My latest project is a electronic digital compass.
While browsing a component site, I spotted this interesting module.
CMPS03 Compass Module.
Fig1. The PCB as received from the supplier.
North is at right angle to the left side of the pcb.
The 2 x 8 pin chips nearest the left side are the Philips KMZ51 magnetic detector devices.
Data sheet for the compass can be downloaded from here.
http://www.robot-electronics.co.uk/htm/cmps3tech.htm
Required Hardware.
EB006 Multi-programmer.
EB005 LCD Display.
EB016 Prototyping Board.
The unit must be used horizontally or on a flat surface non metallic surface, serious errors will be introduced if these recommendations are not followed.
The unit consists of a small PCB (approx 35mm square), fitted with a SIL header plug. This has standard spacing allowing it to be plugged into a standard protoboard.
The functional part of the circuit is 2 Philips KMZ51 magnetic field sensor IC’s mounted at right angles to each other. These pick up the earth’s magnetic field and can calculate the direction the unit is facing.
Module Calibration
It is recommend to ensure the unit is working properly before attempting calibration.
It may be necessary to calibrate the unit.
A standard magnetic needle compass is needed to do this.
The module is positioned to point to the 4 main points of the compass (N E S W)
At each point, a value of 255 is written to the module via the I2C bus
Alternatively it can be calibrated by connecting the cal input (pin6) to ground (pin9) by a push switch.
This way will be fitted to the final version using a jumper to allow the button to be totally disconnected from the module when not needed, this will prevent it being pressed accidentally and corrupting the calibration.
This method is preferable to using the I2C bus method as it allows the unit to be recalibrated in the field where access to a pc may not be possible.
As above the unit is calibrated at the 4 main points of the compass, the button is pressed momentarily to set the value before being moved to the next position.
Data Output
0 to 255 = 0 to 360° (1 byte)
This means each value read is equal to approximately 1.4°
The data is read by using a 12C bus protocol.
Steps to read the data are as follows
I2C Initialise
I2C Start
I2C Transmit Byte 0xC0 Send start bit to the compass with read/write bit low
I2C Transmit Byte 1 Register to be read
I2C Restart
I2C Transmit Byte 0xC1 Send start bit to the compass with read/write bit high
I2C Receive Byte 1 Register to read Return Value = out
I2C Stop
This will put the current value read from the I2C bus into the variable “out”
Because the program is using integer math the calculation will be done as follows
Angle = ((out * 7) / 4)
This way the measured value can be multiplied by approximately 1.4
By converting the output value to a float, the accuracy can be improved
Angle = fmul(out,1.406)
A still more accurate method is available where the output is 3599 for an angle of 359.9°
This uses a 16bit word and is read as 2 bytes (Highbyte LowByte)
This uses registers 2 & 3 and is read in a similar way
out = lowbyte + (highbyte <<8)
angle = fdiv(out,10)
My latest project is a electronic digital compass.
While browsing a component site, I spotted this interesting module.
CMPS03 Compass Module.
Fig1. The PCB as received from the supplier.
North is at right angle to the left side of the pcb.
The 2 x 8 pin chips nearest the left side are the Philips KMZ51 magnetic detector devices.
Data sheet for the compass can be downloaded from here.
http://www.robot-electronics.co.uk/htm/cmps3tech.htm
Required Hardware.
EB006 Multi-programmer.
EB005 LCD Display.
EB016 Prototyping Board.
The unit must be used horizontally or on a flat surface non metallic surface, serious errors will be introduced if these recommendations are not followed.
The unit consists of a small PCB (approx 35mm square), fitted with a SIL header plug. This has standard spacing allowing it to be plugged into a standard protoboard.
The functional part of the circuit is 2 Philips KMZ51 magnetic field sensor IC’s mounted at right angles to each other. These pick up the earth’s magnetic field and can calculate the direction the unit is facing.
Module Calibration
It is recommend to ensure the unit is working properly before attempting calibration.
It may be necessary to calibrate the unit.
A standard magnetic needle compass is needed to do this.
The module is positioned to point to the 4 main points of the compass (N E S W)
At each point, a value of 255 is written to the module via the I2C bus
Alternatively it can be calibrated by connecting the cal input (pin6) to ground (pin9) by a push switch.
This way will be fitted to the final version using a jumper to allow the button to be totally disconnected from the module when not needed, this will prevent it being pressed accidentally and corrupting the calibration.
This method is preferable to using the I2C bus method as it allows the unit to be recalibrated in the field where access to a pc may not be possible.
As above the unit is calibrated at the 4 main points of the compass, the button is pressed momentarily to set the value before being moved to the next position.
Data Output
0 to 255 = 0 to 360° (1 byte)
This means each value read is equal to approximately 1.4°
The data is read by using a 12C bus protocol.
Steps to read the data are as follows
I2C Initialise
I2C Start
I2C Transmit Byte 0xC0 Send start bit to the compass with read/write bit low
I2C Transmit Byte 1 Register to be read
I2C Restart
I2C Transmit Byte 0xC1 Send start bit to the compass with read/write bit high
I2C Receive Byte 1 Register to read Return Value = out
I2C Stop
This will put the current value read from the I2C bus into the variable “out”
Because the program is using integer math the calculation will be done as follows
Angle = ((out * 7) / 4)
This way the measured value can be multiplied by approximately 1.4
By converting the output value to a float, the accuracy can be improved
Angle = fmul(out,1.406)
A still more accurate method is available where the output is 3599 for an angle of 359.9°
This uses a 16bit word and is read as 2 bytes (Highbyte LowByte)
This uses registers 2 & 3 and is read in a similar way
out = lowbyte + (highbyte <<8)
angle = fdiv(out,10)
Last edited by JohnCrow on Sat Jul 16, 2011 10:28 am, edited 6 times in total.
1 in 10 people understand binary, the other one doesn't !
- 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: Digital Compass
Very nice project John, wouldn't mind a go at this one myself
Thanks for posting.
Thanks for posting.
Regards Ben Rowland - MatrixTSL
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
This is a slightly more accurate version of the flowchart.
Using floating point variables I can divide by 1.406 rather than using the fraction 7/5.
I have still kept it to a simple display, making it easier for other users to learn from and adapt to their needs.
A couple of important points that were missed of the first post.
1.)The SDA & SCL lines need a 1k8 pull up resistor to the 5V line. See data sheet for more information on this.
2.)If buying a module ensure it has at least version 14 firmware.
This can be easilly checked as earlier versions have a ceramic resonator on the board. V14 and up just have 3 solder pads.
This firmware allows the user to :
Change the default bus address
Restore factory defaults
The firmware version is stored in register 0, which can be read over the I2C bus.
Both programs have been checked on hardware, along with a magnetic compass, and are within a couple of degrees of true value.
I will not bother atempting calibration of the module at the current time as I dont believe it will make a great deal of difference.
Using floating point variables I can divide by 1.406 rather than using the fraction 7/5.
I have still kept it to a simple display, making it easier for other users to learn from and adapt to their needs.
A couple of important points that were missed of the first post.
1.)The SDA & SCL lines need a 1k8 pull up resistor to the 5V line. See data sheet for more information on this.
2.)If buying a module ensure it has at least version 14 firmware.
This can be easilly checked as earlier versions have a ceramic resonator on the board. V14 and up just have 3 solder pads.
This firmware allows the user to :
Change the default bus address
Restore factory defaults
The firmware version is stored in register 0, which can be read over the I2C bus.
Both programs have been checked on hardware, along with a magnetic compass, and are within a couple of degrees of true value.
I will not bother atempting calibration of the module at the current time as I dont believe it will make a great deal of difference.
1 in 10 people understand binary, the other one doesn't !
-
- Matrix Staff
- Posts: 9520
- Joined: Sat May 05, 2007 2:27 pm
- Location: Northamptonshire, UK
- Has thanked: 2585 times
- Been thanked: 3815 times
- Contact:
Re: Digital Compass
Hi John. I agree, what a great project!
I have just added a bit extra to your Flowchart
So now, not only will LCD display angle, but will also display direction e.g N, NNW,SE etc.
Would you mind testing to see if it shows correct direction when compared with a compass please?
Martin
I have just added a bit extra to your Flowchart
So now, not only will LCD display angle, but will also display direction e.g N, NNW,SE etc.
Would you mind testing to see if it shows correct direction when compared with a compass please?
Martin
- Attachments
-
- Simple Angle V1 Float V2.fcf
- (15.01 KiB) Downloaded 415 times
Martin
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Hi Martin
Thanks for the addition to the flowchart.
I'm impressed with the board, nice little unit and not very expensive either.
Just tried it on the hardware and it works great.
Looks like you got your calculations right in the decision loops.
The unit is within a degreee or so with a compass anyway, so Im not bothering changing it at the moment, as I dont want to make things worse.
The data sheet shows it was calibrated at latitude of 67° (I'm at 53°)
Thanks again
Thanks for the addition to the flowchart.
I'm impressed with the board, nice little unit and not very expensive either.
Just tried it on the hardware and it works great.
Looks like you got your calculations right in the decision loops.
The unit is within a degreee or so with a compass anyway, so Im not bothering changing it at the moment, as I dont want to make things worse.
The data sheet shows it was calibrated at latitude of 67° (I'm at 53°)
Thanks again
1 in 10 people understand binary, the other one doesn't !
-
- Matrix Staff
- Posts: 9520
- Joined: Sat May 05, 2007 2:27 pm
- Location: Northamptonshire, UK
- Has thanked: 2585 times
- Been thanked: 3815 times
- Contact:
Re: Digital Compass
Your welcome.JohnCrow wrote:
Just tried it on the hardware and it works great.
Looks like you got your calculations right in the decision loops.
That's good it works.
Thanks for letting me know John.
Martin
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Latest version incorporating Martin's update and using my custom 4x20 LCD
Last edited by JohnCrow on Sun Jul 17, 2011 8:39 pm, edited 1 time in total.
1 in 10 people understand binary, the other one doesn't !
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
I've written a simple version to use the gLCD display.
This shares some of the connections with the I2C bus so I have moved the compass module to port D and used software implementation of the I2C
(This is set in Extenal Properties, Use software settings)
Because the display has a slow refresh, the data doesn't clear each time the compass outputs the next value and the text becomes overwritten each time.
To overcome this, the display is cleared once a second
This shares some of the connections with the I2C bus so I have moved the compass module to port D and used software implementation of the I2C
(This is set in Extenal Properties, Use software settings)
Because the display has a slow refresh, the data doesn't clear each time the compass outputs the next value and the text becomes overwritten each time.
To overcome this, the display is cleared once a second
1 in 10 people understand binary, the other one doesn't !
-
- Posts: 594
- Joined: Thu Sep 17, 2009 7:52 am
- Location: Belgium
- Has thanked: 63 times
- Been thanked: 102 times
- Contact:
Re: Digital Compass
Hi John,
Have you tried writing spaces before writing your data on the gLCD ?
This should clear the previous data written on the gLCD.
Nice project btw
Have you tried writing spaces before writing your data on the gLCD ?
This should clear the previous data written on the gLCD.
Nice project btw
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Hi
Thanks for the comments
I did try that, bit it did'nt clear all the text. For some reason it left a row of pixels at the bottom of where the data was, so it was still not clear.
The next value displayed still didn't look correct.
Will have to have another look at that method, and try different colour / font combinations.
Maybe if I set text = background colour, print some spaces, then change back to text colour.
This is the first time Ive tried using the gLCD apart from a few simple tests when I bought it, so need to experiment a bit to get the best from it.
Thanks for the comments
I did try that, bit it did'nt clear all the text. For some reason it left a row of pixels at the bottom of where the data was, so it was still not clear.
The next value displayed still didn't look correct.
Will have to have another look at that method, and try different colour / font combinations.
Maybe if I set text = background colour, print some spaces, then change back to text colour.
This is the first time Ive tried using the gLCD apart from a few simple tests when I bought it, so need to experiment a bit to get the best from it.
1 in 10 people understand binary, the other one doesn't !
- petesmart
- Valued Contributor
- Posts: 395
- Joined: Thu May 06, 2010 11:42 am
- Location: Sydney, Australia
- Has thanked: 187 times
- Been thanked: 140 times
- Contact:
Re: Digital Compass
Hi John,
Your compass looks great. it appears that we are playing with the same toys at the moment. I'm using the bigger brother version of the sensor, the tilt compensated CMPS09 as an angle sensor. A slight over kill, however i had it laying around from another project
I attempted for quite some time to get the numbers to print and update cleanly on the gLCD, with very limited success. Then i switched over to printing strings instead and this produced a very positive result. Not only does it over write cleanly you can pad the number sequence with trailing and leading zeros or spaces as required. Printing spaces is also another clean up and formatting method. The other benefit is that you can control how many decimal places you want to display without having to manage it via math..
So the secret to my much improved outcome was to convert the integer/float number captured from the CMPS09 and converting it to a string - Float2string(). Then i simply added stings together to achive dymanic formatting (left$(), mid$() )without having to clear down the display which is very slow and looks completely awful in terms of user experience. For refrence see attched pix, i have included a pix of the screen output plus the macro of the screen format routine.
the variables:
degree = "°"
pad = " " this can either be a space or leading zero
the only thing to watch is string and float manipulation issues with 8bit series PIC, the result was a little flaky. I moved to a ds30F2011 in the end and acheived a dramtic improvement not only in performance, but stability around the convert process... BTW the screen update is very fast. I even change the colour of the angle indication line when it exceeds +/- 10°
Note that I also used a custom character to show the degree symbol ° refer post http://www.matrixmultimedia.com/mmforum ... =29&t=8609. My thanks go to Ben Rowland for the solution here. This post demonstrates how to customise a character on the gLCD display.
Oh and you must turn transparency off, ie set it to zero... this is the other important ingredient to clean display update!
hope this helps - appreciate your ongoing contribution to the forum, its both entertaining and enlightening.
all the best
Pete
Your compass looks great. it appears that we are playing with the same toys at the moment. I'm using the bigger brother version of the sensor, the tilt compensated CMPS09 as an angle sensor. A slight over kill, however i had it laying around from another project
I attempted for quite some time to get the numbers to print and update cleanly on the gLCD, with very limited success. Then i switched over to printing strings instead and this produced a very positive result. Not only does it over write cleanly you can pad the number sequence with trailing and leading zeros or spaces as required. Printing spaces is also another clean up and formatting method. The other benefit is that you can control how many decimal places you want to display without having to manage it via math..
So the secret to my much improved outcome was to convert the integer/float number captured from the CMPS09 and converting it to a string - Float2string(). Then i simply added stings together to achive dymanic formatting (left$(), mid$() )without having to clear down the display which is very slow and looks completely awful in terms of user experience. For refrence see attched pix, i have included a pix of the screen output plus the macro of the screen format routine.
the variables:
degree = "°"
pad = " " this can either be a space or leading zero
the only thing to watch is string and float manipulation issues with 8bit series PIC, the result was a little flaky. I moved to a ds30F2011 in the end and acheived a dramtic improvement not only in performance, but stability around the convert process... BTW the screen update is very fast. I even change the colour of the angle indication line when it exceeds +/- 10°
Note that I also used a custom character to show the degree symbol ° refer post http://www.matrixmultimedia.com/mmforum ... =29&t=8609. My thanks go to Ben Rowland for the solution here. This post demonstrates how to customise a character on the gLCD display.
Oh and you must turn transparency off, ie set it to zero... this is the other important ingredient to clean display update!
hope this helps - appreciate your ongoing contribution to the forum, its both entertaining and enlightening.
all the best
Pete
- Attachments
-
- display showing declination of >10°
- Capture2.JPG (14 KiB) Viewed 11084 times
-
- Capture1.JPG
- (227.71 KiB) Downloaded 2410 times
sorry about that Chief!
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Thanks for that Pete
I'll give a a go later and see how it works.
I'll give a a go later and see how it works.
1 in 10 people understand binary, the other one doesn't !
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Completed Compass Board
I have now built the digital compass on a EB-017 Patch Board, freeing my Protoboard for another project.
Jumper = Calibration Enable/Disable. (Jumper Top = Enable)
Switch = Start Calibration.
LED = Calibrating.
The enable jumper is to prevent the calibration routine being entered by accident.
Sockets from left hand side.
1 = 5V
2 = SCL
3 = SDA
4 = PWM
5 = LED Input
6 = Switch Input
Room on RHS for another project if nessesary
I have now built the digital compass on a EB-017 Patch Board, freeing my Protoboard for another project.
Jumper = Calibration Enable/Disable. (Jumper Top = Enable)
Switch = Start Calibration.
LED = Calibrating.
The enable jumper is to prevent the calibration routine being entered by accident.
Sockets from left hand side.
1 = 5V
2 = SCL
3 = SDA
4 = PWM
5 = LED Input
6 = Switch Input
Room on RHS for another project if nessesary
1 in 10 people understand binary, the other one doesn't !
- JohnCrow
- Valued Contributor
- Posts: 1367
- Joined: Wed Sep 19, 2007 1:21 pm
- Location: Lincolnshire
- Has thanked: 364 times
- Been thanked: 716 times
- Contact:
Re: Digital Compass
Audio / Visual Version
I have now added audio/visual feedback to my compass board.
4 LEDs which represent the 4 cardinal points
N = Blue
E = Green
S = Pink
W = Green
When exactly between the 2 points i.e. NE both LED's light.
When pointing North, a buzzer also sounds.
The LED's and buzzer are connected to PORT D in this example program, but they could all be connected to PORT C.
The LED's light for a couple of degrees either side of the cardinal point
This is read from the raw data out of the compass module.
When looking at the board in the photograph, North is the bottom of the board.
I have now added audio/visual feedback to my compass board.
4 LEDs which represent the 4 cardinal points
N = Blue
E = Green
S = Pink
W = Green
When exactly between the 2 points i.e. NE both LED's light.
When pointing North, a buzzer also sounds.
The LED's and buzzer are connected to PORT D in this example program, but they could all be connected to PORT C.
The LED's light for a couple of degrees either side of the cardinal point
This is read from the raw data out of the compass module.
When looking at the board in the photograph, North is the bottom of the board.
1 in 10 people understand binary, the other one doesn't !