HMC5883L作為一個(gè)IIC兼容裝置,該裝置包含一個(gè)7-bit串行地址,并支持IIC協(xié)議。HMC5883L可以支持標(biāo)準(zhǔn)和快速模式,分別為100kHz和400kHz,但不支持高速模式(Hs)。
要求主機(jī)的活動(dòng)(寄存器讀取和寫入)優(yōu)先于內(nèi)部活動(dòng),例如測(cè)量,這一優(yōu)先次序的安排是為了不讓主機(jī)等待,同時(shí)IIC總線占用的事件比必須的時(shí)間長(zhǎng)。
如果磁力計(jì)在含有附加的局部磁場(chǎng)的環(huán)境中進(jìn)行操作,磁力計(jì)的輸出做附加的修正將是必要的。 在沒有任何本地磁場(chǎng)的影響下,下圖1可以通過旋轉(zhuǎn)設(shè)備360°產(chǎn)生的平面 ,圖2為引入本地磁場(chǎng)。

方法一。修正的輸出可以根據(jù)下面的方法來計(jì)算:
1)在磁場(chǎng)干擾的條件下進(jìn)行,數(shù)據(jù)收集設(shè)備被旋轉(zhuǎn)360°。
2)數(shù)據(jù)進(jìn)行分析,以產(chǎn)生偏差的偏移和靈敏度的比例因子,以補(bǔ)償所述干擾。
例子:
從數(shù)據(jù)中發(fā)現(xiàn)的X和Y磁強(qiáng)計(jì)的最大輸出:
Xmin = -0.284gauss Xmax = +0.402gauss
Ymin = -0.322gauss Ymax = +0.246gauss
從中可以看出X軸的數(shù)據(jù),X具有更大的反應(yīng),我們?cè)O(shè)置其比例系數(shù)為1
Xs = 1
再計(jì)算其他比例系數(shù):
(Xmax - Xmin)
Ys = ————————
(Ymax - Ymin)
對(duì)于偏置補(bǔ)償:
Xb = Xs[1/2(Xmax - Xmin) - Xmax ]
Yb = Ys[1/2(Ymax - Ymin) - Ymax ]
正確的輸出:
Xout = Xin*Xs + Xb
Yout = Yin*Ys + Yb
方法二。
1)水平勻速旋轉(zhuǎn),收集XY軸數(shù)據(jù)
2)轉(zhuǎn)動(dòng)器材90度(Z軸)勻速轉(zhuǎn)動(dòng)以收集Z軸數(shù)據(jù)
Xoffset = (Xmax + Xmin)/2
Yoffset = (Ymax + Ymin)/2
Zoffset = (Zmax + Zmin)/2
將磁力計(jì)讀到的裸值減去offset,得到用做角度計(jì)算的Heading值
XH = X - Xoffset
YH = Y - Yoffset
ZH = Z - Zoffset
水平測(cè)試,得到的方位角 = arctanYH/XH
非水平測(cè)試,需要使用加速計(jì)進(jìn)行傾角補(bǔ)償,先計(jì)算出翻滾角Roll和俯仰角Pitch,然后計(jì)算Heading值:
XH = x*cos(P)+Y*sin(R)*sin(P)-Z*cos(R)*sin(p)
YH = Y*cos(R)+Z*sin(R)
關(guān)于為什么設(shè)置偏置,請(qǐng)參考以下文章:
ST集成傳感器方案實(shí)現(xiàn)電子羅盤功能:http://www.dzsc.com/data/html/2010-11-29/87454.html
HMC5883L常見問題解答:http://blog.sina.com.cn/s/blog_402c071e0102v8gj.html
這里我采用了上方的簡(jiǎn)單方法,來計(jì)算一個(gè) offsetX, offsetY, offsetZ,然后減去這個(gè)偏移量,得到了正確的結(jié)果。下方是代碼。下方我做了一個(gè)處理(諸如:mag.x*0.2 + magRange[0]*0.8)。是因?yàn)榕紶杕ag.x mag.y mag.z 會(huì)出現(xiàn)一個(gè)異常的值,使得計(jì)算的offsetX offsetY offsetZ不準(zhǔn),所以加了這個(gè)濾波處理。
static float magRange[6] = {1.0,-1.0,1.0,-1.0,1.0,-1.0};// magRange[0] 對(duì)應(yīng)X最小,magRange[1] 對(duì)應(yīng)X最大
// Magnetometer not yet used more then for logging.
// 磁力計(jì)尚未使用到,僅僅只是 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];
自我檢測(cè)也比較重要。通過HMC5883l芯片提供的自我檢測(cè)功能,進(jìn)行自我檢測(cè),然后找到一個(gè)比例因子。將傳感器的檢測(cè)值乘以這個(gè)比例因子,就可以修正磁場(chǎng)。我在代碼中沒有使用。相關(guān)的詳細(xì)資料請(qǐng)看如下英文。
相關(guān)源代碼,可以參考 Crazyflie firmware中的 bool hmc5883lSelfTest() 函數(shù)。
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.
比例因子校準(zhǔn)
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() 函數(shù)代碼如下,僅供參考:(函數(shù)中的各種定義這里未給出)
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;
}
電子發(fā)燒友App







評(píng)論