带 Arduino 的 ITG3200 全速运行

Full speed on ITG3200 with Arduino

我正在为我的项目使用 ITG3200(Sparkfun 分线板)。我试图将 ITG3200 的采样率提高到 2K HZ 以上。我已经在传感器上焊接了两个 2.2K 上拉电阻并关闭时钟输入垫。我在这里遇到了一些问题。它连接到 Arduino Uno。

  1. 我能达到的最高采样率是 500 赫兹左右。我已将时钟更改为 400K。但是,如果不这样做,我仍然会得到超过 1000 Hz 的东西,对吧?我在下面附上了我的代码。

如有任何意见或建议,我们将不胜感激!

#include <SPI.h>
#include <Wire.h>

// Pin definitions - Shift registers:
int enPin = 13;  // Shift registers' Output Enable pin
int latchPin = 12;  // Shift registers' rclk pin
int clkPin = 11;  // Shift registers' srclk pin
int clrPin = 10;  // shift registers' srclr pin
int datPin = 8;  // shift registers' SER pin

int show = 0;
int lastMax = 0;


//This is a list of registers in the ITG-3200. Registers are parameters that determine how the sensor will behave, or they can hold data that represent the
//sensors current status.
//To learn more about the registers on the ITG-3200, download and read the datasheet.
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;//0x15
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;

//This is a list of settings that can be loaded into the registers.
//DLPF, Full Scale Register Bits
//FS_SEL must be set to 3 for proper operation
//Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
char DLPF_CFG_0 = 0;//1
char DLPF_CFG_1 = 0;//2
char DLPF_CFG_2 = 0;//4
char DLPF_FS_SEL_0 = 8;
char DLPF_FS_SEL_1 = 16;

char itgAddress = 0x69;

// Some of the math we're doing in this example requires the number of bargraph boards
// you have connected together (normally this is one, but you can have a maximum of 8).

void setup()
// Runs once upon reboot
{
  // Setup shift register pins
  pinMode(enPin, OUTPUT);  // Enable, active low, this'll always be LOW
  digitalWrite(enPin, LOW);  // Turn all outputs on
  pinMode(latchPin, OUTPUT);  // this must be set before calling shiftOut16()
  digitalWrite(latchPin, LOW);  // start latch low
  pinMode(clkPin, OUTPUT);  // we'll control this in shiftOut16()
  digitalWrite(clkPin, LOW);  // start sck low
  pinMode(clrPin, OUTPUT);  // master clear, this'll always be HIGH
  digitalWrite(clrPin, HIGH);  // disable master clear
  pinMode(datPin, OUTPUT);  // we'll control this in shiftOut16()
  digitalWrite(datPin, LOW);  // start ser low

  // To begin, we'll turn all LEDs on the circular bar-graph OFF
  digitalWrite(latchPin, LOW);  // first send latch low
  shiftOut16(0x0000);
  digitalWrite(latchPin, HIGH);  // send latch high to indicate data is done sending

  Serial.begin(230400);

  //Initialize the I2C communication. This will set the Arduino up as the 'Master' device.
  Wire.begin();

  //Read the WHO_AM_I register and print the result
  char id=0; 
  id = itgRead(itgAddress, 0x00);  
  Serial.print("ID: ");
  Serial.println(id, HEX);

  //Configure the gyroscope
  //Set the gyroscope scale for the outputs to +/-2000 degrees per second
  itgWrite(itgAddress, DLPF_FS, (DLPF_FS_SEL_0|DLPF_FS_SEL_1|DLPF_CFG_0));
  //Set the sample rate to 100 hz
  itgWrite(itgAddress, SMPLRT_DIV, 0);
}

void loop()
// Runs continuously after setup() ends
{
  static int zero = 0;

  // Create variables to hold the output rates.
  int xRate, yRate, zRate;
  float range = 3000.0;
  int divisor;

  divisor = range / 8;

  //Read the x,y and z output rates from the gyroscope.
  xRate = int(float(readX()) / divisor - 0.5) * -1;
  yRate = int(float(readY()) / divisor - 0.5) * -1;
  zRate = int(float(readZ()) / divisor - 0.5);

  //Print the output rates to the terminal, seperated by a TAB character.

  Serial.print(xRate);
  Serial.print('\t');
  Serial.print(yRate);
  Serial.print('\t');
  Serial.println(zRate);  
  Serial.print('\t');
//  Serial.println(zero);


//  fillTo(zRate);

  //Wait 10ms before reading the values again. (Remember, the output rate was set to 100hz and 1reading per 10ms = 100hz.)
//  delay(10);
}


// This function will write a value to a register on the itg-3200.
// Parameters:
//   char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
//   char registerAddress: The address of the register on the sensor that should be written to.
//   char data: The value to be written to the specified register.
void itgWrite(char address, char registerAddress, char data)
{
  //Initiate a communication sequence with the desired i2c device
  Wire.beginTransmission(address);
  //Tell the I2C address which register we are writing to
  Wire.write(registerAddress);
  //Send the value to write to the specified register
  Wire.write(data);
  //End the communication sequence
  Wire.endTransmission();
}

//This function will read the data from a specified register on the ITG-3200 and return the value.
//Parameters:
//  char address: The I2C address of the sensor. For the ITG-3200 breakout the address is 0x69.
//  char registerAddress: The address of the register on the sensor that should be read
//Return:
//  unsigned char: The value currently residing in the specified register
unsigned char itgRead(char address, char registerAddress)
{
  //This variable will hold the contents read from the i2c device.
  unsigned char data=0;

  //Send the register address to be read.
  Wire.beginTransmission(address);
  //Send the Register Address
  Wire.write(registerAddress);
  //End the communication sequence.
  Wire.endTransmission();

  //Ask the I2C device for data
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 1);

  //Wait for a response from the I2C device
  if(Wire.available()){
    //Save the data sent from the I2C device
    data = Wire.read();
  }

  //End the communication sequence.
  Wire.endTransmission();

  //Return the data read during the operation
  return data;
}

//This function is used to read the X-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second. 
//Usage: int xRate = readX();
int readX(void)
{
  int data=0;
  data = itgRead(itgAddress, GYRO_XOUT_H)<<8;
  data |= itgRead(itgAddress, GYRO_XOUT_L);  

  return data;
}

//This function is used to read the Y-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second. 
//Usage: int yRate = readY();
int readY(void)
{
  int data=0;
  data = itgRead(itgAddress, GYRO_YOUT_H)<<8;
  data |= itgRead(itgAddress, GYRO_YOUT_L);  

  return data;
}

//This function is used to read the Z-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
//NOTE: This value is NOT in degrees per second. 
//Usage: int zRate = readZ();
int readZ(void)
{
  int data=0;
  data = itgRead(itgAddress, GYRO_ZOUT_H)<<8;
  data |= itgRead(itgAddress, GYRO_ZOUT_L);  

  return data;
}

void fillTo(int place) {
  int ledOutput = 0;

  if(place > 8)
    place = 8;
  if(place < -8)
    place = -8;

  if(place >= 0) {
    for (int i = place; i >= 0; i--)
      ledOutput |= 1 << i;
  } else {
    ledOutput = 32768;
    for (int i = place; i <= 0; i++)
      ledOutput |= (ledOutput >> 1);
  }

//  Serial.println(ledOutput);

  digitalWrite(latchPin, LOW);  // first send latch low
  shiftOut16(ledOutput);  // send the ledOutput value to shiftOut16
  digitalWrite(latchPin, HIGH);  // send latch high to indicate data is done sending 
}

void shiftOut16(uint16_t data)
{
  byte datamsb;
  byte datalsb;

  // Isolate the MSB and LSB
  datamsb = (data & 0xFF00) >> 8;  // mask out the MSB and shift it right 8 bits
  datalsb = data & 0xFF;  // Mask out the LSB

  // First shift out the MSB, MSB first.
  shiftOut(datPin, clkPin, MSBFIRST, datamsb);
  // Then shift out the LSB
  shiftOut(datPin, clkPin, MSBFIRST, datalsb);
}

500Hz 意味着 loop() 函数的每次迭代为 2ms。您的循环功能正在从 Wire 读取并写入串行端口,这可能需要超过 2ms 的时间,具体取决于您发送的内容和波特率。

根据您的波特率 (230400) 判断,如果另一端没有流量控制,发送每个测量值(估计每个测量值 12 个字符)可能需要大约 0.5 毫秒。尝试减少写入串行的频率,看看您的性能是否有所提升。

我测试了串行写入、I2C 端口和时钟速度。发现主要问题是与 i2c 的冗余通信。例如,可以在一轮 i2c 通信中读取 6 位数据。我参考了下面的代码: https://raw.githubusercontent.com/ControlEverythingCommunity/ITG3200/master/Arduino/ITG-3200.ino

此外,使用 Teensy 也很有帮助。

使用带I2C调试功能的示波器检查输出速度。