ITG3200, fast i2c and 8kHz sample frequency

Hi,
i have a ITG3200, but i can't understand something.
using "normal" i2c speed (TWI_FREQ = 100000L) i can read sample at about 1kHz
using "fast" i2c speed (TWI_FREQ = 400000L) i can read sample at about 2.8kHz

now, this sensor can sampe at 8kHz, and only support i2c protocol.

How am i supposed to read the sample at full speed?

I'm using the standard (ide 1.0) wire.h , maybe it's the library that is too much slow?

The built-in Wire library seems to only support 100kHz I2C. Look in .../libraries/Wire/utility/twi.h for the #define of TWI_FREQ

Perhaps this should be reported as a bug / feature request. I'm sure there are other 400kHz-compatible I2C libraries out there if you look for them.

it's what i've done, changhing the twi freq give me almost x3 improvment, look at the data above

Doh! Well apart from that all I can suggest is read the relevant part of the datasheet and write your own I2C interface code with less overhead-per-bit. The I2C hardware seems inordinately complex (compared to the SPI interface). Plan B is get a different gyro that's SPI.

Not sure why you need 8kHz sampling though, this seems unnecessary unless the gyro is on some very low M.o.I. mount. Have you tried selecting a suitable on-sensor LPF and sampling at a lower rate? I presume you are attempting to get as low a drift signal as possible when integrating the output?

I'm writing my own quadcopter/plane stabilization software. It is not necessary to go faster than 100/200Hz because of the engine/servo inertia (but faster rate means better integration, as you pointed out), it is just to understand why a sensor that can sample at 8kHz hasn't a throughput enough fast.

and yes, next time i'll get SPI sensor, when my reflow oven will be ready :slight_smile:

you might have a look at the soft I2C lib - New i2c libraries with 'softi2c' - adafruit industries - as alternative?

using DssCircuits.com is for sale | HugeDomains it increased to 3kHz... it is not worth it..

i cannot make the I2CMaster work..

lesto:
Hi,
i have a ITG3200, but i can't understand something.
using "normal" i2c speed (TWI_FREQ = 100000L) i can read sample at about 1kHz
using "fast" i2c speed (TWI_FREQ = 400000L) i can read sample at about 2.8kHz

now, this sensor can sampe at 8kHz, and only support i2c protocol.

How am i supposed to read the sample at full speed?

I'm using the standard (ide 1.0) wire.h , maybe it's the library that is too much slow?

Hi, i'm working on a bench to measure vibrations for fine tuning of multicopters and I was puzzled as well by the inconsistency between this 8 kHz spec of this sensor, and the i2C limitations. Since you've been working on multicopter too, i thought i'd dig out this thread. Did you come up with another solution to match the sampling rate of 8 kHz closer than just by changing the TWI_FREQ to 400000L ?

you can set the I2C freq also to TWI_FREQ = 800000L for most sensors, just give it a try.
I expect the effective data rate will go up to 3.8~4Khz.

The fact that you do not get the maximum out of it is because the Arduino is "single threaded"
so all overhead is done sequentially resulting in lower effective throughput.

robtillaart:
you can set the I2C freq also to TWI_FREQ = 800000L for most sensors, just give it a try.
I expect the effective data rate will go up to 3.8~4Khz.

The fact that you do not get the maximum out of it is because the Arduino is "single threaded"
so all overhead is done sequentially resulting in lower effective throughput.

Ok, thanks, I will give it a try.
In the meantime, i wonder about how to get an accurate data rate, apart from just counting the data i got divided by the time it took to send them.
Say i get the data out of the arduino with a serial.print , toward some recording software (PC, Matlab, whatever ...), what would be the most accurate way to know how fast i'm getting the data ?
In addition, if i'm requesting data faster than they can be delivered by the i2c, what symptoms shall i get ? Do i freeze the arduino ? Or am i getting zeros ? or is it printing the last measured data ? (resulting in cloned data)
In the later case it's hard to check when the sensor is standing still. There will be lots of actual identical triplet data (x, y, z).
This is a noob question i guess.

you can read the bit "dataready", but because we already have bandwidth problem, that would be really bad.

what symptoms shall i get

nothing. You get value, but sometimes strange value, as they are written while you read. but this also depends on the sensor chip you are using.

ok. I'm dealing with the ITG3205.
I realized that i can easily check what i can hope to get at which rates through the serial :
http://forum.arduino.cc/index.php?topic=196328.0

In this test, serial monitor can output bytes of data at 10 kHz. I'll run the same test with a triplet data but it will be of the order of the sensor sampling rate (8 kHz) or less (3 coordinates to send after all). So, printing to serial is another bottleneck. Maybe that is why you thought the i2C was killing your sampling rate ? Is it not the serial output rate that kills it even more ? Just a thought.

yes, serial kill even more, but you can use a baudrate of almost 1.000.000 or use the SPI bus.
as far as i remeber, sending raw data you can use the Serial, as into i2c must pass request and response, in rearial just 2+2+2+1 byte(last byte is "align byte", just read about 100 byte, and find where this "align" byte get repeated, and you are off to go.)

I just made a few time measurements with this ITG3205 and the Pro Mini 16Mhz, for reading only one value (X rate)

Tried Both baud rate of 9600 and 115200, couldn't go higher with the arduino serial monitor. But Matlab seems to support up to 256000 so i will give it a try, since i'm making the bench with this.

Both 9600 and 115200 give the same time for serial.printing individual values : 120 us (ITG320x sends out signed integers)

As for reading the sensor value through i2c, to which i add the print time , i get on average :

Standard I2c @100000 Hz : 1.3 ms => 770 Hz
Fast I2c@400000 Hz : 0.520 ms => 1.9 kHz
Very Fast I2c@800000 Hz : 0.420 ms => 2.4 kHz (not that faster though)

So, 800000 Hz does help indeed. At least the Fast and very Fast mode are reasonably above the 1 kHz of the other DLPF modes from the datasheet (page 23).

Serial.print is an asinc operation, so util you don't full the output buffer, you get "fake" value.

Is there a better way than below (that's what i did for my measurements) for testing communication speed ? I'm using the ITG3200 firmware example code from the Sparkfun website :

https://learn.sparkfun.com/tutorials/itg-3200-hookup-guide/firmware

stripped to only reading 1 coordinate and printing some micros() differences.

void loop()
{
  strt =  micros();
  xRate = readX();
  dt = micros() - strt;
  Serial.println(dt,DEC);
  strt =  micros();
  Serial.println(xRate, DEC);
  dt = micros() - strt;
  Serial.println(dt,DEC);
  delay(5000);
}

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;
}

int readX(void)
{
  int data=0;
  data = itgRead(itgAddress, GYRO_XOUT_H)<<8;
  data |= itgRead(itgAddress, GYRO_XOUT_L);  
  return data;
}

with print every number i 1 byte, so 130 is 3byte. use wryte, it will write the raw integer (2 byte) and raw long (4 byte)

obviusly it will be a little more trycky read them

ok, that was an helpful advise actually. Thanks

Instead of using
Serial.println(int value),

i used

Serial.write(lowByte(int value))
Serial.write(highByte(int value))

I then use "typecast" on Matlab to convert back into integers.
It takes now 20 us instead of 120 us to send the whole coordinate value over serial !

Updated sampling frequencies for 1 coordinate :

Standard I2c @100000 Hz : 1.3 ms => 833 Hz
Fast I2c@400000 Hz : 0.520 ms => 2.2 kHz
Very Fast I2c@800000 Hz : 0.420 ms => 3 kHz

Can you test reading 2 bytes at once? (maybe the 2 bytes should be swapped?)

int readX()
{
  int data = 0;
  Wire.beginTransmission(itgAddress);
  Wire.write( GYRO_XOUT_H);
  Wire.endTransmission();
  Wire.requestFrom(address, 2);
 
  if (Wire.available())
  {
    data = Wire.read() << 8;
    data = data + Wire.read();
  }
  return data;
}

pay attention on the syncronization of the first byte!