Plotting Vector Graphs for High Sampling Rates

162 views
asked May 29, 2019 in System Integration by rpi3usr

Hello

I am developing an application to receive sound signals from a microphone and display the values on a Graph. I am using Vector Graphics to display the moving plot as mentioned in Example https://doc.embedded-wizard.de/path-data?v=9.20.I have been able to successfully receive ADC values from my raspberryPi and ADC setup onto the GUI and display the graph.

However , the Main problem is that I need to acquire 30000 samples every second. I can clearly see from the graph that the sampling rate is well below the required mark. Eventhough the ADC has been configured to acquire at 30kSPS, the overall size of the C program including all the functions of Embedded Wizard are not allowing the DeviceDriver to run fast enough to capture the required number of datapoints.

Kindly, suggest how should I decouple the acquisition from the GUI program so as to be able to Acquire and display such a number of datapoints or whether any other approach should be followed.

Thanks in advance.

1 Answer

0 votes
answered May 29, 2019 by Manfred Schweyer
Hello,

generally, for the overall performance it is important how you transfer the data from the ADC to the Path Data object. This can be done more or less efficent, e.g. it is better to read a complete set of ADC values instead of calling a method for each single sample.

Nevertheless, without knowing your exact implementation, I can imagine that 30k samples per second (sps) will never be drawn with 60 frames per second (fps). I think the goal must be to reduce the huge amount of samples to a reasonable amount of data for the Path Data object - nobody can follow 30k sps...

Is it possible, that you anlayse and filter your data so that you can reduce the amount of samples that have to be drawn?

Best regards,

Manfred.
commented May 29, 2019 by rpi3usr

I completely agree that nobody can follow 30k sps. I have been using Labview for acquiring data and if you have used it , you know that the most basic display is the graph wherein ALL the acquired data points can be visualised if so required by the viewer. This is my target. 

The implementation being used so far is the same as in your example. Single values being passed into the device class and updating the Path Data Object. I understand that I require buffered acquisition and then transfer the datapoints in arrays, but how to pass arrays from the device driver to the GUI.  Is there something very basic that I am missing?

There is also another concern, to acquire 30ksps for frequency analysis, I need my acquisition loop to run pretty fast. Since the acquisition is part of the Devicedriver file and also a whole bunch of EmWi programs, I doubt the acquisition will be able to actually run 30k times a second. This is why I was considering decoupling acquisition from the EmWi set of code. After this, I can think of sending reduced data to display.

commented May 30, 2019 by Manfred Schweyer
Yes, there is no way to pass an array from the device driver to the GUI. But instead of transferring each single datapoint, you can send a notification to the GUI when a complete set of data is available and then load a complete chunk of datapoints within a small loop.

In case you need to process your data (e.g. by doing a frequency analysis), it may be helpful to make a separate worker thread, that is responisble to get the data from the ADC and to do the analysis. Each time a result with a resonable amount of data is calculated, the set of data is provided to the GUI thread.
commented Jun 14, 2019 by rpi3usr
Hello Manfred

I followed your suggestion and did the following-

1. Implemented a separate thread for acquiring ADC values in an array. A counter confirmed that the thread was able to run at the required rate.

2. The ADC array was used by the main EmWi thread to transfer the collected values in a FOR loop to the UI. (eg. If ADC is running at 1K sps, each iteration of the main thread sends 1000/60 =approx 17 samples to the UI.)

The problem remains as it was earlier, it seems the vector Graph is still showing only 60 points each second on the display even when the ADC is running only at 1K sps.
commented Jun 16, 2019 by Manfred Schweyer
Hello,

the 60 points per seconds indicates that there is one point drawn (or added) every frame.

Can you post some code snippets? Especially, I would like to see the code that you have implemented for exchanging the data from the ADC data array to the GUI and how you add the data values to the path data object.

Otherwise it is too difficult to give you better recommendations.

Best regards,

Manfred.
commented Jun 18, 2019 by rpi3usr
void* adc_run (void* arg)
{
       while(1)
       {
	       while(ADS1256_Scan()==0);
	       adc[0] = ADS1256_GetAdc(0);
	       volt[0] = (adc[0] * 100)/167;
	       a[i] = volt[0];
	       i++;
	       
	       
	       if(timestamp != time(NULL))
	       {
		       timestamp = time(NULL);
		       j=i; // copying the number of elements read in that second
		       ApplicationDeviceClass_UpdateTimeCount( DeviceObject, (XInt32)i);
		       i=0;
	       }
       }
       return NULL;	
}

This is the function(adc_run) doing the acquisition in the separate thread. The array a[] collects all the acquired values .

#ifdef _ApplicationDeviceClass__UpdateADC_

for (k=0;k<(j/60);k++)                                            
   {
    ApplicationDeviceClass__UpdateADC( DeviceObject, (XInt32)a[l*(j/60)+k]);
   }
   l++;

    if (timestamp1 != time(NULL))
    {
	l=0;
	timestamp1 = time(NULL);
    }
  #endif

This is the main EmWi loop . We know 60 iterations happen every second so each iteration uploads N/60 values to the UI.

This chora expression is written inside a slot method(UpdatePath) which is called when the Timer  completes its period ( currently at 1ms).

I cannot exactly say how many data points have reached the UI but they are certainly much less than 1K as I can conclude after giving a suitable input to the sensor-adc system.

The example is the path-data6  given here https://doc.embedded-wizard.de/path-data?v=9.20#2. The random number function has been removed and device class added.

commented Jun 27, 2019 by Manfred Schweyer

Hi,

before starting to implement something new - I just saw two problems within your code snippets that may cause the problem:

1.) Within your adc_run() thread you make calls to the DeviceObject - this is very dangerous. Never make calls to an Embedded Wizard function from any other thread than the main GUI thread. You can use the adc_run() thread to collect the data - but providing the data to the GUI application has to be done from your ProcessData function of your Device Driver.

2.) You mentioned that you add the path data by a timer triggered slot method. You intended to trigger this by using a 1 ms timer. However, each time the timer expires and a new data is added, the graph is updated - which happens V-synchroneous. As a result you will add 60 data points per second... When you put all available data values that are provided to the device class, then the next update will show all available data points. The timer triggered update is not necessary.

Does this help you?

commented Jul 4, 2019 by rpi3usr
Hello

The points put forward by you will certainly help. We have been trying for the past couple of weeks to get our Acquisition part work good enough so that we can proceed with processing the acquired data.

It seems accomplishing this with EmWi will take a little more effort. It would be really helpful if you can prepare and provide the example for raspberry pi. Till then, I hope we will also be able to properly do the acquisition and your example would help us understand how to properly implement it

Thanks

Embedded Wizard Website | Privacy Policy | Imprint

...