1

I'm trying to create an app that calculates heart rate from an ecg signal that is picked up and sent to the app using bluetooth. I have been able to create the code that will detect the peaks in an ecg signal (which would be an array of 500 values), calculate heart rate and output it to the screen. So far the array is hardcoded. But I would like to ensure that every time the array is overwritten, the calculations are performed again and new values are being outputted to the screen. So it essentially needs to be constantly repeating. I tried inserting my entire code in the following loop:

while(true) { }

As you can see below:

private class ProcessECG extends Thread {
    public ProcessECG() {

    }

        public void run() {

        heartRateValues = (TextView) findViewById(R.id.heartRateValues);

        double rawHeartData[] = {0.024, -0.016, -0.032, 0.016, -0.008, 0.024, 0.016, -0.016, 0.016, -0.016, 0.0, 0.112, 0.096, -0.264, -0.272, 0.136, 0.272, 0.096, 0.088, -0.016, 0.024, -0.024, -0.008, -0.04, -0.032, 0.008, -0.024, 0.008, -0.016, 0.016, 0.024, -0.024, -0.016, 0.016, -0.016, 0.016, -0.016, 0.016, 0.024, -0.008, 0.008, 0.056, 0.056, 0.008, 0.016, -0.032, -0.032, 0.0, -0.024, 0.008, -0.016, 0.024, -0.016, 0.024, -0.016, 0.016, -0.016, 0.016, 0.016, -0.016, 0.024, -0.016, -0.008, 0.024, -0.016, 0.024, 0.024, -0.016, -0.008, 0.016, 0.024, -0.016, 0.016, -0.016, -0.016, 0.024, -0.016, 0.024, -0.008, 0.024, -0.016, 0.024, 0.024, -0.016, -0.016, 0.024, -0.016, 0.016, 0.016, -0.016, -0.016, 0.024, 0.016, -0.024, -0.016, 0.024, 0.024, -0.016, 0.016, -0.016, -0.016, 0.048, 0.08, -0.064, -0.08, -0.216, -0.144, 0.2, 0.208, 0.024, 0.024, -0.008, 0.008, -0.032, -0.032, 0.008, -0.024, 0.016, 0.016, -0.024, -0.024, 0.016, 0.016, -0.024, -0.016, 0.016, -0.024, 0.016, -0.008, 0.016, -0.008, 0.032, 0.008, 0.048, 0.032, -0.016, 0.0, -0.032, -0.032, 0.0, -0.024, 0.024, 0.024, -0.016, -0.024, 0.024, -0.016, 0.016, 0.024, -0.016, -0.016, 0.024, 0.024, -0.016, -0.016, 0.024, 0.024, -0.016, -0.016, 0.016, 0.024, -0.016, -0.016, 0.024, -0.016, 0.024, -0.016, 0.024, -0.008, 0.024, 0.016, -0.016, -0.016, 0.024, -0.016, 0.016, -0.016, 0.016, -0.008, 0.024, 0.016, -0.016, -0.008, 0.024, -0.016, 0.024, 0.016, -0.024, 0.008, -0.024, -0.008, 0.024, 0.024, -0.016, -0.008, 0.016, -0.008, 0.08, 0.064, -0.264, -0.232, 0.192, 0.224, 0.072, 0.056, -0.032, 0.016, -0.032, -0.032, -0.008, -0.032, 0.008, 0.016, -0.016, -0.024, 0.016, -0.016, 0.016, 0.024, -0.016, 0.016, -0.024, 0.016, -0.016, -0.008, 0.024, 0.0, 0.04, 0.056, 0.0, 0.024, -0.024, 0.0, -0.032, -0.032, 0.016, -0.024, 0.016, -0.016, 0.016, 0.024, -0.016, 0.024, -0.008, -0.016, 0.016, -0.016, 0.016, 0.016, -0.016, 0.024, -0.016, 0.024, -0.016, -0.016, 0.024, -0.016, 0.016, -0.016, 0.024, 0.024, -0.016, 0.024, -0.016, -0.016, 0.016, -0.016, 0.024, 0.024, -0.024, 0.016, -0.016, 0.024, -0.016, 0.016, -0.016, -0.016, 0.016, -0.016, 0.024, 0.024, -0.016, -0.008, 0.024, -0.008, 0.104, 0.08, -0.28, -0.28, 0.12, 0.256, 0.128, 0.12, -0.032, 0.008, -0.016, -0.04, -0.008, -0.032, 0.008, 0.0, -0.024, -0.016, 0.024, -0.016, 0.016, 0.024, -0.024, -0.024, 0.016, 0.016, -0.016, -0.016, 0.024, 0.0, 0.056, 0.056, 0.0, 0.016, -0.032, 0.0, -0.032, -0.032, 0.016, -0.024, 0.016, -0.024, 0.016, -0.016, 0.016, 0.016, -0.016, -0.016, 0.024, 0.016, -0.016, 0.016, -0.016, -0.016, 0.024, -0.008, 0.024, -0.016, 0.024, -0.016, 0.024, -0.016, 0.024, -0.016, 0.024, 0.024, -0.016, 0.024, -0.016, 0.016, -0.008, -0.016, 0.016, -0.016, 0.016, 0.016, -0.016, 0.024, -0.016, -0.016, 0.024, -0.016, 0.024, 0.024, -0.032, 0.008, -0.032, -0.008, 0.024, 0.024, -0.008, 0.024, -0.016, -0.016, 0.024, 0.112, -0.072, -0.088, -0.272, -0.128, 0.272, 0.248, -0.008, 0.024, -0.024, 0.0, -0.048, -0.032, 0.0, -0.032, 0.008, -0.032, 0.016, -0.024, 0.016, 0.016, -0.016, 0.024, -0.016, 0.016, -0.024, -0.016, 0.016, -0.016, 0.024, 0.008, 0.056, 0.04, -0.008, 0.016, -0.032, -0.04, 0.0, -0.024, 0.016, 0.016, -0.024, 0.016, -0.016, 0.024, -0.016, -0.016, 0.016, -0.016, 0.024, -0.016, 0.016, 0.024, -0.008, 0.024, -0.016, -0.016, 0.024, -0.016, 0.016, 0.016, -0.016, -0.016, 0.024, 0.024, -0.016, -0.008, 0.024, 0.016, -0.024, -0.008, 0.024, 0.024, -0.032, 0.024, -0.016, -0.008, 0.016, -0.016, 0.024, -0.016, 0.024, 0.024, -0.016, 0.024, -0.016, -0.016, 0.016, -0.024, 0.008, -0.008, 0.024, 0.024, -0.016, 0.024, -0.016, -0.016, 0.04, 0.096, -0.152, -0.256, -0.112, -0.088, 0.264, 0.248, 0.008, -0.024, 0.008, 0.0, -0.04, -0.032, 0.0, -0.032, 0.008, -0.024, 0.016, -0.024, 0.016, -0.016, 0.024, -0.024, 0.016, 0.016, -0.024, -0.016, 0.024, -0.008, 0.032, 0.008, 0.056, 0.04, -0.016, 0.008, -0.032, 0.0, -0.032, -0.032, 0.016, -0.016, 0.016, 0.016, -0.016, 0.024, -0.016, -0.016, 0.024, -0.016, 0.024, -0.016, 0.016, 0.024, -0.016, 0.024, -0.016, -0.024, 0.024, -0.016, 0.024, -0.016, 0.016, -0.016, 0.016, 0.024, -0.016, 0.024, -0.008, -0.016, 0.024, -0.024, 0.016, -0.016, 0.016, -0.016, 0.024, 0.024, -0.016, -0.008, 0.024, 0.016, -0.024, -0.032, 0.008, -0.008, 0.024, 0.024, -0.016, 0.016, -0.016, -0.016, 0.064, 0.104, -0.224, -0.264, 0.024, 0.04, 0.248, 0.176, -0.024, -0.032, 0.016, -0.032, 0.0, 0.0, -0.032, 0.016, -0.024, -0.032, 0.008, -0.016, 0.016, 0.016, -0.032, 0.016, -0.024, 0.016, -0.016, -0.016, 0.024, -0.008, 0.04};


        double max = 0;
        for (int i = 0; i <rawHeartData.length; i++) {
            if (rawHeartData[i] > max) {
                max = rawHeartData[i];
            }
        }
        double threshold = 0.7*max;



        while (true) {

            //Calculate Heart Rate from list "Raw Data"
            int upflag = 0;
            int last = 1;
            int p = 0;
            int t = 0;
            int count = 0;
            //List<Double> heartRate2 = new ArrayList<Double>();
            int heartRate[] = new int[7];

            for (int i = 0; i < rawHeartData.length; i++) {
                if (rawHeartData[i]> threshold){
                    if (upflag == 0){
                        if (last > 0){
                            t = i - last;
                            p = 100*60/t;
                            //100 is the sampling rate

                            heartRate[count]= p;
                            count = count + 1;
                            //int k = (int) p;
                            //heartRate2.add(p);
                        }
                        last = i;
                    }
                    upflag = 50;
                }

                else {
                    if (upflag > 0){
                        upflag = upflag -1;
                    }
                }

            }
            //Change array to String and display last value
            String heartRate3 = Arrays.toString(heartRate);
            String[] bits = heartRate3.split(",");
            String lastValue = bits[bits.length-1];

            heartRateValues.setText(lastValue + "bpm");

        }

        }


}

However that just kept causing my app to crash and I get the following error:

03-15 14:22:50.809  10094-10300/es.pymasde.blueterm E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-1165
Process: es.pymasde.blueterm, PID: 10094
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6247)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:867)
        at android.view.View.requestLayout(View.java:17364)
        at android.view.View.requestLayout(View.java:17364)
        at android.view.View.requestLayout(View.java:17364)
        at android.view.View.requestLayout(View.java:17364)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
        at android.view.View.requestLayout(View.java:17364)
        at android.widget.TextView.checkForRelayout(TextView.java:6855)
        at android.widget.TextView.setText(TextView.java:4047)
        at android.widget.TextView.setText(TextView.java:3905)
        at android.widget.TextView.setText(TextView.java:3880)
        at es.pymasde.blueterm.ProcessActivity$ProcessECG.run(ProcessActivity.java:164)

It errors out when it comes to setText but works perfectly fine when the code is outside the while loop. I found the following link in response to my error: Android "Only the original thread that created a view hierarchy can touch its views." error in Fragment However, Im still not sure how to use runOnUIThread. Is that the best solution or are there any ideas regarding how to make sure that my calculations are constantly being performed in real time while new data is coming in?

Community
  • 1
  • 1
Code
  • 21
  • 3
  • Have your background threat process incoming ECG data. Once calculated, post it to a UI handler, or execute a runnable on the UI thread. Or better yet, create a LocalBroadcastReceiver. – 323go Mar 15 '15 at 23:07
  • 1
    I posted it to a UI handler and that worked perfectly! Thank you! – Code Mar 16 '15 at 01:15

1 Answers1

-1

Well, you will need to setText on the ui thread, no matter what.

However, depending on how much data you are processing and how often, you might want to do this at an interval which doesn't cause too much work on the UI thread.

puj
  • 770
  • 5
  • 9