i2c总线上LSM303DLHC传感器的磁力计输出不稳定。问题写作gobot飞行员

时间:2018-11-29 14:50:52

标签: go i2c gobot.io

我使用Adafruit LSM303DLHC传感器。它由2个传感器,加速度计和磁力计组成。 我目前正在为该传感器编写驱动程序,以便通过Raspberry Pi 2上的 i2c 界面与gobot.io软件包一起使用。

问题:加速度计部分正常工作。磁力计传感器部件没有。我可以读取磁场寄存器,但得到的值没有意义。 这些值在每个阅读周期之间都会更新,但是它们变化不大且没有意义。

使用的设备:

  • LSM303DLHC传感器-Datasheet
  • Raspberry Pi 2
  • Arduino Uno

有关读取磁力计输出的详细信息:

LSM303DLHC输出6个字节,代表沿3轴的3个磁场值。 每个轴的每个值由2个字节(16位)组成。输出顺序如下:

  • X高字节
  • X个低字节
  • Z高字节
  • Z低字节
  • Y高字节
  • Y低字节

为了设置传感器,我们按以下顺序写入以下寄存器:

  • 重置磁力计增益:将0x00写入CRB_REG_M寄存器(0x01)
  • 设置磁力计增益:将0x60(+/- 2.5高斯)写入CRB_REG_M寄存器(0x01)
  • 设置输出数据速率:在CRA_REG_M寄存器(0x00)中写入0x05(30 Hz)
  • 启用连续模式:在MR_REG_M寄存器中写入0x00

设置传感器后,我们可以读取输出。为了读取它,我们写入6个输出寄存器中的第1个。然后我们一口气读取6个寄存器的输出,将6个字节放入缓冲区。

测试已完成

  1. 使用Adafruit的库和Arduino平台:确定-输出正常
  2. 使用Raspberry Pi 2 + python示例:确定-输出正常
  3. 使用Raspberry Pi 2 + gobot.io + lsm303DLHC驱动程序:错误
  4. 使用io.ReadFull()代替注释中建议的io.Read():错误

前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中工作。

我先感谢那些花时间阅读我的人。

0 个答案:

没有答案