用于 sparkfun redboard turbo 的 ADXL345 库给出错误的读数

ADXL345 library for sparkfun redboard turbo giving wrong readings

我是 运行 在 sparkfun redboard turbo(处理器 samd21g18)和旧的 arduino uno(处理器 mega16u2)上使用 I2C 的 ADXL345。我在两块板上使用的库和草图是相同的,除了串行端口更改为 SerialUSB 以适应红板。

问题似乎是 uno 将 xyz 寄存器(寄存器 0x​​32 - 0x37 中每轴 2 个字节)解释为 16 位二进制补码(根据数据表),而红板则不然。 uno的输出是正确的,红板的输出是错误的,都是正整数输出。

下图显示了 ADXL345 相同相对位置下左侧红板和右侧 uno 的输出。

我认为有问题的代码在以下库代码中。

/*********************** READING ACCELERATION ***********************/
/*    Reads Acceleration into Three Variables:  x, y and z          */

void ADXL345::readAccel(int *xyz){
    readAccel(xyz, xyz + 1, xyz + 2);
}

void ADXL345::readAccel(int *x, int *y, int *z) {
    readFrom(ADXL345_DATAX0, ADXL345_TO_READ, _buff);   // Read Accel Data from ADXL345

    // Each Axis @ All g Ranges: 10 Bit Resolution (2 Bytes)
    *x = (((int)_buff[1]) << 8) | _buff[0];
    *y = (((int)_buff[3]) << 8) | _buff[2];
    *z = (((int)_buff[5]) << 8) | _buff[4];
}

草图代码如下:

#include <SparkFun_ADXL345.h>


/*********** COMMUNICATION SELECTION ***********/
/*    Comment Out The One You Are Not Using    */
//ADXL345 adxl = ADXL345(10);           // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

/****************** INTERRUPT ******************/
/*      Uncomment If Attaching Interrupt       */
//int interruptPin = 2;                 // Setup pin 2 to be the interrupt pin (for most Arduino Boards)


/******************** SETUP ********************/
/*          Configure ADXL345 Settings         */
void setup(){

  SerialUSB.begin(9600);                 // Start the SerialUSB terminal
  SerialUSB.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
  SerialUSB.println();

  adxl.powerOn();                     // Power on the ADXL345

  adxl.setRangeSetting(2);           // Give the range settings
                                      // Accepted values are 2g, 4g, 8g or 16g
                                      // Higher Values = Wider Measurement Range
                                      // Lower Values = Greater Sensitivity

} 
/****************** MAIN CODE ******************/
/*     Accelerometer Readings and Interrupt    */
void loop(){

  // Accelerometer Readings
  int x,y,z;   
  adxl.readAccel(&x, &y, &z);         // Read the accelerometer values and store them in variables declared above x,y,z

  // Output Results to SerialUSB
  /* UNCOMMENT TO VIEW X Y Z ACCELEROMETER VALUES */  
  SerialUSB.print(x);
  SerialUSB.print(", ");
  SerialUSB.print(y);
  SerialUSB.print(", ");
  SerialUSB.println(z);
  adxl.printAllRegister();
  delay(10); 
}

头文件.h中声明_buff[]的代码:

private:
    void writeTo(byte address, byte val);
    void writeToI2C(byte address, byte val);
    void writeToSPI(byte address, byte val);
    void readFrom(byte address, int num, byte buff[]);
    void readFromI2C(byte address, int num, byte buff[]);
    void readFromSPI(byte address, int num, byte buff[]);
    void setRegisterBit(byte regAdress, int bitPos, bool state);
    bool getRegisterBit(byte regAdress, int bitPos);
    byte _buff[6] ;     //  6 Bytes Buffer
    int _CS = 10;
    bool I2C = true;
    unsigned long SPIfreq = 5000000;

我认为需要修改红板库以将输出寄存器 0x​​32-0x37 读取为 16 位二进制补码。我是这个编程环境的新手,所以感谢任何帮助。

谢谢 - 杰瑞

我从 Sparkfun board notes (https://www.sparkfun.com/products/14812) 怀疑问题是 Redboard Turbo 是一个 32 位处理器,具有 32 位 int 而不是 16 位 int。在这样的处理器上,存储在 int 中的所有 16 位值都是正值。

为了检验我的理论,运行 Redboard Turbo 上的以下草图:

void setup() {
  Serial.begin(9600);
  while (!Serial) {}

  Serial.print("sizeof(int) = ");
  Serial.println(sizeof(int));
}

void loop() {
}

在我的 Arduino Uno - 一个 16 位环境 - 输出表明一个 int 是两个字节(16 位)

sizeof(int) = 2

如果你的 Redboard Turbo 打印出来

sizeof(int) = 4

那么它的int是4个字节(32位)。

我怀疑该库不是为 32 位处理器编写的,并且可能会在 Redboard Turbo 上显示一些问题。要修复特定的 readAccel() 函数,请重写它以将 16 位数字符号扩展为 32 位:

  int16_t i16;  // the 16-bit result, signed.

  i16 = (int16_t) ((((uint16_t)_buff[1]) << 8) | _buff[0]);
  *x = (int) i16;

  i16 = (int16_t) ((((uint16_t)_buff[3]) << 8) | _buff[2]);
  *y = (int) i16;

  i16 = (int16_t) ((((uint16_t)_buff[5]) << 8) | _buff[4]);
  *z = (int) i16;

顺便说一句,在上面的 readAccel() 重写中,我使用了 uint16_t 来确保字节移位发生在无符号值上,因为左移有符号数可能会产生意想不到的结果一些处理器。