I am trying to read data from a 6DOF IMU that has an ADXL345 accelerometer and an ITG-3200 gyroscope. I can get it to stream into the serial monitor in the arduino IDE, but I have some timing questions regarding arduino baud rate and I2C capabilities.
My understanding is that to pull data from a sensor I2C has to go through the following procedure:
Send start bit (1 bit)
Send slave address (7 bits)
Send write bit ( 1 bit)
receive acknowledge bit (1 bit)
Send sub address (7 bits)
receive acknowledge bit (1 bit)
send start bit (1 bit)
send slave address (7 bits)
send read bit (1 bit)
receive acknowledge bit (1 bit)
receive data (8 bits)
receive acknowledge bit (1 bit)
receive data (8 bits)
receive acknowledge bit( 1 bit)
send stop bit (1 bit)
That's 47 bits to read 1 value or 282 bits to read all 6. If I want to do that 100 times a second, that's 28,200 bits per second which is a lot higher than the 9600 baud rate used in arduino. I'm guessing these are related, but maybe I'm just thinking about this wrong. I want to read data from the sensors (and 100 times a second is just arbitrary; it can be less frequent) and read accel_x, accel_y, accel_z, deg/s_x, deg/s_y, and deg/s_z all for the same time step and at a reliable, evenly spaced time step. I've heard about something in I2C called clock stretching. I don't fully understand it, but I don't want it to mess up the spacing between readings. For example. Let's say I wanted to get readings 10x/second. I want to make sure that the 3rd group of readings all come from 0.3 seconds after I started and that the next group will come from 0.4 seconds after, and the next 0.5 and so forth.
Also, I just want to clarify something. When the arduino code reads values from the IMU, it's looking in a buffer, right? The values it is reading have already been sampled by the IMU? Is the sample rate of the ensors critical to ensuring that I get evenly spaced readings?
My understanding is that to pull data from a sensor I2C has to go through the following procedure:
Send start bit (1 bit)
Send slave address (7 bits)
Send write bit ( 1 bit)
receive acknowledge bit (1 bit)
Send sub address (7 bits)
receive acknowledge bit (1 bit)
send start bit (1 bit)
send slave address (7 bits)
send read bit (1 bit)
receive acknowledge bit (1 bit)
receive data (8 bits)
receive acknowledge bit (1 bit)
receive data (8 bits)
receive acknowledge bit( 1 bit)
send stop bit (1 bit)
I2C doesn't have a start bit but a start condition. Your "subaddress" (this is usually called a register index or register address) is also 8 bits on most I2C sensors.
After receiving a byte you have to send the acknowledge bit, you don't receive it. You stop that transfer by sending a NAK instead of a ACK, it's not fixed to receive 2 bytes.
That's 47 bits to read 1 value or 282 bits to read all 6. If I want to do that 100 times a second, that's 28,200 bits per second which is a lot higher than the 9600 baud rate used in arduino.
On I2C you don't call the frequency baud rate but just clock frequency and usually it's fixed to be either 100kHz or 400kHz.
I've heard about something in I2C called clock stretching. I don't fully understand it, but I don't want it to mess up the spacing between readings.
Clock stretching is used by the slave if the master is clocking too fast or if the slave needs some time until it's got the requested value.
I want to make sure that the 3rd group of readings all come from 0.3 seconds after I started and that the next group will come from 0.4 seconds after, and the next 0.5 and so forth.
What for?
When the arduino code reads values from the IMU, it's looking in a buffer, right?
No, the Arduino gets the values from the IMU and stores it in a buffer locally (that's what requestFrom() is doing) and you read it from there (with the read() call).
The values it is reading have already been sampled by the IMU? Is the sample rate of the ensors critical to ensuring that I get evenly spaced readings?
That depends on the sensor. Which one of the two your IMU has do you talk about here?
What I intend to do is stream data from both the gyro and accelerometer and then, via Processing, save it to a data file. I want to be able to then take that data and do a variety of things to it, including frequency analysis. However, to do this, the recorded data points must be evenly spaced in time. In other words, the time step between each set of data points must be the same. Additionally, the data points in any given set must be recorded at the same time. For example, let's say I had the following data output:
I have no idea how realistic those values are. I just made them up so I'd have something to reference. The DataID just represents the sample number. (first sample, second sample, etc.). For every time the arduino samples data, I want to make sure all 6 values in one sampling iteration happen at the same time (or nearly the same time) and I want to make sure that each sample is evenly spaced from the next in time (i.e. the time between the first and second samples is the same as the amount of time between the second and third samples, etc.). Is this already guaranteed to happen? Or are there precautions I need to take to ensure this happens. How do the I2C speed, arduino baud rate and clock stretching each effect this, if at all? Perhaps I am just confused as to how the baud rate of the arduino and the speed of the I2C bus are related, if at all.
Usually the sensor returns the value sampled at the time the read command was received. You then have to read the whole data out. Assuming that the acceleration values are 16bit integers the transfer time (for only one sensor) is a bit more than 50 clock cycles or about half a millisecond (both sensors need a bit more than a millisecond). How often do you want to read the data from the IMU (as fast as possible doesn't make sense in your case)?
If you want to get the best possible throughput don't calculate the float values on the Arduino but transfer the raw data to the PC and make the calculations there.
The baud rate you use between the Arduino and the PC is relevant if you want to transfer the data in a non-binary format (because you transfer much more data than you receive on the I2C, so if you want to keep a high update frequency you may run into problems).
Additionally, the data points in any given set must be recorded at the same time.
At the same time is not possible, define how much delay is acceptable by your application. What kind of movement are you measuring?
In addition to pylon's replies, you may have a bottleneck in the serial monitor display. If you still have the serial baud rate at 9600, change the serial baud rate to 115200 in the sketch and the serial monitor.