Ejemplo n.º 1
0
/** Get 3-axis heading measurements.
 * In the event the ADC reading overflows or underflows for the given channel,
 * or if there is a math overflow during the bias measurement, this data
 * register will contain the value -4096. This register value will clear when
 * after the next valid measurement is made. Note that this method automatically
 * clears the appropriate bit in the MODE register if Single mode is active.
 * @param x 16-bit signed integer container for X-axis heading
 * @param y 16-bit signed integer container for Y-axis heading
 * @param z 16-bit signed integer container for Z-axis heading
 * @see HMC5883L_RA_DATAX_H
 */
void HMC5883L::getHeading(int16_t *x, int16_t *y, int16_t *z) {
	int16_t rawx, rawy, rawz;
	getRawHeading(&rawx, &rawy, &rawz);
	*x = (int16_t) (scaleFactors[gain][0]*rawx);
	*y = (int16_t) (scaleFactors[gain][1]*rawy);
	*z = (int16_t) (scaleFactors[gain][2]*rawz);
}
Ejemplo n.º 2
0
// --------------------------------------------------------------------------
// This Function calculates the offset in the Magnetometer
// using Positive and Negative bias Self test capability
// This function updates X_offset Y_offset and Z_offset Global variables
// Call Initialize before
void HMC5883L::calibration_offset(int select)
{
    int             compass_x=0, compass_y=0, compass_z=0;
    float           compass_x_scaled=0, compass_y_scaled=0, compass_z_scaled=0;
    int             i = 0;
    
    // ***********************************************************
    // offset_calibration() function performs two taskes
    // 1. It calculates the diffrence in the gain of the each axis magnetometer axis, using
    //    inbuilt self excitation function of HMC5883L (Which is useless if it is used as a compass
    //    unless you are very unlucy and got a crapy sensor or live at very High or low temperature)
    // 2. It calculates the mean of each axes magnetic field, when the Magnetometer is rotated 360 degree
    // 3. Do Both
    // ***********************************************************
    
    
    // *****************************************************************************************
    // Gain offset estimation
    // *****************************************************************************************
    if (select == 1 | select == 3)
    {
        // User input in the function
        // Configuring the Control register for Positive Bais mode
        Serial.print("          Calibrating the Magnetometer (Gain)  ");
        Wire.beginTransmission(devAddr);
        Wire.write(0x00);
        Wire.write(0b01110001); // bit configuration = 0 A A DO2 DO1 DO0 MS1 MS2
        
        /*
         A A                        DO2 DO1 DO0      Sample Rate [Hz]      MS1 MS0    Measurment Mode
         0 0 = No Average            0   0   0   =   0.75                   0   0   = Normal
         0 1 = 2 Sample average      0   0   1   =   1.5                    0   1   = Positive Bias
         1 0 = 4 Sample Average      0   1   0   =   3                      1   0   = Negative Bais
         1 1 = 8 Sample Average      0   1   1   =   7.5                    1   1   = -
         1   0   0   =   15 (Default)
         1   0   1   =   30
         1   1   0   =   75
         1   1   1   =   -
         */
        Wire.endTransmission();
        
        for(i=0 ; i<50 ; i++)
        {
            getRawHeading(&compass_x, &compass_y, &compass_z); // Disregarding the first data
            delay(10);
        }
    
        // Reading the Positive baised Data
        while(compass_x<200 | compass_y<200 | compass_z<200)
        {
            // Making sure the data is with Positive baised
            getRawHeading(&compass_x, &compass_y, &compass_z);
            delay(10);
            Serial.print(".");
        }
        
        compass_x_scaled = compass_x * mgPerDigit;
        compass_y_scaled = compass_y * mgPerDigit;
        compass_z_scaled = compass_z * mgPerDigit;
        
        // Offset = 1160 - Data_positive
        compass_x_gainError = (float)COMPASS_XY_EXCITATION / compass_x_scaled;
        compass_y_gainError = (float)COMPASS_XY_EXCITATION / compass_y_scaled;
        compass_z_gainError = (float)COMPASS_Z_EXCITATION / compass_z_scaled;
        
        
        // Configuring the Control register for Negative Bais mode
        Wire.beginTransmission(devAddr);
        Wire.write(0x00);
        Wire.write(0b01110010); // bit configuration = 0 A A DO2 DO1 DO0 MS1 MS2
        
        /*
         A A                        DO2 DO1 DO0      Sample Rate [Hz]      MS1 MS0    Measurment Mode
         0 0 = No Average            0   0   0   =   0.75                   0   0   = Normal
         0 1 = 2 Sample average      0   0   1   =   1.5                    0   1   = Positive Bias
         1 0 = 4 Sample Average      0   1   0   =   3                      1   0   = Negative Bais
         1 1 = 8 Sample Average      0   1   1   =   7.5                    1   1   = -
         1   0   0   =   15 (Default)
         1   0   1   =   30
         1   1   0   =   75
         1   1   1   =   -
         */
        Wire.endTransmission();
        
        
        for(i=0 ; i<50 ; i++)
        {
            getRawHeading(&compass_x, &compass_y, &compass_z); // Disregarding the first data
            delay(10);
        }

        // Reading the Negative baised Data
        while(compass_x>-200 | compass_y>-200 | compass_z>-200){   // Making sure the data is with negative baised
            getRawHeading(&compass_x, &compass_y, &compass_z);
            Serial.print(".");
        }
        
        compass_x_scaled = compass_x * mgPerDigit;
        compass_y_scaled = compass_y * mgPerDigit;
        compass_z_scaled = compass_z * mgPerDigit;
        
        // Taking the average of the offsets
        maggainerr[0] = (float)((COMPASS_XY_EXCITATION / abs(compass_x_scaled)) + compass_x_gainError) / 2;
        maggainerr[1] = (float)((COMPASS_XY_EXCITATION / abs(compass_y_scaled)) + compass_y_gainError) / 2;
        maggainerr[2] = (float)((COMPASS_Z_EXCITATION / abs(compass_z_scaled)) + compass_z_gainError) / 2;
        Serial.println("");
        Serial.print("            Gain:");
        Serial.print(maggainerr[0]);Serial.print(",  ");
        Serial.print(maggainerr[1]);Serial.print(",  ");
        Serial.println(maggainerr[2]);
        Serial.println("        Done");
    }
    
    // Configuring the Control register for normal mode
    Wire.beginTransmission(devAddr);
    Wire.write(0x00);
    Wire.write(0b01111000); // bit configuration = 0 A A DO2 DO1 DO0 MS1 MS2
    
    /*
     A A                        DO2 DO1 DO0      Sample Rate [Hz]      MS1 MS0    Measurment Mode
     0 0 = No Average            0   0   0   =   0.75                   0   0   = Normal
     0 1 = 2 Sample average      0   0   1   =   1.5                    0   1   = Positive Bias
     1 0 = 4 Sample Average      0   1   0   =   3                      1   0   = Negative Bais
     1 1 = 8 Sample Average      0   1   1   =   7.5                    1   1   = -
     1   0   0   =   15 (Default)
     1   0   1   =   30
     1   1   0   =   75
     1   1   1   =   -
     */
    Wire.endTransmission();
    
    // *****************************************************************************************
    // Offset estimation
    // *****************************************************************************************
    if (select == 2 | select == 3)
    {
        Serial.println("          Calibrating the Magnetometer (Offset)  ");

        // User input in the function
        for(i=0 ; i<50 ; i++)
        {
            getRawHeading(&compass_x, &compass_y, &compass_z); // Disregarding the first data
            delay(10);
        }
        
        float x_max=-4000,y_max=-4000,z_max=-4000;
        float x_min=4000,y_min=4000,z_min=4000;
        float last_time = 0;
        
        unsigned long t = millis();
        Serial.println("                Rotate Sensor for 20 Sec. ");
        while(millis()-t <= 20000)
        {
            getRawHeading(&compass_x, &compass_y, &compass_z);
            
            compass_x_scaled = (float)compass_x * mgPerDigit * maggainerr[0];
            compass_y_scaled = (float)compass_y * mgPerDigit * maggainerr[1];
            compass_z_scaled = (float)compass_z * mgPerDigit * maggainerr[2];
            
            x_max = max(x_max, compass_x_scaled);
            y_max = max(y_max, compass_y_scaled);
            z_max = max(z_max, compass_z_scaled);
            
            x_min = min(x_min, compass_x_scaled);
            y_min = min(y_min, compass_y_scaled);
            z_min = min(z_min, compass_z_scaled);

            if(((millis()-t) - last_time) > 1000)
            {
                last_time = millis() - t;
                Serial.print(".");
            }

            delay(10);
        }
        
        magoffset[0] = ((x_max - x_min) / 2) - x_max;
        magoffset[1] = ((y_max - y_min) / 2) - y_max;
        magoffset[2] = ((z_max - z_min) / 2) - z_max;
        Serial.println("");
        Serial.print("            Offset:");
        Serial.print(magoffset[0]);Serial.print(",  ");
        Serial.print(magoffset[1]);Serial.print(",  ");
        Serial.println(magoffset[2]);
        Serial.println("        Done");        
    }
    
}
Ejemplo n.º 3
0
bool HMC5883L::calibrate(int8_t testGain) {

	// Keep the current status ...
	uint8_t previousGain = getGain();

	// Set the gain
	if (testGain < 0) {
		testGain = gain;
	}
	setGain(testGain);

	// To check the HMC5883L for proper operation, a self test
	// feature in incorporated in which the sensor offset straps
	// are excited to create a nominal field strength (bias field)
	// to be measured. To implement self test, the least significant
	// bits (MS1 and MS0) of configuration register A are changed
	// from 00 to 01 (positive bias) or 10 (negetive bias)
	setMeasurementBias(HMC5883L_BIAS_POSITIVE);

	// Then, by placing the mode register into single-measurement mode ...
	setMode(HMC5883L_MODE_SINGLE);

	// Two data acquisition cycles will be made on each magnetic vector.
	// The first acquisition will be a set pulse followed shortly by
	// measurement data of the external field. The second acquisition
	// will have the offset strap excited (about 10 mA) in the positive
	// bias mode for X, Y, and Z axes to create about a ±1.1 gauss self
	// test field plus the external field.
	// The first acquisition values will be subtracted from the
	// second acquisition, and the net measurement will be placed into
	// the data output registers.
	int16_t x,y,z;
	getRawHeading(&x,&y,&z);

	// In the event the ADC reading overflows or underflows for the
	// given channel, or if there is a math overflow during the bias
	// measurement, this data register will contain the value -4096.
	// This register value will clear when after the next valid
	// measurement is made.
	if (min(x,min(y,z)) == -4096) {
		scaleFactors[testGain][0] = 1.0f;
		scaleFactors[testGain][1] = 1.0f;
		scaleFactors[testGain][2] = 1.0f;
		return false;
	}
	getRawHeading(&x,&y,&z);

	if (min(x,min(y,z)) == -4096) {
		scaleFactors[testGain][0] = 1.0f;
		scaleFactors[testGain][1] = 1.0f;
		scaleFactors[testGain][2] = 1.0f;
		return false;
	}

	// Since placing device in positive bias mode
	// (or alternatively negative bias mode) applies
	// a known artificial field on all three axes,
	// the resulting ADC measurements in data output
	// registers can be used to scale the sensors.
	float xExpectedSelfTestValue =
			HMC5883L_SELF_TEST_X_AXIS_ABSOLUTE_GAUSS *
			HMC5883L_LSB_PER_GAUS[testGain];
	float yExpectedSelfTestValue =
			HMC5883L_SELF_TEST_Y_AXIS_ABSOLUTE_GAUSS *
			HMC5883L_LSB_PER_GAUS[testGain];
	float zExpectedSelfTestValue =
			HMC5883L_SELF_TEST_Z_AXIS_ABSOLUTE_GAUSS *
			HMC5883L_LSB_PER_GAUS[testGain];

	scaleFactors[testGain][0] = xExpectedSelfTestValue/x;
	scaleFactors[testGain][1] = yExpectedSelfTestValue/y;
	scaleFactors[testGain][2] = zExpectedSelfTestValue/z;

	setGain(previousGain);
	setMeasurementBias(HMC5883L_BIAS_NORMAL);

	return true;

}
Ejemplo n.º 4
0
/** Get raw Z-axis heading measurement.
 * @return 16-bit signed integer with Z-axis heading
 * @see HMC5883L_RA_DATAZ_H
 */
int16_t HMC5883L::getRawHeadingZ() {
	int16_t x,y,z;
	getRawHeading(&x,&y,&z);
    return z;
}