5

I want to plot real time data from a bluetooth device. I have a Bluetooth device that the phone will connect to and read the data coming from it. The data is voltage levels from some sensors and having a sample rate of 300 samples per sec. Most of the plotting libs(like aiChart, Androidplot, achartengine,...) I have seen can't handle that amount of data and repainting the graph. So I looked into openGL and Android NDK and it seems that I might be able to graph using either one of these with the sample rates I have. Does anyone have a sample code for openGL line graph plotting in android/Java and/or NDK code sample?

JPM
  • 9,077
  • 13
  • 78
  • 137

1 Answers1

3

We did something like this simply by creating a point array class with several pages and drawing in opengl with offset so the current point is always in the same place.

The idea use fixed size arrays with a separate counter so you aren't hitting memory alloc issues which would cause gc to kick in. Once a page is full, cycle to the next page displaying the old as well. The idea is that if you have 5 pages, you can write to one, display the other 3 and batch write the last one to sqlite on an sdcard in a seperate thread so you can pull all the data out later on.

As long as you only have one thread writing to the array you can get away with something like

arrayPoint[] p;
....
int currentPos = 0;
arrayPoint current = p[currentPos];

..... 
while(....

if(current.end < current.max)
{
      .... get datax and datay
     current.end++;
     current.x[current.end] = datax;
     current.y[current.end] = datay;
}
else
{
     currentPos = getNextPos();
     current = p[currentPos];
     current.end = -1; // truncate the array without actually freeing or allocating mem
     ..... flip volatile bool to let other thread know its ok to get exclusive access to its data etc      
}

Its very fast and should do what you need. You can then output as a point on a canvas or draw in opengl es

Hope that helps.

Kactus
  • 123
  • 7
  • Your idea makes sense about writing to say 5 pages of data...in fact the last page can be thrown to a side process/thread to do the writing to SD. Although your code method I wouldn't go with as that seems too slow. As the data may be of variable size and rates and pushing an array say when you have 10 new data points and re-indexing would be way too slow. Hence why I use LinkedLists if this is Java code we are talking about. – JPM Aug 31 '11 at 14:32
  • One question in your openGL code did you write that in Android/Java or in C/NDK? – JPM Aug 31 '11 at 15:36
  • Hi JPM The reason I went with static arrays is to avoid gc as that was my main bottle neck. I have found from personal experience that the dynamic classes make thousands of objects and that will kill any chance of keeping fast data flowing. Using a static array with an index to end means its only one operation to reset it (by setting end to -1) and data is over written as added. Have a play with the DDMS and you can track where you are creating objects. I wrote everything in Android Java and it was fast enough once I removed GC. – Kactus Sep 07 '11 at 09:06
  • I should mention that how well your device handles opengl varies greatly from device to device but you can optimize by reducing duplicate calls. Eg per frame one set of enables then all your translates and DrawElements and one set of disables at the end. Don't bind more than you need to. You'll need to test for you data if you are better off drawing points for each data set or recreating a vertex buffer for a page, but in my case I used a single point with translates. Once again use DDMS with method profiling to see where you can make gains. – Kactus Sep 07 '11 at 09:14
  • I have no idea what you are talking about as I am new to openGL, but I trust you. Just trying to figure out what is the best way to go with dynamic line graph plotting of real time data. – JPM Sep 07 '11 at 14:40
  • This array recycling (so to speak) seems like a good idea to protect against GC pauses. I used similar approach for FFT with similar data rates and it works. All in all just optimise your object creation first and then go for drawing calls optimisations. First will make it work and second will just make it a faster. – Igor Čordaš Jul 18 '14 at 10:16