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?