I am currently working on a project that reads digital accelerometer data via an arduino (I2C), prints this over the serial port and is read into matlab.
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 Serial
Serial.print(x, DEC);
Serial.print(" ");
Serial.print(y, DEC);
Serial.print(" ");
Serial.println(z, DEC);
delay(5);
}
I'm getting confused with sampling rate. The default data rate for the accelerometer is 100Hz. To obey nyquist, I should be sampling at atleast 200Hz (200 times a second)?? Is placing a 5ms delay in the while loop (as shown) a valid way of setting the sampling rate ?
Further to this, should me matlab code be set to match the sampling rate i.e. 5ms ?
If you want regular times for sampling, don't use delay, use micros, otherwise you'll be at the vaguaries
of how long your code takes to run, not just the ticking of the clock. millis() is not suitable for this, note, as it has a lot of jitter.
unsigned long target = 0L ;
void loop()
{
if (micros() - target >= 5000) // sample when time comes
{
int x,y,z;
adxl.readAccel(&x, &y, &z);
....
target += 5000 ; // prepare for next sample
}
}
You haven't said what accelerometer, so don't know what the actual fastest sample rate is.
If you are reading at high rates and try to print lots to serial for each sample, serial will slow
you down, even at 115200 baud you can't output that much per millisecond.
9600 bps = 9,600 bits per second or 1.04 milliseconds per character. So there is your first problem. The 18 or so characters you print take almost 19 ms to arrive, while you have only 5 ms per reading available.
115200 bps is a lot better, then at least you can send out your data in 1.25 ms.
A quick Google search indicates that the maximum sampling rate of this sensor is about 1 kHz, so no problem there. You will be able to do 200 Hz, even push it to 300-400 Hz.
Now not sure how to go about setting the rate, maybe you have to look at micros(). Millis() is a bit crude of a resolution here. Your code will look like this:
#define INTERVAL 5000 // 5 milliseconds per sample for 200 Hz, change this for different sampling rates.
unint32_t lastMicros = 0;
void loop() {
if (micros() - lastMicros > INTERVAL) {
lastMicros = micros(); // do this first or your interval is too long!
readSensor();
serialPrintData();
}
}
The output data from the accelerometer is formatted as 16 bit - twos compliment. So 9600 baud would mean one bit is transmitted in 104us. therefore 16 bits would be transmitted in 1.667ms. This would mean that theoretically 600 samples of data could be sent in 1 second ?
Please let me know if this is correct or if my understanding is a little off ? I understand there are other process running in the background etc...
Not in the way you handle the data, which you receive in the form of three ints. Each int is two bytes, plus the spaces in between, plus the \n terminator, makes for 9 characters or 72 bits. Then you print it in human readable format to Serial so the int can be up to 5 characters (digits) long.
If you take the raw data of the accelerometer, then transmit it in binary form, you can save a lot of overhead. Still it's a good idea to increase the baud rate, no reason to keep it that low.
curlyBracket:
formatted as 16 bit - twos compliment.
complEment. As in the opposite. A compliment is something else entirely!
Is there a reason you can't use 115200 baud? 9600 is sooooo veerrrrrrryyyyy
sllllllooooooowwwwwwwwwwwwwwwww.
So what is the maximum sampling rate of the accelerometer? If you only
have 2 bytes per sample 115200 baud allows over 5kSPS (assuming low packetization/protocol
overhead).
You mentioned the Nyquist Sampling Cryterion earlier. This constraint is only set by the max bandwidth of the signal you're sampling. For instance, if the max frequency you want to detect is 100kHz, you need to sample at at least 200kHz.
If there are signals higher in frequency that the max you want to detect, you have to filter them out
before sampling, which clearly has to be done on the sensor itself here - I think the ADXL345 does
this for you based on the sampling rate you select. You just have to read every sample and not
miss any. If you want a lower bandwidth that the sensor can provide, you have to low pass filter
the samples in the digital domain yourself.