working wavelet transform

Dependencies:   CMSIS_DSP_5 include mbed

Fork of Nucleo-Heart-Rate by BAP TUDelft

Revision:
11:337c5ff16f27
Parent:
10:f62efa525bb6
--- a/main.cpp	Thu Jun 21 11:55:09 2018 +0000
+++ b/main.cpp	Fri Jun 22 13:46:16 2018 +0000
@@ -12,6 +12,37 @@
 
 Serial usb_serial(SERIAL_TX, SERIAL_RX);    // tx, rx
 const int baud_rate = 115200;     // Baud rate.
+double* getPeaks(double* values, int window, double Tr_low)
+{
+    static double result[4] = {0, 0, 0, 0}; // {Value min, index min, value max, index max}
+    int wnd_max = 320;//Max window is 2 seconds = 2*fs = 320
+    int cont =0;// Variable to continue to max peak find
+    int i,j;
+    for(i = 0; i < wnd_max; i++) {
+        if(values[i] < Tr_low) { //Find MIN peak below a threshold
+            result[0] = values[i]; // Place where the threshold is met
+            cont=1; //Continue to find MAX peak
+            for(j=i; j<i+window; j++) {//Find MIN peak
+                if(values[j] < result[0]) {
+                    result[0] = values[j];  //value MIN peak
+                    result[1] = (double) j; //index MIN peak
+                }
+            }
+            break;
+        }
+    }
+    if (cont==1) {
+        for(i = result[1]; i < result[1]+window; i++) {
+            result[2]=0;
+            if (values[i]>result[2]) {
+                result[2]=values[i];
+                result[3]=(double) i;
+            }
+        }
+    }
+
+    return result;//Will return result = {0,0,0,0} if nothing is found
+}
 
 int main()
 {
@@ -22,46 +53,116 @@
 
     int N_samples = 2000;
     int wt_scale = 3;
-//    int fs = 160;
     int i,j;
-   
-    
+    static int fs =160;//Sampling freq.
+    int wnd_offset = 0.25*fs;
+    static int wnd=0.05*fs;//Window to find peaks in
+    int Strtup =1;// Start with the starting sequence
+    double Tr_low = -0.02; //Threshold MIN peak
+    double Tr_temp = 0; //Temporary threshold MIN peak
+    double Tr_scale = 0.45; //Starting threshold scale
+    double *Peaks=(double*)calloc(4,sizeof(double)); //To save peak data
+    double *PTD=(double*)calloc(3,sizeof(double)); //To save peak time difference
+    int *Index_min=(int*)calloc(4,sizeof(int)); //To save MIN peak index
+    int *Index_max=(int*)calloc(4,sizeof(int)); //To save MAX peak index
+    double PTD_temp;//Temporary value of PTD
+    double MTD2;//PTD average of last two PTD
+    double MTD3;//PTD average of last 3 PTD
     double *inp = signal_in; //,*out,*diff;
     double *out =(double*)malloc(sizeof(double)* N_samples);
     double *wt_res=(double*)malloc(sizeof(double)* N_samples);
-     
+    double *t_wavelet=(double*)malloc(sizeof(double)* N_samples); //To save wavelet coefficients temporarily
+
+        
     char *m_wavelet = "db4";
+    
     wave_init_obj = wave_init(m_wavelet);// Initialize the wavelet
 
     wavelet = wt_init(wave_init_obj, "modwt", N_samples, wt_scale);// Initialize the wavelet transform object
 
     modwt(wavelet, inp);// Perform MODW
-    wt_summary(wavelet);
-    double t_wavelet[N_samples*wt_scale+2000];
-    memset(t_wavelet,0,N_samples*wt_scale+2000);
 
-//    int wt_scale_start=((wavelet->outlength)/wt_scale)*0;//1=last level
-//    int wt_scale_end=((wavelet->outlength)/wt_scale)*2;
     int wt_scale_start=2000;//Level 3
     int wt_scale_end=4000;
     //Choose scales
     for (i=0,j=wt_scale_start; j<wt_scale_end; i++,j++) {
         t_wavelet[i]=wavelet->output[j];
     }
+
     wavelet->output=t_wavelet;
     imodwt(wavelet,out);// Perform IMODWT
-
     for (i=0; i<N_samples; ++i) {
         wt_res[i]=wavelet->output[i]*fabs(wavelet->output[i]);
     }
-    
-    while(1) {
+while (1) {
+            if (Strtup == 1) { //Starting sequence
+                //First heartbeat
+                Peaks = getPeaks(wt_res, wnd, Tr_low);// Peaks={Value min, index min, value max, index max}               
+                Tr_temp = Tr_scale*Peaks[0]; //Set MIN peak threshold
+                Index_min[0]= (int)Peaks[1]; //Save MIN peak index
+                Index_max[0]=(int)Peaks[3]; //Save MAX peak index
 
-        for (i = 0; i < N_samples; ++i) {
-            usb_serial.printf("%d %e \n",i, wt_res[i]);
+                for (i=0; i<3; i++) { //Next 3 heartbeats
+                    Peaks = getPeaks(wt_res+(wnd_offset+Index_min[i]), wnd, Tr_temp);// Peaks={Value min, index min, value max, index max}
+                    Tr_temp = Tr_scale*Peaks[0];//Set MIN peak threshold
+                    Index_min[i+1]=wnd_offset+Index_min[i]+(int)Peaks[1];//Save MIN peak index + starting offset
+                    Index_max[i+1]=wnd_offset+Index_min[i]+(int)Peaks[3];//Save MAX peak index + starting offset
+                    PTD[i] = Index_max[i+1]-Index_max[i];//Determine PTD
+                    wnd_offset = 0.5*PTD[i]; //Set new window offset
+                }
+                //Set MTD2 & MTD3
+                MTD2 = (PTD[2]+PTD[1])/2;
+                MTD3 = (PTD[2]+PTD[1]+PTD[0])/3;
+                if(MTD2>(0.9*MTD3) && MTD2<(1.1*MTD3)) { //Signal stable, so heartbeat found
+                    Strtup = 0;
+                    Tr_low =Tr_temp;
+                } else { //Unstable signal, restart startup
+                    Strtup = 1;
+                    Tr_low = -0.01;
+                }
+                
+            } else if(Strtup==0) { //Normal sequence
+                //First heartbeat
+                Peaks = getPeaks(wt_res, wnd, Tr_low);// Peaks={Value min, index min, value max, index max}
+                Tr_temp = Tr_scale*Peaks[0]; //Set MIN peak threshold
+                Index_min[0]=(int)Peaks[1]; //Save MIN peak index
+                Index_max[0]=(int)Peaks[3]; //Save MAX peak index     
+usb_serial.printf("Normal sequence started \n");        
+                for (i=0; i<2; i++) {
+                    Peaks = getPeaks(wt_res+(wnd_offset+Index_min[i]), wnd, Tr_temp);// Peaks={Value min, index min, value max, index max}
+                    Tr_temp = Tr_scale*Peaks[0]; //Set MIN peak threshold
+                    Index_min[i+1]=wnd_offset+Index_min[i]+(int)Peaks[1]; //Save MIN peak index
+                    Index_max[i+1]=wnd_offset+Index_min[i]+(int)Peaks[3]; //Save MAX peak index 
+                    
+                    PTD_temp=Index_max[i+1]-Index_max[i];
+                    if (PTD_temp>= (0.8*MTD2) && PTD_temp<= (1.2*MTD2)) {//Found heart rate
+                        Strtup = 0;//Continue normal sequence 
+                        Tr_low =Tr_temp; //Set threshold
+                        //Pop off first PTD and add PTD_temp to the back of PTD
+                        PTD[1]=PTD[2];
+                        PTD[0]=PTD[1];
+                        PTD[2]=PTD_temp;
+                        
+                        //Set MTD2 & MTD3
+                        MTD2 = (PTD[2]+PTD[1])/2;
+                        MTD3 = (PTD[2]+PTD[1]+PTD[0])/2;
+        
+                        break; 
+                    }
+                    Strtup = 1;
+                }
+            } else { //Error
+                usb_serial.printf("Error in algorithm");
+            }
+            break;
         }
-        myled = !myled;
-    }
+    
+//    while(1) {
+//        for (i = 0; i < N_samples; ++i) {
+//            usb_serial.printf("%d %e \n",i, wt_res[i]);
+//        }
+//        myled = !myled;
+//    }
  //   while(1) {
 //
 //        for (i = 0; i < N_samples; ++i) {