03-04-2013 09:04 AM
I'm currently undertaking a Masters project, which involves reading data from an accelerometer, and then performing fft's, to allow frequency data manipulation.
I've found Nathan_B's code, and modified it to acquire a 128 sample array, using a for loop, which I then pass to a power spectrum vi. However, the time it takes to read each sample is on the order of 10's of milliseconds, which means it takes on average 1 1/2 seconds to acquire the whole sample, and output the power spectrum. This is far to slow for my application, as I need to be able to acquire the data, and process it in around 100ms
I've tried modifying the twi header to run at a speed of 400kHz, but this has produced no appreciable increase in read rate (I suspect that a significant chunk of the time taken to read each sample is tied up in communication overhead).
One thing that my friend suggested, is to have the arduino read in the array of samples, and then send the data to the vi in one chunk; whilst I know how I would go about reading the samples in the arduino, I have no idea how to pass the data to LV.
Any help on the issue would be greatly appreciated.
03-04-2013 09:37 AM
You are correct about the communication overhead, it is relatively very slow. Also, your friend is absolutely correct, you need to sample the entire data set on the Arduino and then send it back to LabVIEW.
You will need to make a custom function for LIFA that will execute your data acquisition loop and pass it back to LabVIEW. The communiction with the sensor, then, will be entirely on Arduino (meaning you would not use my library at all). When you have the data in an array you would loop through that data and send it to LabVIEW using Serial.write().
Likewise, you need to create custom LabVIEW-side functions to issue the command and retreive the data (a predefined number of bytes; 120 samples would give you 240 bytes of data). You will get this data as a string and you will convert it to a byte array and then pair up bytes so that you have your original data back. Now, you can process the new array of 16-bit data points.
I recommend looking at existing functions to see how they send back data to LabVIEW. I would start by simply duplicating an existing function and make sure you can get that to work as a "new" function. Once you have that working correctly, you would modify it to maybe read a single data point from the acceleromter to make sure that you can successfully communicate with the sensor. Then, you would add your loop.
If you have any issues during this process, post your modified firmware and your VIs (saved for LabVIEW 2009) and we will try to help you out.
03-06-2013 08:33 AM
I've had some success at getting values out of the arduino, however no matter what 've tried, I only get 0's out. I've attached my modified LIFA code and vi's.
03-07-2013 07:37 AM
You can disregard my earlier post. I defined accel as an LSM303 class, called init() and enableDefault(),<smackselfonforehead> but I forgot to call read() </smackselfonforehead>. I just need to fix the values.
[edit]
For some reason, my functions/vi's have stopped behaving.
When I try this version:
case 0x36: //acquire samples and transmit
for (int i=0;i<command[2];i++){
accel.read();
sample_array = accel.a.z;
}
for (int i=0;i<command[2];i++) {
Serial.write((sample_array));
}
break;
No matter what size array I set (sample_array is initialised in the previous function), or how many bytes to read, it always times out.
However, if I bypass the array, and use this version:
case 0x36: //acquire samples and transmit
for (int i=0;i<command[2];i++) {
accel.read();
Serial.write(int(accel.a.z));
}
break;
I get some values out. This does thow up an error unless I use a type converter, i.e. int(), byte(). The vi also throws a timeout error if I specify the number of bytes to read as greater than the length of the for loop.
When I get data out with the second version of the function, it doesn't some to conform with any of the values I get using either your original library, or the LSM303 examples.
Frankly, I'm stumped, and any help you could give would be greatly appreciated. I've attached the latest version of the modified LIFA code, and the vi's, saved for version 9.0.
Message was edited by: Lucid_Insanity
03-07-2013 05:09 PM
The first thing that I notice is that "sample_array[]" is declared locally which means once the init function completes, that array is deleted and no longer exists when you go to call the "acquire samples" function.
It's been a while since I've had to write custom functions so I'm not entirely sure how Serial.write() will handle the two bit integer that you are giving to it. If it sends the MSB first then you need to swap the wires on the "Join Numbers" function in your for loop in Array_aquire_test.vi. Try this out and see what happens.
03-08-2013 09:04 PM
After doing a bit of searching on how Serial.write() works, I came across a solution to passing integers:
int sample_array[command[2]];
for (int i=0;i<command[2];i++){
accel.read();
sample_array = accel.a.z;
}
for (int i=0;i<command[2];i++) {
byte hi = sample_array >> 8; //extract first half
byte lo = sample_array & 0xFF; // extract second half
Serial.write(hi);
Serial.write(lo);
}
break;
Reconstruction on the other end is now trivial, as I'm fully controlling how the data is sent.
However, a new issue has arisen: the time it takes each for each batch varies. As I will be performing filtering, and maybe using FFT's, I need to have a consistent (and known) sampling frequency/period, and thus I have a few more questions:
How consistent are the execution times of the I2C functions?
read() calls readAcc() and readMag(). Would it be worth calling readAcc() instead, or would the time saving be negligible?
How long does it actually take the I2C functions to execute? Is it on the order of microseconds or milliseconds? (I need to know this to determine if I need to use delay() or if I can get away with delayMicroseconds())
Is there anything else you can suggest for reducing the execution time of the function?
12-17-2015 03:58 PM - edited 12-28-2016 05:29 AM
none