在Android应用程序中为蓝牙脉率传感器创建实时图表

时间:2014-09-29 21:15:50

标签: android bluetooth arduino android-graphview

我目前正在开发一款Android应用程序,它通过Bluetooth Low Energy连接到Arduino,后者带有nRF8001蓝牙低功耗模块,可连接Spark Fun提供的SEN-11574脉搏传感器(https://www.sparkfun.com/products/11574 )。

我一直在尝试实施一个图表,每当我点击“获取心率”时,就会在图表上绘制数据。按钮,但我只管理以下内容:

screenshot

我研究了许多不同的资源,其中包括以下内容但遗憾的是他们没有回答我的问题:

1234567

我正在使用Android Graph View Library尝试解决我的问题,因为它提供了与Android Studio的最佳集成。

我正在努力解决三件事:

  1. 正确标记X和Y值
  2. 将心率传感器数据附加到图表
  3. 完整项目位于:Arduino Pulse Rate

    我似乎在这两段代码中苦苦挣扎:

         private void writeSensorData(final CharSequence text) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.e(LOG_TAG,text.toString());
                output=text.toString().trim();
    
                if (output.length() > 0 && output.length() <=3) {
                    pulseRateView.setText(output);
                    rateSeries.appendData(new GraphView.GraphViewData(graph2LastXValue,Double.parseDouble(output)),AutoScrollX,maxDataCount);
                }
                else {
                    return;
                }
            }
        });
    }
    
         @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pulse);
    
        //Connect U.I Elements
        getPulseRate = (Button)findViewById(R.id.heartRateBtn);
        pulseRateView = (TextView) findViewById(R.id.pulseValueView);
        connectionStsView = (TextView) findViewById(R.id.connectionStsView);
        refreshButton = (Button) findViewById(R.id.refreshBtn);
    
        // init heart rate series data
        rateSeries = new GraphViewSeries(new GraphView.GraphViewData[] {
        });
    
        GraphView graphView = new LineGraphView(this, "Pulse Rate Sensor");
    
        graphView.addSeries(rateSeries);
        graphView.setScrollable(true);
        graphView.setScalable(true);
    
        LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
        layout.addView(graphView);
    
        getPulseRate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String setOutputMessage = "/bpm /";
                tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
                if (gatt.writeCharacteristic(tx)) {
                    writeConnectionData("Sent: " + setOutputMessage);
                } else {
                    writeConnectionData("Couldn't write TX characteristic!");
                }
            }
        });
    
        refreshButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                restartScan();
            }
        });
    }
    

    感谢您的帮助,感谢您的时间。

1 个答案:

答案 0 :(得分:1)

下面的解决方案配置您的图表以实现您想要的基本布局和功能。请注意,我已将示例图更新绑定到单击refresh按钮 - 您可以将类似的过程绑定到与实际脉冲设备的接口。您所需要的只是分别绘制到x和y轴的时间bpm对。

PulseActivity#onCreate

    // Local variable for simulating the sample time
    private int x = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pulse);

        //Connect U.I Elements
        getPulseRate = (Button) findViewById(R.id.heartRateBtn);
        pulseRateView = (TextView) findViewById(R.id.pulseValueView);
        connectionStsView = (TextView) findViewById(R.id.connectionStsView);
        refreshButton = (Button) findViewById(R.id.refreshBtn);

        final GraphView graphView = new LineGraphView(
                this, // context
                "Pulse Rate Sensor" // heading
        );

        graphView.setVerticalLabels(new String[]{"high", "normal", "low"});

        graphView.setCustomLabelFormatter(new CustomLabelFormatter() {
            @Override
            public String formatLabel(double value, boolean isValueX) {
                if (isValueX) {
                    return null;
                } else {
                    if (value < 60) {
                        return "low";
                    } else if (value < 100) {
                        return "normal";
                    } else {
                        return "high";
                    }
                }
            }
        });

        // init heart rate series data
        rateSeries = new GraphViewSeries(new GraphView.GraphViewData[]{
        });
        graphView.addSeries(rateSeries);

        LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
        layout.addView(graphView);

        getPulseRate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String setOutputMessage = "/bpm /";
                tx.setValue(setOutputMessage.getBytes(Charset.forName("UTF-8")));
                if (gatt.writeCharacteristic(tx)) {
                    writeConnectionData("Sent: " + setOutputMessage);
                } else {
                    writeConnectionData("Couldn't write TX characteristic!");
                }
            }
        });

        refreshButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //restartScan();
                rateSeries.appendData(new GraphView.GraphViewData(x += 3, new Random().nextInt(100)), false, 100);
                graphView.redrawAll();
            }
        });
    }

activity_pulse.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="250dip"
        android:id="@+id/graph1"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp" />

    <LinearLayout
        android:id="@+id/rest"
        android:layout_width="fill_parent"
        android:layout_height="250dip"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Refresh Connection"
            android:id="@+id/refreshBtn"
            android:layout_gravity="center_horizontal" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Get Heart Rate"
            android:id="@+id/heartRateBtn"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Last Pulse Rate Value"
            android:id="@+id/pulsePlaceholderText"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Large Text"
            android:id="@+id/pulseValueView"
            android:layout_gravity="center_horizontal" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="Connection Status"
            android:id="@+id/connectionStsView"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>

</LinearLayout>