背景资料
我从亚马逊买了一个带QMC5883芯片的Arduino磁力计指南针,然而我得到的轴承输出与我在网上找到的计算结果并不一致。序列输出似乎是可信的(相位差为90°的正弦波),但我得到的计算轴承的数字与应该的不一致。我将串行输出存储为一个.csv文件,以便在Excel中绘制磁力计转过360°时的响应图。
响应大致符合预期–Z大致保持稳定(除了电缆引起的一些晃动!),X和Y通过360°正弦变化。(请记住,我不能用手以恒定的速度转动磁力计,这就是为什么曲线如此不稳定的原因)。
不过下面是计算出的航向图,结果应该是在-180°到+180°之间。
正如你所看到的,它只在-60°到-160°左右变化,而且每个方位的读数都不是唯一的,因为它是由磁力计的两个不同的旋转给出的。所用代码中的具体计算方法(全文在底部)是。
bearing =180*atan2(y,x)/3.141592654; //values will range from +180 to -180°
bearing +=0-(19/60); //Adjust for local magnetic declination
问题:
我不知道这个计算有什么问题,因为它在一些不同的来源中使用,我想知道如何将我得到的读数转换为一个可用的范围,即一比一,而不是多比一,例如-180°到+180°或0°到360°。
下面是代码。
//There are several differences between the QMC5883L and the HMC5883L chips
//Differences in address: 0x0D for QMC5883L; 0x1E for HMC5883L
//Differences in register map (compare datasheets)
//Output data register differences include location of x,y,z and MSB and LSB for these parameters
//Control registers are also different (so location and values for settings change)
#include <Wire.h> //I2C Arduino Library
#define addr 0x0D //I2C Address for The QMC5883L (0x1E for HMC5883)
double scale=1.0;
void setup() {
// double scaleValues[9]={0.00,0.73,0.92,1.22,1.52,2.27,2.56,3.03,4.35};
// scale=scaleValues[2];
//initialize serial and I2C communications
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(addr); //start talking to slave
Wire.write(0x0B);
Wire.write(0x01);
Wire.endTransmission();
Wire.beginTransmission(addr); //start talking to slave
Wire.write(0x09);
Wire.write(0x1D);
Wire.endTransmission();
}
void loop() {
int x, y, z; //triple axis data
//Tell the QMC what regist to begin writing data into
Wire.beginTransmission(addr);
Wire.write(0x00); //start with register 00H for QMC5883L
Wire.endTransmission();
double bearing=0.00;
//Read the data.. 2, 8 bit bytes for each axis.. 6 total bytes
Wire.requestFrom(addr, 6);
//read 6 registers in order; register location (i.e.00H)indexes by one once read
if (6 <= Wire.available()) {
//note the order of following statements matters
//as each register will be read in sequence starting from data register 00H to 05H
//where order is xLSB,xMSB,yLSB,yMSB,zLSB,zMSB
//this is different from HMC5883L!
//data registers are 03 to 08
//where order is xMSB,xLSB,zMSB,zLSB,yMSB,yLSB
x = Wire.read(); //LSB x;
x |= Wire.read()<<8; //MSB x; bitshift left 8, then bitwise OR to make "x"
// x*=scale;
y = Wire.read(); //LSB y
y |= Wire.read()<<8; //MSB y;
// y*=scale;
z = Wire.read(); //LSB z; irrelevant for compass
z |= Wire.read()<<8; //MSB z;
// z*=scale;
bearing =180*atan2(y,x)/3.141592654;//values will range from +180 to -180 degrees
bearing +=0-(19/60);//Adjust for local magnetic declination
}
// Show Values
//Serial.print("X:");
Serial.print(x);
//Serial.print(" Y: ");
Serial.print(",");
Serial.print(y);
//Serial.print(" Z: ");
Serial.print(",");
Serial.print(z);
//Serial.print(" B: ");
Serial.print(",");
Serial.println(bearing);
delay(500);
}
解决方案:
对于其他读到这个问题的人。上位机忘了实现x,y,z的平滑和去除范围外的值。如何实现这个功能,其实现方法请看这个源码 QMC5883罗盘库:
QMC5883L Compass是一个Arduino库,用于使用QMC5583L系列芯片板作为指南针。
它支持的功能有
- 获取XYZ轴的数值。
- 计算方位角。
- 获取16点方位角方向(0-15)。
- 获取16点方位角方位名称(N、NNE、NE、ENE、E、ESE、SE、SSE、S、SSW、SW、SW、W、WNW、NW、NNW)。
- 通过滚动平均和最小最大删除对XYZ读数进行平滑处理。
本文来自投稿,不代表运维实战侠立场,如若转载,请注明出处:https://www.shizhanxia.com/898.html