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

标签 android bluetooth arduino android-graphview

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

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

screenshot

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

1 , 2 , 3 , 4 , 5 , 6 , 7

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

我正在努力解决三个主要问题:

  1. 正确标记 X 和 Y 值
  2. 将心率传感器数据附加到图表中

完整项目可在以下网址获得: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();
        }
    });
}

非常感谢您的帮助,感谢您抽出宝贵时间。

最佳答案

下面的解决方案配置您的图表以实现您想要的基本布局和功能。请注意,我已将示例图形更新绑定(bind)到单击 refresh 按钮 - 您可以将类似的过程绑定(bind)到您的接口(interface)与实际脉冲设备。您所需要的只是要分别绘制到 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>

关于android - 在 Android 应用程序中为蓝牙脉搏率传感器创建实时图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26109056/

相关文章:

java - 如何在 Android 中检测整个图像已下载

java - Mac 操作系统和 Java 蓝牙

java - 应用程序在 Android Studio 中崩溃。 getMenuInflater().inflate(R.menu.activity_main, 菜单);不存在?

android - Android 6.0 中的蓝牙简单安全配对不起作用

android - 无法使用蓝牙 HC-06 发送数据 - 应用程序停止工作

Android 音频延迟解决方法

javascript - HTML5 视频自动播放不适用于手机和平板电脑

php - 没有数据从 Android 插入到 MySQL

arrays - Arduino atmega2560代码大小

Arduino 无符号长溢出