Teensy 3.2 or 3.6 used for High Speed DAQ

Status
Not open for further replies.

nejcmedved

New member
Hello Teensy users!

I would like to propose for guidance for a Teensy based project.

Hardware to be used :
- Teensy 3.2, 3.5 or 3.6
- 2x MEMS accelerometer (single or triple axis)

At the moment I have one Teensy 3.2 and 2x MEMS ADXL326 wired and running.

Goals :
- Live data stream (1kHz or similar) currently implemented as :

Code:
while(true)
{
  //Read ADC values
  start = micros();
  x1= analogRead(A0);
  ..
  z2=analogRead(A6);
 
  //Serial output
  Serial.print(x1);
  Serial.print(";");
  ..
  Serial.print(z2);
  stop=micros();
  delayMicroseconds(1000-(stop-start));
}

Live stream is not so important as the high speed DAQ below. It is working good enough at the moment.

- 10kHz DAQ with Serial output at the end of acquisition.

I would like to implement 10 kHz DAQ for 1 or 2 seconds for 6 analog reads or at least 2.

Currently I do it like this :

Code:
int zdata1[5000];
int zdata2[5000];

void HighSpeedDAQ()
{

for(int i=0;i<5000;i++)
{
  zdata1[i]=analogRead(A0);
  zdata2[i]=analogRead(A1);
  delayMicroseconds(100-(stop-start));
}

for(int i=0;i<5000;i++)
{
  Serial.print(zdata1[i]);
  Serial.print(";");
  Serial.print(zdata2[i]);
}

The problem with High Speed DAQ is that if I try to enlarge arrays compiler is complaining about insufficient memory.

Could I do it with writing data to SD card or something? I am afraid it is not fast enough.

Thank you in advance for help. This is my first post on this forum but I have already used Teensy for some other projects.

Best regards,

Nejc
 
Could I do it with writing data to SD card or something? I am afraid it is not fast enough.

Yes, but you're going to have to write more complex code, because SD cards sometimes spend many milliseconds to perform your writes.

The first step is collecting data into 512 byte buffers. Always write 512 bytes or multiples of 512, since the SD sector size is 512 bytes.

Even if you do this, you're going to need a way to keep collecting data while the SD card is busy writing. Maybe use IntervalTimer to run your data collection code. But this gets into some tricky programming to properly pass the data from the interrupt to your main program.

It is possible, but involves more advanced programming techniques.
 
Paul, thank you for your reply!

My code is currently very sensitive because I am using delayMicroseconds function with delayMicroseconds(1000-(stop-start)).

If stop-start is higher than 1000 then the code hangs there. I know I could do something to bypass that but the cycle would still be higher than 1000ys.

Below is again my Serial stream code:

Code:
while(true)
{
  //Read ADC values
  start = micros();
  x1= analogRead(A0);
  ..
  z2=analogRead(A6);
 
  //Serial output
  Serial.print(x1);
  Serial.print(";");
  ..
  Serial.print(z2);
  stop=micros();
  delayMicroseconds(1000-(stop-start));
}

With 1kHz(1000ys) stream Works quiet well. AnalogReads and Serial output for 2 pins takes around 100ys. If I decrease delay to 500 or 300 ys it often occurs that Serial.print() takes a lot of time to execute.

Could you help me with speeding up Serial stream?

Should I program in some other way? I would be extremely happy to solve this problem and increase sampling rate to 5kHz.

Thanks for your help!

Nejc
 
First, try analogReadAveraging(1) in setup(). That will speed up the analogRead, but it might be more noise.

On the loop, try this:

Code:
elaspedMicros usec;
while(true)
{
  //Read ADC values
  x1= analogRead(A0);
  ..
  z2=analogRead(A6);
 
  //Serial output
  Serial.print(x1);
  Serial.print(";");
  ..
  Serial.print(z2);
  while (usec < 1000) ; // wait
  usec -= 1000;
}

This may or may not help, but worth a try.

On the serial speed, there's 2 things that matter.

First, the USB is limited to about 1 Mbyte/sec. Looks like you're well under that limit, but hard to know for sure from your code. I see printing of 7 integers as plain text, which range to 1023, plus 1 extra byte per number as a delimiter. So worst case, this looks like 35 bytes sent 1000 times per second, or 35,000 bytes/sec. That's FAR less than 1,000,000 bytes/sec, unless I've misunderstood (can't see all your code...)

You may find this surprising, but the speed of the software on your PC receiving the data also matters. You might not think a multi-GHz processor with gigabytes of RAM could limit the speed, but it very certainly can. Especially systems like Labview and Puredata where GUI stuff happens can really be slow. But only 35,000 bytes/sec slow?!

Anyway, the point is USB serial uses true end-to-end flow control. If the PC side software lags, buffers in the PC driver fill up, and then the PC stops moving the data from Teensy as quickly, and then buffers on the Teensy side fill up, and the net result is Teensy has to wait. If extreme slowness of the PC side software is holding you back, efforts on the Teensy side to send an compact binary data aren't going to help.

Then again, if you're doing something much different than I've guessed from this incomplete code, and you really are sending close to 1,000,000 bytes/sec, then you will need to move to a more compact binary format.
 
Thanks for all the answers! Project is progressing good. At the moment we can sample 9 ADC channels with 10kHz frequency which is now more than enough.

However I would have one more question regarding ADC noise on teensy.

Does someone has experience if there is a difference/influence on Teensy 3.2 ADC noise if Teensy is powered from 1) USB or 2) Battery.

Thanks in advance for the answers!

Best regards, Nejc
 
USB power will generally be noisier, since you have both the 5V supply noise + anything EMI got onto the cable. Less of an impact if you are not using the USB power to feed any of the hardware going into the ADC though.
 
Status
Not open for further replies.
Back
Top