pulsensor: Added new sensor (not stable and not documented yet)
authorKiveisha Yevgeniy <yevgeniy.kiveisha@intel.com>
Wed, 18 Jun 2014 09:37:50 +0000 (09:37 +0000)
committerKiveisha Yevgeniy <yevgeniy.kiveisha@intel.com>
Wed, 18 Jun 2014 09:37:50 +0000 (09:37 +0000)
Signed-off-by: Kiveisha Yevgeniy <yevgeniy.kiveisha@intel.com>
examples/CMakeLists.txt
examples/pulsensor.cxx [new file with mode: 0644]
src/pulsensor/CMakeLists.txt [new file with mode: 0644]
src/pulsensor/jsupm_pulsensor.i [new file with mode: 0644]
src/pulsensor/pulsensor.cxx [new file with mode: 0644]
src/pulsensor/pulsensor.h [new file with mode: 0644]
src/pulsensor/pyupm_pulsensor.i [new file with mode: 0644]

index 0fcd077..edf92ac 100644 (file)
@@ -18,6 +18,7 @@ add_executable (lcd st7735.cxx)
 add_executable (max31855-example max31855.cxx)
 add_executable (gy65-example gy65.cxx)
 add_executable (stepmotor-example stepmotor.cxx)
+add_executable (pulsensor-example pulsensor.cxx)
 
 include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
 include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -34,6 +35,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/st7735)
 include_directories (${PROJECT_SOURCE_DIR}/src/max31855)
 include_directories (${PROJECT_SOURCE_DIR}/src/gy65)
 include_directories (${PROJECT_SOURCE_DIR}/src/stepmotor)
+include_directories (${PROJECT_SOURCE_DIR}/src/pulsensor)
 
 target_link_libraries (compass hmc5883l ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries (groveled grove ${CMAKE_THREAD_LIBS_INIT})
@@ -55,3 +57,4 @@ target_link_libraries (lcd st7735 ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries (max31855-example max31855 ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries (gy65-example gy65 ${CMAKE_THREAD_LIBS_INIT})
 target_link_libraries (stepmotor-example stepmotor ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries (pulsensor-example pulsensor ${CMAKE_THREAD_LIBS_INIT})
diff --git a/examples/pulsensor.cxx b/examples/pulsensor.cxx
new file mode 100644 (file)
index 0000000..196d704
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include "pulsensor.h"
+#include <signal.h>
+
+int doWork = 0;
+pulsensor_context sensor_ctx;
+
+void
+sig_handler(int signo)
+{
+    printf("got signal\n");
+    if (signo == SIGINT) {
+        printf("exiting application\n");
+        doWork = 1;
+    }
+}
+
+void
+handler (clbk_data data) {
+    printf ("callback data (%d)\n", data);
+}
+
+int
+main(int argc, char **argv)
+{
+//! [Interesting]
+    init_pulsensor (&sensor_ctx, handler);
+    
+    start_sampler (&sensor_ctx);
+    while (!doWork) {
+        usleep (5);
+    }
+    stop_sampler (&sensor_ctx);
+//! [Interesting]
+    return 0;
+}
diff --git a/src/pulsensor/CMakeLists.txt b/src/pulsensor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..223c642
--- /dev/null
@@ -0,0 +1,5 @@
+set (libname "pulsensor")
+set (libdescription "upm PULSENSOR")
+set (module_src ${libname}.cxx)
+set (module_h ${libname}.h)
+upm_module_init()
diff --git a/src/pulsensor/jsupm_pulsensor.i b/src/pulsensor/jsupm_pulsensor.i
new file mode 100644 (file)
index 0000000..ff6d49d
--- /dev/null
@@ -0,0 +1,7 @@
+%module jsupm_pulsensor
+
+%{
+    #include "pulsensor.h"
+%}
+
+%include "pulsensor.h"
diff --git a/src/pulsensor/pulsensor.cxx b/src/pulsensor/pulsensor.cxx
new file mode 100644 (file)
index 0000000..ae19b3b
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include "pulsensor.h"
+
+void init_pulsensor (pulsensor_context * ctx, callback_handler handler) {
+    ctx->callback = handler;
+    
+    ctx->pin_ctx = maa_aio_init(0);
+    
+    ctx->sample_counter = 0;
+    ctx->last_beat_time = 0;
+    ctx->threshold      = 512;
+    ctx->ibi            = 600;
+    ctx->trough         = 512;
+    ctx->peak           = 512;
+    ctx->is_pulse       = FALSE;
+    ctx->ret            = FALSE;
+    ctx->bpm            = 0;
+    ctx->qs             = FALSE;
+    ctx->apmlitude      = 100;
+}
+
+void start_sampler (pulsensor_context * ctx) {
+    int error;
+    ctx_counter++;
+    usleep (100000);
+    error = pthread_create (&(ctx->sample_thread), NULL, do_sample, (void *) ctx);
+    if (error != 0) {
+        printf ("ERROR : Cannot created sampler thread.\n");
+    }
+}
+
+void stop_sampler (pulsensor_context * ctx) {
+    ctx_counter--;
+}
+
+void * do_sample (void * arg) {
+    int data_from_sensor;
+    clbk_data callback_data;
+    while (ctx_counter) {
+        pulsensor_context * ctx = (pulsensor_context *) arg;
+        maa_aio_context pin = ctx->pin_ctx;
+        data_from_sensor = maa_aio_read (pin);
+        ctx->ret = FALSE;
+        
+        ctx->sample_counter += 2;
+        int N = ctx->sample_counter - ctx->last_beat_time;
+        
+        if (data_from_sensor < ctx->threshold && N > ( ctx->ibi / 5)* 3) {
+            if (data_from_sensor < ctx->trough) {
+                ctx->trough = data_from_sensor;
+            }
+        }
+        
+        if (data_from_sensor > ctx->threshold && data_from_sensor > ctx->peak) {
+            ctx->peak = data_from_sensor;
+        }
+        
+        if (N > 250) {
+            // printf ("(NO_GDB) DEBUG\n");
+            if ( (data_from_sensor > ctx->threshold) && 
+                    (ctx->is_pulse == FALSE) && 
+                    (N > (ctx->ibi / 5)* 3) ) {
+                ctx->is_pulse = callback_data.is_heart_beat = TRUE;
+                ((pulsensor_context *) arg)->callback(callback_data);
+                
+                ctx->ibi = ctx->sample_counter - ctx->last_beat_time;
+                ctx->last_beat_time = ctx->sample_counter;
+                
+                // second beat
+                if (ctx->second_beat) {
+                    ctx->second_beat = FALSE;
+                    for (int i = 0; i <= 9; i++) {
+                        ctx->ibi_rate[i] = ctx->ibi;                      
+                    }
+                }
+                
+                // first beat
+                if (ctx->first_beat) {
+                    ctx->first_beat  = FALSE;
+                    ctx->second_beat = TRUE;
+                    ctx->ret = TRUE;
+                } else {                    
+                    uint32_t running_total = 0;
+                    for(int i = 0; i <= 8; i++){
+                        ctx->ibi_rate[i] = ctx->ibi_rate[i+1];
+                        running_total += ctx->ibi_rate[i];
+                    }
+                    
+                    ctx->ibi_rate[9] = ctx->ibi;
+                    running_total += ctx->ibi_rate[9];
+                    running_total /= 10;
+                    ctx->bpm = 60000 / running_total;
+                    ctx->qs = TRUE;
+                }
+            }
+        }
+        
+        if (ctx->ret == FALSE) {
+            if (data_from_sensor < ctx->threshold && ctx->is_pulse == TRUE) {
+                ctx->is_pulse = callback_data.is_heart_beat = FALSE;
+                ((pulsensor_context *) arg)->callback(callback_data);
+                
+                ctx->is_pulse   = FALSE;
+                ctx->apmlitude  = ctx->peak - ctx->trough;
+                ctx->threshold  = ctx->apmlitude / 2 + ctx->trough;
+                ctx->peak       = ctx->threshold;
+                ctx->trough     = ctx->threshold;
+            }
+
+            if (N > 2500) {
+                ctx->threshold      = 512;
+                ctx->peak           = 512;
+                ctx->trough         = 512;
+                ctx->last_beat_time = ctx->sample_counter;    
+                ctx->first_beat     = TRUE;
+                ctx->second_beat    = FALSE;
+            }
+        }
+        
+        usleep (2000);
+    }
+}
diff --git a/src/pulsensor/pulsensor.h b/src/pulsensor/pulsensor.h
new file mode 100644 (file)
index 0000000..ae54832
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
+ * Copyright (c) 2014 Intel Corporation.
+ *
+ * Credits to Adafruit.
+ * Based on Adafruit BMP085 library.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#pragma once
+
+#include <string>
+#include <math.h>
+#include <maa/pwm.h>
+#include <maa/aio.h>
+#include <maa/gpio.h>
+#include <pthread.h>
+
+#define HIGH               1
+#define LOW                0
+
+#define TRUE               HIGH
+#define FALSE              LOW
+
+struct clbk_data {
+    int is_heart_beat;
+};
+
+typedef void (* callback_handler) (clbk_data);
+
+struct pulsensor_context {
+    pthread_t        sample_thread;
+    uint32_t         sample_counter;
+    uint32_t         last_beat_time;
+    int              threshold;
+    int              ibi_rate[10];
+    int              ibi;
+    int              trough;
+    int              peak;
+    int              bpm;
+    int              apmlitude;
+    uint8_t          qs;
+    uint8_t          is_pulse;
+    uint8_t          first_beat;
+    uint8_t          second_beat;
+    uint8_t          pin;
+    uint8_t          ret;
+    maa_aio_context  pin_ctx;
+    
+    callback_handler callback;
+};
+
+static volatile uint16_t ctx_counter = 0;
+
+void init_pulsensor (pulsensor_context * ctx, callback_handler handler);
+void start_sampler (pulsensor_context * ctx);
+void stop_sampler (pulsensor_context * ctx);
+
+void * do_sample (void * arg);
diff --git a/src/pulsensor/pyupm_pulsensor.i b/src/pulsensor/pyupm_pulsensor.i
new file mode 100644 (file)
index 0000000..cece2b0
--- /dev/null
@@ -0,0 +1,10 @@
+%module pyupm_pulsensor
+
+%include "stdint.i"
+
+%feature("autodoc", "3");
+
+%include "pulsensor.h"
+%{
+    #include "pulsensor.h"
+%}