我使用Adafruit LSM303DLHC传感器。它由2个传感器,加速度计和磁力计组成。 我目前正在为该传感器编写驱动程序,以便通过Raspberry Pi 2上的 i2c 界面与gobot.io软件包一起使用。
问题:加速度计部分正常工作。磁力计传感器部件没有。我可以读取磁场寄存器,但得到的值没有意义。 这些值在每个阅读周期之间都会更新,但是它们变化不大且没有意义。
使用的设备:
有关读取磁力计输出的详细信息:
LSM303DLHC输出6个字节,代表沿3轴的3个磁场值。 每个轴的每个值由2个字节(16位)组成。输出顺序如下:
为了设置传感器,我们按以下顺序写入以下寄存器:
设置传感器后,我们可以读取输出。为了读取它,我们写入6个输出寄存器中的第1个。然后我们一口气读取6个寄存器的输出,将6个字节放入缓冲区。
测试已完成
前2个测试(1和2)告诉我传感器正常工作。没坏 i2c速度不是这里的罪魁祸首,因为python程序(2)也可以工作。
当从字节中正确地形成int16值时,我怀疑我的代码有问题。 我的驱动程序代码部分,以读取传感器输出并形成结果值
此代码位于〜/ go / src / gobot.io / x / gobot / drivers / i2c / lsm303DLHC.go(也称为驱动程序)中
func (d *LSM303Driver) MagneticField() (x, z, y float32, err error) {
// Write to the first output register to start the reading procedure
if _, err = d.Magnetometer.connection.Write([]byte{lsm303RegisterMagOutXLSB}); err != nil {
return 0, 0, 0, err
}
// create a buffer to put the output bytes
measurements := make([]byte, 6)
// read the 6 output bytes
if _, err = d.Magnetometer.connection.Read(measurements); err != nil {
return 0, 0, 0, err
}
var rawXh uint8
var rawXl uint8
var rawZh uint8
var rawZl uint8
var rawYh uint8
var rawYl uint8
buf := bytes.NewBuffer(measurements)
binary.Read(buf, binary.BigEndian, &rawXh)
binary.Read(buf, binary.BigEndian, &rawXl)
binary.Read(buf, binary.BigEndian, &rawZh)
binary.Read(buf, binary.BigEndian, &rawZl)
binary.Read(buf, binary.BigEndian, &rawYh)
binary.Read(buf, binary.BigEndian, &rawYl)
rawX := int16((uint16(rawXh) << 8) | uint16(rawXl))
rawZ := int16((uint16(rawZh) << 8) | uint16(rawZl))
rawY := int16((uint16(rawYh) << 8) | uint16(rawYl))
// Gain is set to +/- 2.5 LSB/Gauss (Least Significant Byte)
// Datasheet page 38
// Unit convertion: gaussToMicroTesla = 100
gainXY, gainZ := d.getGainXYZ()
x = float32(rawX) / float32(gainXY) * float32(gaussToMicroTesla)
z = float32(rawZ) / float32(gainZ) * float32(gaussToMicroTesla)
y = float32(rawY) / float32(gainXY) * float32(gaussToMicroTesla)
fmt.Printf("DEBUG rawX %016b ---> %v \t\t|\t X %v\n", rawX, rawX, x)
fmt.Printf("DEBUG rawZ %016b ---> %v \t\t|\t Z %v\n", rawZ, rawZ, z)
fmt.Printf("DEBUG rawY %016b ---> %v \t\t|\t Y %v\n\n", rawY, rawY, y)
return x, z, y, nil
}
这是我使用此功能的小程序的输出:
...
DEBUG rawX 0000001100101011 ---> 811 | X 121.04478
DEBUG rawZ 0000001011110111 ---> 759 | Z 126.5
DEBUG rawY 0000001100110000 ---> 816 | Y 121.79104
DEBUG rawX 0000001100101011 ---> 811 | X 121.04478
DEBUG rawZ 0000001011110111 ---> 759 | Z 126.5
DEBUG rawY 0000001100110000 ---> 816 | Y 121.79104
DEBUG rawX 0000001100100111 ---> 807 | X 120.44777
DEBUG rawZ 0000001011110110 ---> 758 | Z 126.33333
DEBUG rawY 0000001100101100 ---> 812 | Y 121.19403
...
您可以在每一行上看到rawX(Y-Z)二进制和正态表示,然后是微特斯拉中的确定值。 在所有情况下,这些值都相去甚远。即使当我向各个方向转动设备时,它们的变化也不会太大。
我密切关注了Adafruits C++ library的arduino,但没有发现任何重大差异。这是读取磁力计输出的Adafruit代码:
void Adafruit_LSM303_Mag_Unified::read()
{
// Read the magnetometer
Wire.beginTransmission((byte)LSM303_ADDRESS_MAG);
Wire.send(LSM303_REGISTER_MAG_OUT_X_H_M);
Wire.endTransmission();
Wire.requestFrom((byte)LSM303_ADDRESS_MAG, (byte)6);
// Wait around until enough data is available
while (Wire.available() < 6);
// Note high before low (different than accel)
uint8_t xhi = Wire.receive();
uint8_t xlo = Wire.receive();
uint8_t zhi = Wire.receive();
uint8_t zlo = Wire.receive();
uint8_t yhi = Wire.receive();
uint8_t ylo = Wire.receive();
// Shift values to create properly formed integer (low byte first)
raw.x = (int16_t)(xlo | ((int16_t)xhi << 8));
raw.y = (int16_t)(ylo | ((int16_t)yhi << 8));
raw.z = (int16_t)(zlo | ((int16_t)zhi << 8));
}
我想念一些大东西吗? (我希望如此...)
老实说,我在这个问题上花费了很多时间,但我却无处可去。我确实学到了很多有关linux内核和i2c协议,ioctl等的有趣知识...但是,即使加速度计可以工作,我仍然无法通过gobot.io使磁力计在golang中工作。>
我先感谢那些花时间阅读我的人。