From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Signal Conditioning

cancel
Showing results for 
Search instead for 
Did you mean: 

arduino USB data STFT

Hi,

 

I am to acquire snsor data from arduino through USB and NI VISA drivers.

the prole is i am getting discontinuity in signal at specific interval of time 2048 samples. (as attached image);

i want avoid that, so could you suggest some new strategy?

 

more over, the STFT that i am plotting is accurate, but the power spectrum is showing wrong reading. I tried giving 10Hz signal as input but the power spectrum  showing a reading of 30-32Hz.

what could be the prolem?

In this VI, the "dt" value is tuned uning signal generator to show correct frequency in FFT/STFT. 

Download All
0 Kudos
Message 1 of 15
(7,058 Views)

Of course you get a discontinuity. You are storing 2047 datapoints in a circular buffer. Only if your signal has exactly an integer number of cycles in 2047 samples will you NOT get a discontinuity.

 

Your math does not work out quite right either. Transmitting 8 bytes at the settings you are using takes at least 1.39 ms. Because RS-232 is asynchronous, random delays between bytes are always possible. You have set dt = 1.52 ms. You indicated that you "tuned" dt but it seems that you have little justification for your method.

 

To do a valid FFT requires that the data be uniformly sampled. If the Arduino is sampling at a uniform rate, then use the reciprocal of that rate as dt. But that dt cannot be less than the communications rate or you will need to wait until all the data has been collected before analyzing it.  If you look closely at the waveform chart in the image you posted, you can see that the last peak has some distortion and there is a variation in amplitude of several pixels across the peaks.  These may well be indications of non-uniform sampling.

 

You are also reversing the time order of the samples in the buffer by replacing the first element each time. Use Quotient and Remaninder with "i" wired to x and the buffer length (2047) wired to y.  Connect the remainder output to the Index input of Replace Arrray Subset. Remove the Rotate Array function.

 

It makes little sense to calculate the STFT on every iteration. Only do it when the buffer is full (Remainder = y-1). 

 

Calculating the reciprocal of the reciprocal is silly. Just use the value at the input of the first reciprocal function.

 

There is no reason to update the spectrogram porperties on every iteration. Use an event structure and only change those when one of the inputs has changed.

 

Lynn

0 Kudos
Message 2 of 15
(7,000 Views)

 

Thank you for your suggestions.

 

I thought that discontinuities in waveform are due to 10bit sampling of arduino. I planned to upgrade ADC to 16bit. Non-uniform sampling also a reason for it

 

I tried using TFA datasamples.VI to find out the sampling rate, it is varying continuously, showing the values 8000, 10000, 10E6. Its varying between these three values.

 

The reciprocal of "dt" is about 657.89Hz. It should show the same value. How to get uniform sampling rate from arduino sensor data?

 

Is there any VI in LabVIEW which resamples the acquired signal with fixed sampling rate? Kind of down sampling /up sampling.

 

Whereas i am getting right output from FFT, the problem is only with STFT "power spectrum" (i need to extract features (band of frequency bins) from it). Even STFT histogram is also showing valid readings if i test with signal generator with present configuration.

 

I tried remainder and quotient technique there is problem in connecting remainder to index of replace array subset.

 

Actually my intention is to get STFT for every 2048 samples of data, but i am not sure whether i am getting STFT for every 2048 samples in present VI.

 

0 Kudos
Message 3 of 15
(6,968 Views)

Before you get bogged down in all these details, what is the sampling rate you need to achieve for your signals? Are you familiar with the Nyquist criterion which states that the sample rate must be more than twice the highest frequency component in your signal?  If the required sample rate is higher than the Arduino can accomplish or higher than the serial port can transfer, then no fixes to the code will help.

 

 

There are discontinuities due to the sampling resolution but those tend to make a signal have small steps in voltage at each sample time.  In your case those are small enough that they are barely visible on the graphs. A 16-bit ADC will provide smoother results but that is a minor issue for what you are doing now.

 

I have never programmed an Arduino and it has been about 25 years since I programmed any small microcontroller, so I do not know the details of what that device can do. In general you want the Arduino to take a sample at fixed time intervals. If the device has some kind of clock or timer which can generate periodic interrupts, that is probably the most precise timing you can get.  But you also need to be sure that no other code running on the device can delay the acquisition and transmission of the data past the time of the next sample. I do not know which parts of the Arduino code are the slowest.

 

Once you get the Arduino sampling at a fixed rate, have it send the rate to the LabVIEW program one time, before starting to send the sample data. Then use that rate to set the dt of the waveforms.

 

If you cannot get the Arduino to sample at a fixed rate, then things get much more complicated. You need to know the time of each sample. Getting the time from the Arduino would be best because any delays due to the serial communications are not a factor. However, the Arduino must transmit approximately twice as much data for each point. This will limit the rate to one half or less of what can be transmitted without the timestamps. The other approach is to create a timestamp in LV when the data is received. This is less accurate because any timing jitter in the communications is added to the sample time.

 

You need to create a second buffer (or make the array 2D) to keep track of the timestamps.

 

When the buffer is full You can use Interpolate 1D.vi to create an array that has uniformly sampled data.

 

The y input to Quotient and Remainder needs to be a scalar, not an array. Wire the size input of Initialize Array to y of Quotient and Remainder. That value should be 2048, not 2047.  Arrays indexes are zero based, meaning that the first index is zero and the last is N-1 where N is the length of the array.

 

Lynn

0 Kudos
Message 4 of 15
(6,939 Views)

I am aware of Nyquist criteria, I also know that "2fmax" wont workout in practical conditions, i believe that it should be at least 4fmax to proper reconstruction of the signal.

the another issue is baud rate in my task, i am acquiring the signal at 57600 baud rate so that i can acquire the signal upto 0-90Hz with any distortion (for single channel only).

if i try acquiring 4 channel data at same baud rate, signal are getting distorted after crossing 12-15Hz. i have to try with 115200 baud rate. I belive it won't help me to achieve 90Hz for all for cannels. If am able to achieve atleast 0-50Hz for all for channels it will be good enough for me.

I would like to acquire 512 samples per second.

Regarding STFT Power Spectrum, what i observed is the example in NI itself not giving proper results. 

There is problem with power spectrum.

Since FFT results are reliable, i would like to go ahead without looking much into non-uniform sampling issue of arduino.

But

If i am able to get reliable readings with STFT, i believe i would get more accurate results.

 

0 Kudos
Message 5 of 15
(6,916 Views)

OK. Let me see if I understand the situation.

 

Ideally you want to acquire data from 4 channels with bandwidths of 90 Hz, but you may be able to get acceptable results with 50 Hz bandwidths.

 

I am assuming that the Arduino has only one ADC which must be multiplexed across the four channels.  You mentioned a 10-bit converter in a presious post and the possibility of switching to a 16-bit converter.

 

Let's do the calculations:

To get 90 Hz bandwidth on 4 channels the minimum sampling rate for a single ADC will be > 90*2*4 = 720 samples per second.

 

To transmit the data via a serial communications protocol let's assume one byte for the channel number, two bytes for the data (this can handle 10- or 16-bit data), and one termination character. The time to transmit the samples from 4 channels for one conversion on each channel will be:

   # bytes = 4*4 =16

  Time per byte = (1/57600 baud)*10(bits per byte)*16 bytes = 2.78 ms or 360 per second.  At 115200 baud the result is 1.39 ms or 720 per second. This assumes that no delays between bytes occur. Because RS-232 is an asysnchronous communications system such delays are possible.  These speeds are upper limits, not necessarily what you can expect on a regualr basis. Since you are already seeing some timing jitter, it likely will be worse as you push the timing to tighter specifications.

 

To get to 512 samples per second per channel you would need a communications rate greater than 164000 baud.

 

 

#####

 

Can the Arduino do the multiplexing and conversions that fast? Does it have an option for hardware timing to assure a constant sample rate?  Can it communicate that fast?

 

 

#####

 

I suspect that the STFT results are correct for the raw data you are feeding it. The FFT may look better but that is because it essentially averages over the entire data set and that tends to hide some of the short term issues.

 

 

#####

 

With the time you have already spent on this and the additional time it will take to get it right, you might be better off buying an inexpensive DAQ device from NI, such as the USB-6008 or 6009 and have the ability to get hardware timed sampling at those rates and higher right out of the box.

 

Lynn

0 Kudos
Message 6 of 15
(6,889 Views)

That's perfect. You understood the situation very well, better than me!!

 

The problem with the arduino is, it supports upto baud rate of 115200. So i should limit my sampling rate to 256Hz for all 4 channels. (i believe there won't be any issues with 90Hz BW at this SR)

 

I am trying to acquire the data wireless with the help of HC-06 Bluetooth. I am successful in acquiring 4 channel data wireless but the problems are associated with this bandwidth and sampling rate.

HC-06 supports very high baudrate of 1382400 but there is a limitation with Arduino microcontroller.

 

Could you suggest me any alternative ways to get rid of these problems?

 

If i am able to address these issues my job is done.

 

 

 

 

0 Kudos
Message 7 of 15
(6,865 Views)

I have not programmed an Arduino (or any other similar device) for more than 20 years so I do not know what capabilities the device has. 

 

The key to successful data acquisition where Fourier transform processing will be done is to assure uniform time intervals between samples. If you cannot do that, everything else is a waste of time. If the Arduino has some kind of hardware timer or counter running from a crystal controlled oscillator and can generate periodic interrupts from that counter, then use those interrupts to set the sample timing.  If it does not have such a timer or interrupts, then you will need to use software timing, which can be quite tedious to get right.

 

Lynn

0 Kudos
Message 8 of 15
(6,842 Views)

The Arduino Uno (the most commonly-used Arduino variant) can take ADC measurements at about 9600 Hz. There's only one actual ADC plus a multiplexer, so acquiring on two channels maxes out at 4800 Hz, etc. However, the real limit is the serial bus. That tops out at 115200 bps. If you send 16 bits per reading, with no termination character or anything, at best you can stream 7200 samples per second from the Arduino to the computer. 

 

Since the Arduino only uses 10 bits per sample, one could do better by packing two samples into three bytes (or, for the masochists, three samples into four bytes) and sending that. Both of those assume no termination character for each write, so making sure the packets stay synched between Arduino and computer isn't trivial.

 

There are Arduino-compatible microcontrollers which use native USB or Ethernet to talk to the computer, in which case a megabit per second or more of bandwidth is available and things become much more straightforward. 

 

Edit: Re timing, the boards do support microsecond-resolution timers and hardware interrupts, so doing regular-cadence timing is possible.

Message 9 of 15
(6,758 Views)

Thanks for the info.  I suspected something like that, but did not want to take the time to dig it out of the documentation.

 

Lynn

0 Kudos
Message 10 of 15
(6,749 Views)