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?
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
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.
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).
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 :
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;
}
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;
}