SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By George64
#145520
Hello,

I'm in the process of building a digital compass with the Arduino Uno and the LSM303. The purpose of this compass is to enter the nmea-data to the boat's network and therefor get a more stable course when the auto pilot is steering the boat. To get a serial data stream I build a small logic board that converts the TX signal into a TTL signal. I can read the data stream using a serial cable (not the usb cable that can be connected to the Arduino too). The code I'm using:
Code: Select all
#include <Wire.h>
#include <LSM303.h>

LSM303 compass;

void setup() {
  Serial.begin(4800);
  Wire.begin();
  compass.init();
  compass.enableDefault();
  
  // Calibration values. Use the Calibrate example program to get the values for
  // your compass.
  compass.m_min.x = -550;  compass.m_min.y = -357;  compass.m_min.z = -460;
  compass.m_max.x = 223;  compass.m_max.y = 378;  compass.m_max.z = 300;
}

/*----------------------------------------------------------------------------
        1   2   3 4   5 6
        |   |   | |   | |
 $--HDG,x.x,x.x,a,x.x,a*hh<CR><LF>
------------------------------------------------------------------------------

Field Number: 
1. Magnetic Sensor heading in degrees
2. Magnetic Deviation, degrees
3. Magnetic Deviation direction, E = Easterly, W = Westerly
4. Magnetic Variation degrees
5. Magnetic Variation direction, E = Easterly, W = Westerly
6. Checksum */

char nmeastr[17]; // HCHDG,000.00,,,,*
int checksum;
char hs[6]; // 000.00

void loop() {
  
  strcpy(nmeastr,"HCHDG,");
  //dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER);
  compass.read();
  
  int heading = compass.heading((LSM303::vector){0,-1,0}); 
 
   Serial.print("Heading list : ");
   Serial.print(heading);
   Serial.print("\t\t");
 
  if (heading > 180) 
  {  
    heading = heading - 360;
  }
 
  // dtostrf(compass.heading((LSM303::vector){0,-1,0}), 5, 2, hs);
  dtostrf(list.getAverage(), 5, 2, hs);
  //dtostrf(heading, 5, 2, hs);
  //Serial.print("hs ");
  //Serial.print(hs);
  //Serial.println();  
  
  strcat(nmeastr,hs);
  strcat(nmeastr,",,,,");
  
  //add a checksum
  checksum=0;
  for (int n=0; n < strlen(nmeastr); n++) {
    checksum ^= nmeastr[n];
  }
  
  Serial.print("$");
  Serial.print(nmeastr);
  Serial.print("*");
  Serial.print(checksum, HEX);
  Serial.print("\t");
  Serial.println();
  
  /* 5hz == 200 */
  delay(100);
}
The problem I have with the output, it is fluctuating heavily. I think some filtering might help. I had already had a look at the Kalman filter, however since I don't speak the programming language, I got stuck in that process.

Someone who can be of any help in solving this issue? Been searching for hours and hours but did not find a similar subjects on this question.

Any help is highly appreciated!
By odin84gk
#145843
Can you post a picture of your setup? I haven't used this part, but heavy fluctuations usually happen if you have an improper setup.
By fll-freak
#145846
Significant changes can also happen in a changing magnetic environment such as near power supplies, electric motors, or any ferrous metals in motion.
By George64
#145847
Thanks for your reply.

This is how my setup looks:
Image
By fll-freak
#145848
Are you able to read the various control registers reliably?
How much variation in the raw magnetic sensor values are you getting?
Need to figure out if its your interface to the chip or the chip itself.
By George64
#145849
fll-freak wrote:Are you able to read the various control registers reliably?
How much variation in the raw magnetic sensor values are you getting?
Need to figure out if its your interface to the chip or the chip itself.
I wish I could, because that would mean I can write C++ ;) The only thing I'm referring to is the output of the call (heading) to the compass.
By fll-freak
#145850
If you are using a library to talk to the compass without understanding how it works or what the limitations are than I would suggest to you that you are sailing into danger.

I do not have experience with this chip, but I have seen lots of information on this Forum that indicates you will get junk unless you calibrate it. Use search to look for LSM303 and calibration. If you can't find an answer, you will need to post where you got the LSM303 library you are using, what version it is, and what modifications you made to it if any.
By George64
#145851
I did calibrate the lsm303. I do got a seperate programm from Git that helped me calibrating the unit. The values got stable after the movements described in the fact sheet. After a while the values got stable and I added these values in the heading.ino
By fll-freak
#145853
Amazing what happens when you calibrate a sensor!

Just remember that you will need to calibrate the sensor again when you move it to a new home. The calibration removes the effects of metals in the area. If you calibrate it at home then move it to a boat, the fields will be different and you must recalibrate. This is just like any magnetic compass. If you move it or move any ferrous materials in your boat, you need to re-compensate it.
By George64
#145856
Ok, recalibrating is good to know.

I would expect a stable heading as soon as it is laying flat on the table, free of metal or computers. However being stable is not the case. Therefor it crossed my mind to add filtering to the various vectors. But, correct me if I'm wrong.
By Mee_n_Mac
#145860
Filtering might help or simply mask a deeper problem, it depends on the nature of the inteference. When you say "fluctuating heavily", how much is that ? Can you capture the output (few hundred samples here should be enough) to a test file and attach it here ?

ps - I think the forum was worked on recently and your pic of your setup (above) is now poofed (at least it is for me). If it is for you as well, try removing and re-attaching it.
By fll-freak
#145864
George64 wrote:I did calibrate the lsm303. I do got a seperate programm from Git that helped me calibrating the unit. The values got stable after the movements described in the fact sheet. After a while the values got stable and I added these values in the heading.ino
Must have a language problem. From these comments I figured your problem was not solved.

Sample of your output would be good. Picture shows OK for me.
By Mee_n_Mac
#145866
fll-freak wrote: Picture shows OK for me.
Yup, it was work blocking the linked site. I wonder how much the copper breadboard under the compass is affecting things ? Hard to guess at the potential causes w/o seeing the data.
By George64
#145987
To for come interference I made a separate box for the compass, so the compass is connected with 4 copper wires to the Arduino board and the two boxes are at a max. of 3meters away from each other.

I used the the .h and .cpp from https://github.com/pololu/LSM303/blob/master/LSM303/ In combination with the code for producing the nmea-string, it is still fluctuating 4-5 degrees when laying flat on the table (after entering the new calibrating values)
By jremington
#146107
The heading indicated by my LSM303 magnetometer/accelerometer 3D compass, calibrated using the primitive Pololu method of min/max/scaling, also jumps around by about 4 degrees while laying flay on the table. If your indicated heading is more or less correct, then the fluctuation you are seeing is probably just an indication of the error in the measurements. Averaging will help a bit.

However, even with the most sophisticated calibration procedures currently available to hobbyists (discussed elsewhere in these forums, see for example http://sailboatinstruments.blogspot.com ... ation.html), the LSM303 hardware won't let you do much better than 1-2 degrees accuracy.