I use GraphView on Android to build real-time data (ECG) received from a connected Bluetooth sensor (BLE).
After some time (5-10 seconds = 500-1000 points), the application becomes very slow and slow.
The output speed of the sensor is 100 Hz, and the data is received and displayed as they are created (every 10 ms).
As indicated in such cases, I only save the data that I need to display. I tried to minimize the performance (2 seconds = 200 points) by testing the application on different Android devices, but the problem is not worth it. Any ideas?
import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.series.DataPoint; import com.jjoe64.graphview.series.LineGraphSeries; import com.jjoe64.graphview.GridLabelRenderer;
...
//GraphView init static LinearLayout GraphView1; static GraphView graphView1; static LineGraphSeries<DataPoint> Series1; static LinearLayout GraphView2; static GraphView graphView2; static LineGraphSeries<DataPoint> Series2; static LinearLayout GraphView3; static GraphView graphView3; static LineGraphSeries<DataPoint> Series3; private static int Xview = 5; private static int maxpoints = 500; private static double xstep = 0.01d; private static double graph2LastXValue = 0; static boolean AutoScrollX = true;
Initialize the diagram for channel 1 (init_ch2 () and init_ch3 () similarly):
void init_ch1(){ GraphView1 = (LinearLayout) findViewById(R.id.Channel1); Series1 = new LineGraphSeries<DataPoint>(new DataPoint[] {new DataPoint(0, 0)}); graphView1 = new GraphView(this); graphView1.getViewport().setYAxisBoundsManual(Yview_manual); graphView1.getViewport().setMinX(0); graphView1.getViewport().setMaxX(Xview); graphView1.getViewport().setScrollable(true); graphView1.getViewport().setScalable(true); graphView1.getGridLabelRenderer().setGridStyle(GridLabelRenderer.GridStyle.BOTH); graphView1.getGridLabelRenderer().setGridColor(Color.DKGRAY); graphView1.getGridLabelRenderer().setHorizontalLabelsVisible(false); graphView1.getGridLabelRenderer().setVerticalLabelsVisible(true); graphView1.getGridLabelRenderer().setNumHorizontalLabels(6); graphView1.getGridLabelRenderer().setNumVerticalLabels(3); graphView1.getGridLabelRenderer().setVerticalLabelsColor(Color.WHITE); graphView1.getGridLabelRenderer().reloadStyles(); Series1.setThickness(6); Series1.setColor(Color.GREEN); graphView1.addSeries(Series1);
The callback is called when new data is received:
public void updateECGCals(BluetoothGattCharacteristic characteristic) { Integer data1, data2, data3; data1 = ReceiveChannelData(characteristic, i*CH_DATA_SIZE); data2 = ReceiveChannelData(characteristic, i*CH_DATA_SIZE+3); data3 = ReceiveChannelData(characteristic, i*CH_DATA_SIZE+6); String strIncom1 = Integer.toString(data1); // create string from bytes array String strIncom2 = Integer.toString(data2); // create string from bytes array String strIncom3 = Integer.toString(data3); // create string from bytes array Series1.appendData(new DataPoint(graph2LastXValue,Double.parseDouble(strIncom1)),AutoScrollX,maxpoints); Series2.appendData(new DataPoint(graph2LastXValue,Double.parseDouble(strIncom2)),AutoScrollX,maxpoints); Series3.appendData(new DataPoint(graph2LastXValue,Double.parseDouble(strIncom3)),AutoScrollX,maxpoints); //X-axis control if (graph2LastXValue >= Xview) { Series1.resetData(new DataPoint[]{}); Series2.resetData(new DataPoint[]{}); Series3.resetData(new DataPoint[]{}); graph2LastXValue = 0; } else graph2LastXValue += xstep; graphView1.getViewport().setMinX(0); graphView1.getViewport().setMaxX(Xview); graphView2.getViewport().setMinX(0); graphView2.getViewport().setMaxX(Xview); graphView3.getViewport().setMinX(0); graphView3.getViewport().setMaxX(Xview); } private static Integer ReceiveChannelData(BluetoothGattCharacteristic c, int offset) { Integer output_code; Integer MSByte = c.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset); Integer MDByte = c.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset+1); Integer LSByte = c.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, offset+2); output_code = (MSByte << 16) + (MDByte << 8) + LSByte; return output_code; }