Shop OBEX P1 Docs P2 Docs Learn Events
Problems with Heading of HMC5883L 3 Axis Compass Module — Parallax Forums

Problems with Heading of HMC5883L 3 Axis Compass Module

SaravananSaravanan Posts: 19
edited 2015-06-16 16:34 in Propeller 1
Dear All,

I am using a Parallax compass module "HMC5883L" with the sample code which was found in the Examples=>Sensor Folder. I changed the Pin configuration to be connected as SCL=>P3 and SDA=>P4. There is no other changes made. When I run this code there seems to be some problems with the heading. The change in heading isn't linear. Heading increases from 0 to 200 degrees just within 90 degrees of movement of the sensor and the change in degrees is very slow for the rest of the circle. I do understand that I am turning along the z axis. Hope someone can help me out on this! Below is the code that I used.
/*
  Test Compass HMC5883L.c
  
  Test compass with SCL connected to P3 and SDA connected to P4. Display
  measurement results in SimpleIDE Terminal.
  
 http://learn.parallax.com/propeller-c-simple-devices/
*/

#include "simpletools.h"                      // Include simpletools header
#include "compass3d.h"                        // Include compass3d header

int main()                                    // main function
{
  int x, y, z;                                // Declare x, y, & z axis variables
  
  i2c *bus = i2c_newbus(3, 4, 0);             // New I2C bus SCL=P3, SDA=P4
  compass_init(bus);                          // Initialize compass on bus.

  while(1)                                    // Repeat indefinitely
  {
    compass_read(bus, &x, &y, &z);            // Compass vals -> variables
    print("%cx=%d, y=%d, z=%d%c\n",           // Display compass variables
           HOME, x, y, z, CLREOL);

    float fy = (float) y;                     // Ints to floats
    float fx = (float) x;
    float heading = atan2(fy, fx) * 180.0/PI; // Calculate heading with floats
    if(heading < 0.0)                         // Convert -180...+180 to 0...360
      heading = (360.0 + heading);
    print("heading = %.2f%c\n",               // Display heading
                        heading, CLREOL);       

    pause(200);                               // Wait 1/2 second
  }
}

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 11:58
    Where do you live?

    Depending on how far away you are from a magnetic pole you can get some strange results with the sensor. Here in Idaho we have a very large component in the z axis of the magnetic field. I was still able to get good heading readings but I think a strong z component could cause trouble.

    Is there any iron near the sensor? How about motors?

    What values do you get for the x, y and z components as you rotate the sensor? If you shared the raw x, y and z values when the compass is oriented close to north, east, south and west, it might provide some clues on how the sensor is working.

    If you're willing to try some Spin code, you could use my demo I attached to this post:

    http://forums.parallax.com/showthread.php/155653-My-Version-of-a-HMC5883L-Object?p=1267049&viewfull=1#post1267049

    IIRC, My version will tell you how far from horizontal the magnetic field is. The code also allows one to easily change the various registers in the sensor. This allows gain and internal averaging values to be changed.
  • SaravananSaravanan Posts: 19
    edited 2015-06-09 15:08
    Hi... thanks for your reply. I live in Colorado Springs. I do not have any other components except a laptop at about 1 meter from the sensor.

    This are the raw readings and the processed heading readings from the chip which is running the sample code.
    x y z heading(Deg)
    North 125 -385 -386 286
    East 204 -70 -389 348.67
    South -92 -7 -386 181.47
    West -182 -285 -369 235.2
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 15:44
    Saravanan wrote: »
    Hi... thanks for your reply. I live in Colorado Springs. I do not have any other components except a laptop at about 1 meter from the sensor.

    This are the raw readings and the processed heading readings from the chip which is running the sample code.
    x y z heading(Deg)
    North 125 -385 -386 286
    East 204 -70 -389 348.67
    South -92 -7 -386 181.47
    West -182 -285 -369 235.2

    That doesn't look right. The y-axis stays negative?!

    If your sensor got close to a large magnet it could be messed up for a while.

    If your sensor is out of whack because of a magnet, I think there's a way to fix it but I don't recall what it is.

    I was going to try the code with my sensor but the example code in the version of Simple IDE I had installed wasn't the same as the code you used.

    I'll install a recent version of Simple IDE and try again.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 17:07
    I downloaded version 1.0.2 of Simple IDE and ran the HMC5883L demo and there is something seriously wrong with the program.

    My sensor also does not output good information using the example program.

    I think there are other C programs available.

    I haven't tried the code in this thread but I think it looks promising.

    http://forums.parallax.com/showthread.php/159754-Propeller-Activity-board-C-Compass-project

    I'll send a bug report to Parallax about this.

    Edit: I tried the code again and it now appears to work. I'm going to test this a bit more. I'll post again later.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 17:33
    The code appears to be working okay right now but there's something strange with how often the data is updated.

    I changed the half second delay to a tenth of a second but the display appears to only update about one a second.

    I'm trying to get a look at the library files to see if there's something limiting how frequently the sensor is read.

    I know from my past experience these sensor work really well and can update quickly. I think there's something in the code which is slowing it down.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 17:41
    I just remembered from my earlier work with this sensor, it has a register to set the internal update frequency. I bet the C code sets this register to an 1 Hz refresh.

    I'll try to track this down but I might not get around to it today.

    I doubt there's anything wrong with your sensor.

    If you have the Propeller Tool installed or some other software to load Spin programs, you might want to take a look at the code I linked to earlier.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2015-06-09 19:45
    Somewhere in my mess of stuff I have one of those compass modules also. If I can dig it up I will mess with your code also to see what I come up with. IIRC, I was having issues with mine so I shelved it. Now to find the darn thing. I bought a whole case of the Sterilite storage cases like Parallax sells on EBay and a few from Parallax and they are all full!!!
  • NWCCTVNWCCTV Posts: 3,629
    edited 2015-06-09 20:10
    So what part of the module is due North and what reading should come up as due North? I ran the SimpleIDE code and SPIN. If the side where the wires connect on the compass module is North then my SPIN code is pretty much dead on. Not sure on the SimpleIDE as I do not know what the North reading should be.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-06-09 20:48
    It's not at all unusual for the raw values from this module to be skewed, and all-negative values for Y are not uncommon. Anytime this module is installed in a different bot or environment, it needs to be calibrated. A sample filled-out version of the worksheet I provided to my students for calibrating their compasses is attached below. When plotted, the raw values should form an ellipse, although it will probably be offset from the origin and maybe quite skewed.

    Once these readings have been acquired, they can be entered in my online calibration program:

    It will return a line like the following:
    compass_corr            long    198,-23,203,-82,-12
    

    that can be inserted into a Spin program or the values copied into a C program. In my compass object (which does not use the Z axis at all, since in my app the compass will always be level), these values are named x_ampl, x_offset, y_ampl, y_offset, and a_offset.

    To compute corrected xc and yc values from the raw x and y, use the following formulae:
      xc := -(x - x_offset) * 300 / x_ampl
      yc := (y - y_offset) * 300 / y_ampl
    

    Then the corrected compass heading (in tenths of a degree) is:
      a := 900 - atan2(yc, xc) + a_offset
      a += 3600 & (a < 0)
      a -= 3600 & (a > 3600)
    

    where atan2 has to return an angle in tenths of a degree.

    BTW, this is all predicated upon interpreting the "heading" as pointing away from, and perpendicular to, the five-pin header of the Parallax module.

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-09 22:09
    It's not at all unusual for the raw values from this module to be skewed, and all-negative values for Y are not uncommon.

    Thanks for the information.

    I've seen calibration information similar to what you use but the couple sensors I've used worked pretty well without calibration.

    Apparently besides having the x, y coordinates "off center", they can also be stretched in one axis or the other. The ap note I attached to this post includes calibration techniques for overcoming these errors. I had hoped they weren't really needed but apparently I've just been lucky with the sensors I've used so far. Edit: I hadn't read Phil's post carefully enough. He already mentioned the stretch issue.

    I'm not sure if I've used two or three of these sensors myself but the ones I've used were pretty symmetrical (and centered) in their output range. Though TTYTT, I haven't checked very carefully. I just checked N, S, E & W, I didn't graph a circle as you suggest.


    I'm still trying to figure out why the program appears to update so slowly.

    BTW, I think this is the initialization code for the compass;
    void compass_init(i2c *bus)
    {
      /* set to continuous mode */
      int modeReg = 0x02;
      unsigned char contMode = 0x00;
      int n = i2c_out(bus, 0x3C >> 1, modeReg, 1, &contMode, 1);
    }
    

    I found the above code in the file "SimpleIDE\Learn\Simple Libraries\Sensor\libcompass3d\compass3d.c"

    The only register changed from the default setting is the mode register which is changed to place the sensor in continuous mode. The default refresh rate is 15Hz so I don't understand why my sensor updates so slowly.

    I'm out of my comfort zone when it comes to C on the Prop. I fear I could easily be missing something obvious.

    I'll probably go back to the Spin demo to make sure I'm remembering the performance of the sensor correctly. It sure seems like the sensor was pretty quick to update when running the Spin code.


    In case anyone else is curious about the function "i2c_out" it's located in a C file of the same name "SimpleIDE\Learn\Simple Libraries\Utility\libsimpletools\source\i2c_out.c."

    I find I have a hard time finding functions used by a C program. (To be honest I haven't spent a lot of time using C on the Propeller, so I shouldn't be too surprised I'm having a hard time finding my way around the library files.)


    @Andy,

    The is the output when my sensor is level and aligned with magnetic north.
    x=337, y=0, z=-572
    heading = 0.00
    

    (Darn, SimpleIDE Terminal doesn't let me copy the output to the clipboard. I suppose I can use PST with SimpleIDE.)

    Edit: I hadn't read Phil's excellent post carefully enough before replying. Phil mentioned the calibration points could form an ellipse.
  • SaravananSaravanan Posts: 19
    edited 2015-06-10 10:11
    Once these readings have been acquired, they can be entered in my online calibration program:
    http://www.phipi.com/pthsrobotics/compass_correct.html

    I have tried your calibration technique and I got these values from the online program.
    compass_corr long 295,42,288,-193,123

    Then I went on to include these in my code as follows:
    #include "simpletools.h"                      // Include simpletools header
    #include "compass3d.h"                        // Include compass3d header
    
    int main()                                    // main function
    {
      int x, y, z;                                // Declare x, y, & z axis variables
      
      i2c *bus = i2c_newbus(3, 4, 0);             // New I2C bus SCL=P3, SDA=P4
      compass_init(bus);                          // Initialize compass on bus.
      
      int x_ampl=295;
      int x_offset=42;
      int y_ampl=288;
      int y_offset=-193;
      int a_offset=123;
    
      while(1)                                    // Repeat indefinitely
      {
        compass_read(bus, &x, &y, &z);            // Compass vals -> variables
        print("%cx=%d, y=%d, z=%d%c\n",           // Display compass variables
               HOME, x, y, z, CLREOL);
        float xc = -(x - x_offset) * 300 / x_ampl;
        float yc = (y - y_offset) * 300 / y_ampl;
        float a = 900 - atan2(yc, xc) + a_offset;
        a += 3600 & (a < 0);
        a -= 3600 & (a > 3600);
        print("heading = %.2f%c\n",a, CLREOL);
        pause(200);                               // Wait 1/2 second
      }
    }
    

    I now get my value for a as 1021.0 to 1023.8 when I rotate the full axis. Is there anything I have skipped or done wrong?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-10 10:35
    Duane Degn wrote: »
    I'm still trying to figure out why the program appears to update so slowly.

    I don't know what's different today but the sensor is working fine. It's updating very quickly.
    I don't think there's anything wrong with the C code.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-10 10:37
    Saravanan wrote: »
    Is there anything I have skipped or done wrong?

    I'm not following along well enough to know what's wrong. I see a mixture of integer math with floating point math but apparently you can do that with C.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-10 11:09
    BTW, this is all predicated upon interpreting the "heading" as pointing away from, and perpendicular to, the five-pin header of the Parallax module.

    I can't find my Parallax board but when I run the SimpleIDE code, I get a heading of zero when the x-axis is aligned with magnetic north. I also see your equation has a 90 degree value not present in the SIDE code.

    I found Arduino example code which uses the same orientation of the sensor as you're using but IMO, having the x-axis aligned north simplifies the calculations needed to determine heading.

    BTW, the y-axis on the Parallax PCB silkscreen is pointing in the opposite direction from the HMC5883L datasheet (I've seen this mentioned elsewhere on the forum).

    @Saravana, The SimpleIDE code and the code Phil posted are not compatible with each other without some changes.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-10 11:09
    BTW, this is all predicated upon interpreting the "heading" as pointing away from, and perpendicular to, the five-pin header of the Parallax module.

    I can't find my Parallax board but when I run the SimpleIDE code, I get a heading of zero when the x-axis is aligned with magnetic north. I also see your equation has a 90 degree value not present in the SIDE code.

    I found Arduino example code which uses the same orientation of the sensor as you're using but IMO, having the x-axis aligned north simplifies the calculations needed to determine heading.

    BTW, the y-axis on the Parallax PCB silkscreen is pointing in the opposite direction from the HMC5883L datasheet (I've seen this mentioned elsewhere on the forum).

    @Saravana, The SimpleIDE code and the code Phil posted are not compatible with each other without some changes.
  • SaravananSaravanan Posts: 19
    edited 2015-06-10 11:56
    Duane Degn wrote: »
    I can't find my Parallax board but when I run the SimpleIDE code, I get a heading of zero when the x-axis is aligned with magnetic north. I also see your equation has a 90 degree value not present in the SIDE code.
    @Saravana, The SimpleIDE code and the code Phil posted are not compatible with each other without some changes.

    what are the proposed changes you suggest? I am very new to parallax propeller activity board and simple IDE. What is a SPIN program?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-10 12:53
    Saravanan wrote: »
    what are the proposed changes you suggest?

    I'll need to study Phil's code a bit and attempt to modify the example code to work with your figures.

    I'll likely do this later in the day as I procrastinate my real work (which these days is programming in Spin).
    Saravanan wrote: »
    What is a SPIN program?

    Spin is the language Chip Gracey developed for use with the Propeller (Chip also designed the Propeller). The Spin interpreter resides in the Propeller's read only memory.

    I was initially annoyed to have to learn Spin to use the Propeller since I previously programmed in C. I found Spin was very easy to learn after having learned some C.

    I now find Spin extremely enjoyable to use.

    There are links in post #3 of my index (see my signature) on learning Spin.

    It would probably be a good idea for you to download the Propeller Tool (the IDE for writing Spin programs) and to give Spin a try. I'm not going to suggest you switch from using C to using Spin since Parallax is putting a lot of effort into their C tutorials and it would be a shame to miss out on Parallax's excellent tutorials.

    Let us know if you need help finding the Propeller Tool to download. I don't know where to find it off hand but I'm sure I could find it if I looked.
  • SaravananSaravanan Posts: 19
    edited 2015-06-11 11:52
    Is there any other ways without touching SPIN code to calibrate the compass.(Just using Simple-IDE) I took a look at the tutorials of spin code and tried a few. The progress seems slow because it's a very new environment for me.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-11 12:42
    Saravanan wrote: »
    Is there any other ways without touching SPIN code to calibrate the compass.(Just using Simple-IDE) I took a look at the tutorials of spin code and tried a few. The progress seems slow because it's a very new environment for me.

    Yes, there is a way to calibrate the compass using Simple IDE. I think I've figured this out enough to help.
    /*
      Test Compass HMC5883L.c
      
      Test compass with SCL connected to P3 and SDA connected to P4. Display
      measurement results in SimpleIDE Terminal.
      
     http://learn.parallax.com/propeller-c-simple-devices/
    */
    
    #include "simpletools.h"                      // Include simpletools header
    #include "compass3d.h"                        // Include compass3d header
    
    int main()                                    // main function
    {
      int x, y, z;                                // Declare x, y, & z axis variables
      
      // Use these values to generate calibrate points
      float x_ampl=300.0;
      float x_offset=0.0;
      float y_ampl=300.0;
      float y_offset=0.0;
       
      /*
      // replace values with output from www.phipi.com/pthsrobotics/compass_correct.html
      float x_ampl=253.0;
      float x_offset=3.0;
      float y_ampl=277.0;
      float y_offset=-80.0;
      */
      
      //float a_offset=102.1;
      
      //xc := -(x - x_offset) * 300 / x_ampl
      //yc := (y - y_offset) * 300 / y_ampl
      
      
      i2c *bus = i2c_newbus(3, 4, 0);             // New I2C bus SCL=P3, SDA=P4
      compass_init(bus);                          // Initialize compass on bus.
      
      /* configAReg is the register which sets the following parameters
       * of the sensor:
       * Samples to average(bits 6&5): B00=1(default);B01=2;B10=4;B11=8
       * 
       * Data ouput rate(bits 4,3&2): B000=0.75;B001=1.5;B010=3;B011=7.5;
       * B100=15(default);B101=30;B110=75;B111=reserved 
       * 
       * Measurement configuration(bits 1&0): B00=normal(default);
       * B01=Positive bias current; B10=Negative bias current; B11=reserved
       * (I think these bits are used in some sort of calibration but I'm not sure.)*/
      
      int configAReg = 0x00;    
      unsigned char rateSetting = 9 << 2;         // Output at 30Hz 
      unsigned char readingsToAverage = 3 << 5;   // Average 8 readings
      unsigned char biasCurrent = 0 ;             // Bias current off
      unsigned char configACombined = rateSetting | readingsToAverage | biasCurrent;
      
      /* configBReg is the register which sets the gain of the sensor.
       * Gain(bits 7,6&5): B000=1370(most sensitive);B001=1090(default);B010=820;
       * B011=660;B100=440;B101=390;B110=330;B111=230
       * The gain values listed above are in units of (LSb/Gauss)
       * LSb = least significant bit
       * The gain should be reduced (by using a higher value in the setting)
       * if the magnetic field strength causes an overflow in any of the 
       * data output registers.
       * 
       * The lowest five bits of configBReg must be cleared for correct operation.*/
                      
      int configBReg = 0x01;
      unsigned char gainSetting = 0 << 5 ;        // Zero is the most sensitive
                                                  // Increase this value if sensor
                                                  // overflows.
    
      int m = i2c_out(bus, 0x3C >> 1, configAReg, 1, &configACombined, 1);
      int n = i2c_out(bus, 0x3C >> 1, configBReg, 1, &gainSetting, 1);
    
      while(1)                                    // Repeat indefinitely
      {
        compass_read(bus, &x, &y, &z);            // Compass vals -> variables
        print("%cx=%d, y=%d, z=%d%c\n",           // Display compass variables
               HOME, x, y, z, CLREOL);
    
        float fy = (float) y;                     // Ints to floats
        float fx = (float) x;
        
        float xc = (fx - x_offset) * 300.0 / x_ampl;
        float yc = (fy - y_offset) * 300.0 / y_ampl;
        //float a = 900 - atan2(yc, xc) + a_offset;
        float heading = atan2(yc, xc) * 180.0/PI; // Calculate heading with floats
    
        
        //float heading = atan2(fy, fx) * 180.0/PI; // Calculate heading with floats
        if(heading < 0.0)                         // Convert -180...+180 to 0...360
          heading = (360.0 + heading);
        print("heading = %.2f%c\n",               // Display heading
                            heading, CLREOL);       
        if (x <= -2048 || x >= 2047 || y <= -2048 || y >= 2047 || 
            z <= -2048 || z >= 2047)
          {
            print("Warning! Overflow Error", CLREOL);// Display overflow warning
            print("Increase the value of 'gainSetting' and try again", CLREOL);
            pause(10000);
          }                        
        pause(200);                            
      }
    }
    

    You'll want to use the this set of correction factors when you first run the program:
    // Use these values to generate calibrate points
      float x_ampl=300.0;
      float x_offset=0.0;
      float y_ampl=300.0;
      float y_offset=0.0;
       
      /*
      // replace values with output from www.phipi.com/pthsrobotics/compass_correct.html
      float x_ampl=253.0;
      float x_offset=3.0;
      float y_ampl=277.0;
      float y_offset=-80.0;
    

    Go through the process Phil described again with the first set of code in this post. I suggest you write down the z value as well. The z value shouldn't change much as you rotate the sensor. When I calibrated my sensor the z ranged from -584 to -603. Hopefully the z value in a low latitude will be more consistent. The calibration process is very sensitive to sensor being level.

    I didn't worry about formatting the code nicely I just stuck extra code where I guessed was a good spot. A lot of the extra initialization code should probably be moved to a separate function but I just added it to the main function.

    The above code sets the sensor to the highest gain sensitivity. It also have the sensor average 8 readings the number of reads has been increased from 15 a second to 30 a second. I thought my sensor performed better with these changes.

    One I added Phil's calibration values, my sensor behaved pretty well.

    I didn't include the "a_offset" value in the calculations. If you want to convert the magnetic heading to a true heading let us know and I'll had a correction factor back in (though it won't be the one calculated by Phil's program).

    With Spin one can't really mix integers and floating point values. I treated the program as it these values couldn't mix. I don't know if this precaution was needed or not. The above code seems to work well with my sensor.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-06-11 13:36
    Thanks for handling that, Duane! I was out of the forum loop due to classroom demands. Today my students made their presentations to the Marine Science Center and demo'd their ROVs on the water. I can say from this experience that the compass calibration matters a lot for navigation.

    BTW, typically the a_offset value will be small. But if not, it should be used to compute the magnetic heading. Then you can add/subtract the declination on top of that to get a true heading.

    -Phil
  • SaravananSaravanan Posts: 19
    edited 2015-06-11 14:26
    Thanks alot @Duane and @Phil.

    I tried the code as you said. The sensor works well now. It is very accurate! Thanks alot for helping me out. :)
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-06-11 16:01
    For any who're interested (or masochistic enough to read Perl), here's the program that computes the correction coefficients:
    #!/usr/local/bin/perl
    
    use strict;
    use CGI;
    use CGI::Carp qw(fatalsToBrowser);
    $CGI::POST_MAX = 1024 * 1024;
    
    my @vals;
    my $f = 30 / 360 * 6.2831854;
    
    my $offset = 0;
    
    my $query = new CGI;  
    foreach my $i (0 .. 11) {
      $vals[0][$i] = $query->param("x$i");
      $vals[1][$i] = $query->param("y$i");
    }
    
    print "Content-type: text/plain\n\nCopy and paste the following line into your program:\n\ncompass_corr  long      ";
    
    foreach my $n (0, 1) {
      my ($sx, $cx, $kx) = (0, 0, 0);
      foreach my $i (0 .. 11) {
        $sx += $vals[$n][$i] * sin($i * $f);
        $cx += $vals[$n][$i] * cos($i * $f);
        $kx += $vals[$n][$i]
      }
      $sx /= 6; $cx /= 6; $kx /= 12;
      print round(sqrt($sx*$sx + $cx*$cx)),",", round($kx), ",";
      if ($n == 0) {
        $offset += atan2($sx, $cx) * 180 / 3.14159265 + 90
      } else {
        $offset += atan2($sx, $cx) * 180 / 3.14159265
      }
    }
    print round($offset * 5), "\n";
    
    sub round {
      my $arg = shift();
      return $arg < 0 ? int($arg - 0.5) : int($arg + 0.5)
    }
    

    It's basically just a Fourier analysis to compute the DC and fundamental coefficients from the sample data.

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-11 18:38
    Today my students made their presentations to the Marine Science Center and demo'd their ROVs on the water.

    Very cool. I hope you tell us more about the event.

    For any who're interested (or masochistic enough to read Perl), here's the program that computes the correction coefficients:

    Very good. I was wondering how you calculated the amplitude values. I could replicate the offset values with a spreadsheet program but my attempts to compute the amplitude values never agreed with the values provided from the output from your web page. I don't understand Perl but I think I can pick out the equations in the code. Thanks for posting it.

    @Saravana, It's good to hear the sensor is working well.
  • SaravananSaravanan Posts: 19
    edited 2015-06-16 15:32
    I changed the configuration to the one below:
    /* set to continuous mode */
      int modeReg = 0x02;
      unsigned char contMode = 0x00;
      int n = i2c_out(bus, 0x3C >> 1, modeReg, 1, &contMode, 1);
      
      int configAReg = 0x00;    
      unsigned char rateSetting = 5 << 2;         // Output at 30Hz 
      unsigned char readingsToAverage = 0 << 5;   // Average 8 readings
      unsigned char biasCurrent = 0 ;             // Bias current off
      unsigned char configACombined = rateSetting | readingsToAverage | biasCurrent;
      /* configBReg is the register which sets the gain of the sensor.
       * Gain(bits 7,6&5): B000=1370(most sensitive);B001=1090(default);B010=820;
       * B011=660;B100=440;B101=390;B110=330;B111=230
       * The gain values listed above are in units of (LSb/Gauss)
       * LSb = least significant bit
       * The gain should be reduced (by using a higher value in the setting)
       * if the magnetic field strength causes an overflow in any of the 
       * data output registers.
       * 
       * The lowest five bits of configBReg must be cleared for correct operation.*/
      int configBReg = 0x01;
      unsigned char gainSetting = 0 << 5 ;        // Zero is the most sensitive
                                                  // Increase this value if sensor
                                                  // overflows.
      int m = i2c_out(ADCSbus, 0x3C >> 1, configAReg, 1, &configACombined, 1);
      int o = i2c_out(ADCSbus, 0x3C >> 1, configBReg, 1, &gainSetting, 1);
    

    the gain is set to 000 and according to the data sheet(page13) the Gain(LSb/Gauss) is 1370. Therefore to change the raw data to units of Gauss I divided the data with 1370. Is this correct?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-06-16 16:34
    Saravanan wrote: »
    Therefore to change the raw data to units of Gauss I divided the data with 1370. Is this correct?

    I think this is correct.
Sign In or Register to comment.