HMC5883L作為一個IIC兼容裝置,該裝置包含一個7-bit串行地址,并支持IIC協議。HMC5883L可以支持標準和快速模式,分別為100kHz和400kHz,但不支持高速模式(Hs)。
要求主機的活動(寄存器讀取和寫入)優先于內部活動,例如測量,這一優先次序的安排是為了不讓主機等待,同時IIC總線占用的事件比必須的時間長。
如果磁力計在含有附加的局部磁場的環境中進行操作,磁力計的輸出做附加的修正將是必要的。 在沒有任何本地磁場的影響下,下圖1可以通過旋轉設備360°產生的平面 ,圖2為引入本地磁場。
方法一。修正的輸出可以根據下面的方法來計算:
1)在磁場干擾的條件下進行,數據收集設備被旋轉360°。
2)數據進行分析,以產生偏差的偏移和靈敏度的比例因子,以補償所述干擾。
例子:
從數據中發現的X和Y磁強計的最大輸出:
Xmin = -0.284gauss Xmax = +0.402gauss
Ymin = -0.322gauss Ymax = +0.246gauss
從中可以看出X軸的數據,X具有更大的反應,我們設置其比例系數為1
Xs = 1
再計算其他比例系數:
(Xmax - Xmin)
Ys = ————————
(Ymax - Ymin)
對于偏置補償:
Xb = Xs[1/2(Xmax - Xmin) - Xmax ]
Yb = Ys[1/2(Ymax - Ymin) - Ymax ]
正確的輸出:
Xout = Xin*Xs + Xb
Yout = Yin*Ys + Yb
方法二。
1)水平勻速旋轉,收集XY軸數據
2)轉動器材90度(Z軸)勻速轉動以收集Z軸數據
Xoffset = (Xmax + Xmin)/2
Yoffset = (Ymax + Ymin)/2
Zoffset = (Zmax + Zmin)/2
將磁力計讀到的裸值減去offset,得到用做角度計算的Heading值
XH = X - Xoffset
YH = Y - Yoffset
ZH = Z - Zoffset
水平測試,得到的方位角 = arctanYH/XH
非水平測試,需要使用加速計進行傾角補償,先計算出翻滾角Roll和俯仰角Pitch,然后計算Heading值:
XH = x*cos(P)+Y*sin(R)*sin(P)-Z*cos(R)*sin(p)
YH = Y*cos(R)+Z*sin(R)
關于為什么設置偏置,請參考以下文章:
ST集成傳感器方案實現電子羅盤功能:http://www.dzsc.com/data/html/2010-11-29/87454.html
HMC5883L常見問題解答:http://blog.sina.com.cn/s/blog_402c071e0102v8gj.html
這里我采用了上方的簡單方法,來計算一個 offsetX, offsetY, offsetZ,然后減去這個偏移量,得到了正確的結果。下方是代碼。下方我做了一個處理(諸如:mag.x*0.2 + magRange[0]*0.8)。是因為偶爾mag.x mag.y mag.z 會出現一個異常的值,使得計算的offsetX offsetY offsetZ不準,所以加了這個濾波處理。
static float magRange[6] = {1.0,-1.0,1.0,-1.0,1.0,-1.0};// magRange[0] 對應X最小,magRange[1] 對應X最大
// Magnetometer not yet used more then for logging.
// 磁力計尚未使用到,僅僅只是 log 記錄下來。
imu9Read(&gyro, &acc, &mag);
if(magRange[0] 》 mag.x) magRange[0] = mag.x*0.2 + magRange[0]*0.8; // x min
if(magRange[1] 《 mag.x) magRange[1] = mag.x*0.2 + magRange[1]*0.8; // x max
if(magRange[2] 》 mag.y) magRange[2] = mag.y*0.2 + magRange[2]*0.8;
if(magRange[3] 《 mag.y) magRange[3] = mag.y*0.2 + magRange[3]*0.8;
if(magRange[4] 》 mag.z) magRange[4] = mag.z*0.2 + magRange[4]*0.8; // z min
if(magRange[5] 《 mag.z) magRange[5] = mag.z*0.2 + magRange[5]*0.8; // z max
magOffset[0] = (magRange[0]+magRange[1])/2.0;
magOffset[1] = (magRange[2]+magRange[3])/2.0;
magOffset[2] = (magRange[4]+magRange[5])/2.0;
mag.x -= magOffset[0];
mag.y -= magOffset[1];
mag.z -= magOffset[2];
自我檢測也比較重要。通過HMC5883l芯片提供的自我檢測功能,進行自我檢測,然后找到一個比例因子。將傳感器的檢測值乘以這個比例因子,就可以修正磁場。我在代碼中沒有使用。相關的詳細資料請看如下英文。
相關源代碼,可以參考 Crazyflie firmware中的 bool hmc5883lSelfTest() 函數。
SELF TEST OPERATION
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), e.g. 0x11 or 0x12.
Then, by placing the mode register into single-measurement mode (0x01), 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.
Since self test adds ~1.1 Gauss additional field to the existing field strength, using a reduced gain setting prevents sensor from being saturated and data registers overflowed. For example, if the configuration register B is set to 0x60 (Gain=3), values around +766 LSB (1.16 Ga * 660 LSB/Ga) will be placed in the X and Y data output registers and around +713 (1.08 Ga * 660 LSB/Ga) will be placed in Z data output register. To leave the self test mode, change MS1 and MS0 bit of the configuration register A back to 00 (Normal Measurement Mode), e.g. 0x10.
比例因子校準
SCALE FACTOR CALIBRATION
Using the self test method described above, the user can scale sensors’ sensitivity to match each other. 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. For example, if the expected self test value for X-axis is 766 and the actual value is 750 then a scale factor of (766/750) should be multiplied to all future readings of X-axis. Doing so for all three axes will ensure their sensitivity are well matched.
The built-in self test can also be used to periodically compensate the scaling errors due to temperature variations. A compensation factor can be found by comparing the self test outputs with the ones obtained at a known temperature. For example, if the self test output is 750 at room temperature and 700 at the current temperature then a compensation factor of (750/700) should be applied to all current magnetic readings. A temperature sensor is not required using this method.
Crazyflie firmware中的 bool hmc5883lSelfTest() 函數代碼如下,僅供參考:(函數中的各種定義這里未給出)
bool hmc5883lSelfTest()
{
bool testStatus = TRUE;
int16_t mxp, myp, mzp; // positive magnetometer measurements
int16_t mxn, myn, mzn; // negative magnetometer measurements
struct
{
uint8_t configA;
uint8_t configB;
uint8_t mode;
} regSave;
// Save register values
if (i2cdevRead(I2Cx, devAddr, HMC5883L_RA_CONFIG_A, sizeof(regSave), (uint8_t *)?Save) == FALSE)
{
// TODO: error handling
return FALSE;
}
// Set gain (sensitivity)
hmc5883lSetGain(HMC5883L_ST_GAIN);
// Write CONFIG_A register and do positive test
i2cdevWriteByte(I2Cx, devAddr, HMC5883L_RA_CONFIG_A,
(HMC5883L_AVERAGING_1 《《 (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
(HMC5883L_RATE_15 《《 (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
(HMC5883L_BIAS_POSITIVE 《《 (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1)));
hmc5883lSetMode(HMC5883L_MODE_SINGLE);
vTaskDelay(M2T(HMC5883L_ST_DELAY_MS));
hmc5883lGetHeading(&mxp, &myp, &mzp);
// Write CONFIG_A register and do negative test
i2cdevWriteByte(I2Cx, devAddr, HMC5883L_RA_CONFIG_A,
(HMC5883L_AVERAGING_1 《《 (HMC5883L_CRA_AVERAGE_BIT - HMC5883L_CRA_AVERAGE_LENGTH + 1)) |
(HMC5883L_RATE_15 《《 (HMC5883L_CRA_RATE_BIT - HMC5883L_CRA_RATE_LENGTH + 1)) |
(HMC5883L_BIAS_NEGATIVE 《《 (HMC5883L_CRA_BIAS_BIT - HMC5883L_CRA_BIAS_LENGTH + 1)));
hmc5883lSetMode(HMC5883L_MODE_SINGLE);
vTaskDelay(M2T(HMC5883L_ST_DELAY_MS));
hmc5883lGetHeading(&mxn, &myn, &mzn);
if (hmc5883lEvaluateSelfTest(HMC5883L_ST_X_MIN, HMC5883L_ST_X_MAX, mxp, “pos X”) &&
hmc5883lEvaluateSelfTest(HMC5883L_ST_Y_MIN, HMC5883L_ST_Y_MAX, myp, “pos Y”) &&
hmc5883lEvaluateSelfTest(HMC5883L_ST_Z_MIN, HMC5883L_ST_Z_MAX, mzp, “pos Z”) &&
hmc5883lEvaluateSelfTest(-HMC5883L_ST_X_MAX, -HMC5883L_ST_X_MIN, mxn, “neg X”) &&
hmc5883lEvaluateSelfTest(-HMC5883L_ST_Y_MAX, -HMC5883L_ST_Y_MIN, myn, “neg Y”) &&
hmc5883lEvaluateSelfTest(-HMC5883L_ST_Z_MAX, -HMC5883L_ST_Z_MIN, mzn, “neg Z”))
{
DEBUG_PRINT(“Self test [OK]。\n”);
}
else
{
testStatus = FALSE;
}
// Restore registers
if (i2cdevWrite(I2Cx, devAddr, HMC5883L_RA_CONFIG_A, sizeof(regSave), (uint8_t *)?Save) == FALSE)
{
// TODO: error handling
return FALSE;
}
return testStatus;
}
評論
查看更多