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

问题描述 投票:0回答:1

我正在Sparkfun红板Turbo(处理器samd21g18)和旧的arduino uno(处理器mega16u2)上都使用I2C运行ADXL345。我在两块板上都使用的库和草图相同,不同之处在于串行端口已更改为SerialUSB以容纳该红板。

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

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

enter image description here

我相信令人反感的代码在以下库代码中。

/*********************** 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); 
}

声明.b文件头中的_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;

我认为需要修改红板库,以读取输出寄存器0x32-0x37,作为16位二进制补码。我是此编程环境的新手,因此感谢您的帮助。

谢谢-杰里

c++ arduino accelerometer
1个回答
0
投票

我从Sparkfun董事会笔记(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来确保字节移位发生在无符号值上,因为左移有符号数会在某些处理器上产生意外的结果。

© www.soinside.com 2019 - 2024. All rights reserved.