Pacemaker models

Dependencies:   MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #define MQTTCLIENT_QOS2 1
00002 
00003 #include "ESP8266Interface.h"
00004 #include "MQTTNetwork.h"
00005 #include "MQTTmbed.h"
00006 #include "MQTTClient.h"
00007 #include "TextLCD.h"
00008 #include "mbed.h"
00009 #include "time.h"
00010 
00011 #include <string.h>
00012 #include <stdlib.h>
00013 #include <deque>
00014 
00015 #define IAP_LOCATION 0x1FFF1FF1
00016 
00017 // Serial port for debug
00018 Serial pc(USBTX, USBRX);
00019 TextLCD LcdControl(p15,p16,p17,p18,p14,p20, TextLCD::LCD16x2);
00020 int LRI = 1100;
00021 int HRI = 1500;
00022 unsigned int case_count = 0;
00023 
00024 // Heart monitor window averaging variables
00025 #define AVG_WINDOW      20 // Can be 20, 40, or 60 seconds
00026 #define AVG_INTERVAL    5 // Can be 5, 10, 15, or 20 seconds
00027 
00028 
00029 DigitalOut led_slow_alarm(LED3);
00030 DigitalOut led_fast_alarm(LED4);
00031 
00032 DigitalOut senseBeatLED(LED1);
00033 DigitalOut sendPaceLED(LED2);
00034 
00035 
00036 DigitalOut pace_signal(p19);
00037 InterruptIn receive_sense(p5);
00038 InterruptIn case1_sense(p21);
00039 InterruptIn case2_sense(p22);
00040 InterruptIn case3_sense(p23);
00041 
00042 
00043 ESP8266Interface wifi(p28, p27);
00044 
00045 // Defines for monitor
00046 #define URL             100 //This is in bpm, not ms
00047 #define RATE_ALARM      1
00048 #define PACE_ALARM      2
00049 #define PACE_THRESH     10  // Pretty arbitrary number
00050 
00051 int RI = 1500; 
00052 int VRP = 240;
00053 bool hp_enable, hp;   
00054 bool sense_received = 0;
00055 bool sense_flag = 0;
00056 bool pace_sent = 0;
00057 time_t start_time;
00058 Timer timer;
00059 Ticker indicator;
00060 Ticker paceIndicator;
00061 
00062 /* pace_times is a subest of beat_times. I need all beats and paces to
00063  * calculate the average heartrate, but only the number of paces to determine 
00064  * if the too slow alarm needs to go off. 
00065  */
00066 deque<time_t> beat_times;
00067 deque<time_t> pace_times;
00068 
00069 // The number of times each alarm has occured
00070 unsigned int rate_alarm_count = 0;
00071 unsigned int pace_alarm_count = 0;
00072 
00073 // Threads
00074 Thread pacemaker_thread;
00075 Thread monitor_observe;
00076 Thread monitor_calculate;
00077 
00078 
00079 const char* hostname = "broker.hivemq.com";
00080 int port = 1883;
00081 char* topic = "sectopic";
00082 char* rTopic = "sectopic";
00083 MQTTNetwork network(&wifi);
00084 MQTTNetwork mqttNetwork(network);
00085 MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork);
00086 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00087 MQTT::Message message;
00088 char buf[100];
00089 
00090 // This looks at the time difference in each element
00091 // of both the pace and heartbeat queues and removes
00092 // any which are too old, i.e. outside the averaging window time
00093 void prune_lists(time_t new_time) 
00094 {
00095     
00096     // Only look at the front of the queues because elements are added
00097     // already sorted
00098     while (difftime(new_time, beat_times.front()) > AVG_WINDOW) 
00099     {
00100         beat_times.pop_front(); 
00101     }
00102     
00103     while (difftime(new_time, pace_times.front()) > AVG_WINDOW)
00104     {
00105         pace_times.pop_front();    
00106     }
00107  
00108     
00109 }
00110 
00111 // Flash an LED for an alarm and send an MQTT message 
00112 // to the cloud
00113 void monitor_alarm(int alarm) 
00114 {
00115     int i;
00116     Timer alarm_t;
00117     alarm_t.start();
00118     if (alarm == RATE_ALARM) 
00119     {
00120         for (i = 0; i < 3; i++) 
00121         {
00122             
00123             led_fast_alarm = 1;
00124             while(alarm_t.read_ms() < 200*(i+1));
00125             led_fast_alarm = 0;
00126         }
00127         rate_alarm_count++;
00128         sprintf(buf, "Fast Alarm :%d", rate_alarm_count);
00129         pc.printf("Too fast\r\n");
00130         
00131     } else if (alarm == PACE_ALARM) 
00132     {
00133         pace_alarm_count++;
00134         sprintf(buf, "Slow Alarm :%d", pace_alarm_count);  
00135         for (i = 0; i < 3; i++) 
00136         {
00137             led_slow_alarm = 1;
00138             while(alarm_t.read_ms() < 200*(i + 1)) ;
00139             led_slow_alarm = 0;
00140         }
00141         pc.printf("Too slow\r\n");
00142     }else{
00143           sprintf(buf, "Normal :%d", 1);    
00144     }
00145     message.qos = MQTT::QOS0;
00146     message.retained = true;
00147     message.dup = false;
00148     message.payload = (void*)buf;
00149     message.payloadlen = strlen(buf);
00150     int rc = client.publish(topic, message);
00151     
00152     client.yield(100);
00153     if(rc == 0){
00154         printf("Success PUB%d\n", rc);
00155     }else{
00156         printf("Failed PUB%d\n", rc);
00157         client.connect(data);
00158     }
00159 } 
00160 
00161 
00162 // This is a thread for the monitor which simply watches for new beats and
00163 // paces and adds them to the queue(s) when they occur
00164 void monitor_obs() 
00165 {
00166     
00167     time_t new_time;
00168     
00169     // Monitor just runs forever
00170     while (1) {
00171     
00172         // Wait until you see a sense or pace
00173         while (!sense_flag && !pace_sent) ;
00174     
00175         // Indicate if you saw a sense or a pace, then set the indicator back to
00176         // 0 so that the current signal is not counted more than once
00177         if (sense_flag) {
00178             beat_times.push_back(time(NULL));
00179             sense_flag = 0;
00180         }
00181         if (pace_sent) {
00182             new_time = time(NULL);
00183             beat_times.push_back(new_time);
00184             pace_times.push_back(new_time);
00185             pace_sent = 0;
00186         }
00187     
00188     }
00189 }
00190 
00191 void  monitor_calc() 
00192 {
00193     time_t current_time;
00194     time_t wait_start = time(NULL);
00195     
00196     int heart_rate;
00197     int num_paces;
00198     int normal_count = 0;
00199     //printf("calc...\n");
00200     // I want to check the heart rate in bpm for the alarm,
00201     // so if my window time is smaller than 60 seconds I want to have
00202     // this window factor to scale it
00203     int window_factor = 60 / AVG_WINDOW;
00204     
00205     // The monitor needs to wait for at least one full AVG_WINDOW
00206     // before it starts to monitor the average heartrate or else 
00207     // it is going to give spurious low heartrate alarms
00208     while (difftime(time(NULL),wait_start) < AVG_WINDOW);
00209     
00210     
00211     message.qos = MQTT::QOS1;
00212     while(1) {
00213           //pc.printf("In monitor calc loop\r\n");
00214          // Get the current time and see if you need to prune any elements from
00215          // your lists
00216          current_time = time(NULL);
00217          prune_lists(current_time);
00218             
00219          
00220          // Find average heart rate and number of paces if it is time to,
00221          // then set any necessary alarms
00222             heart_rate = beat_times.size() * window_factor;
00223             num_paces = pace_times.size();
00224             pc.printf("H.R = %d\r\n", heart_rate);
00225             pc.printf("N.P = %d\r\n", num_paces);
00226             sprintf(buf, "BPM :%d", heart_rate);
00227             LcdControl.cls();
00228             LcdControl.printf("BPM: %03d  TC:%d", heart_rate, case_count);
00229             message.retained = true;
00230             message.dup = false;
00231             message.payload = (void*)buf;
00232             message.payloadlen = strlen(buf);
00233             int rc = client.publish(topic, message);
00234             int rate_flag = 0;
00235             int pace_flag = 0;
00236             
00237             
00238             client.yield(100);
00239             if(rc == 0){
00240                 printf("Success PUB%d\n", rc);
00241             }else{
00242                 printf("Failed PUB%d\n", rc);
00243                 client.connect(data);
00244             }
00245             //printf("About to alarm\r\n");
00246             if (heart_rate > URL) {
00247                 monitor_alarm(RATE_ALARM);    
00248                 rate_flag = 1;
00249             }
00250             if (num_paces > PACE_THRESH) {
00251                 monitor_alarm(PACE_ALARM);
00252                 pace_flag = 1;    
00253             }
00254             if(heart_rate < URL && num_paces < PACE_THRESH){
00255                   normal_count++;
00256                   sprintf(buf, "Normal :%d", normal_count);    
00257             }
00258             LcdControl.locate(0, 1);
00259             LcdControl.printf("AF:%d AS:%d NC:%03d", rate_flag, pace_flag, normal_count);
00260             rate_flag=0; 
00261             pace_flag=0;
00262             message.qos = MQTT::QOS0;
00263             message.retained = true;
00264             message.dup = false;
00265             message.payload = (void*)buf;
00266             message.payloadlen = strlen(buf);
00267             rc = client.publish(topic, message);
00268             
00269             client.yield(100);
00270             if(rc == 0){
00271                 printf("Success PUB%d\n", rc);
00272             }else{
00273                 printf("Failed PUB%d\n", rc);
00274                 client.connect(data);
00275             }
00276          //printf("Alarm done\r\n");
00277          wait_start = time(NULL);
00278          // Wait until you need to calculate averages again
00279          while (difftime(time(NULL),wait_start) < AVG_INTERVAL); 
00280     }
00281 }
00282 
00283 void flip(){
00284 senseBeatLED = 0;
00285 indicator.detach();    
00286 }
00287     
00288 // ISR to receive sense signals
00289 void receive_sense_ISR()
00290 {
00291     sense_received = 1;
00292 }
00293 
00294 void case1_sense_ISR()
00295 {
00296     case_count = 1;
00297 }
00298 
00299 void case2_sense_ISR()
00300 {
00301     case_count = 2;
00302 }
00303 
00304 void case3_sense_ISR()
00305 {
00306     case_count = 3;
00307 }
00308 
00309 void pIndicate(){
00310     sendPaceLED = 0;
00311     paceIndicator.detach();
00312 }
00313 
00314 void pace()
00315 {
00316     sendPaceLED = 1;
00317     paceIndicator.attach(&pIndicate, 0.1);   
00318     pace_signal = 1;
00319     pace_signal = 0;
00320 }
00321 
00322 void pacemaker()
00323 {
00324     //start_time = timer.read_ms();
00325     timer.reset();
00326     timer.start();
00327     while(true)
00328     {
00329         switch(case_count) 
00330         {
00331                 case 1:
00332                         LRI = 1100;
00333                         HRI = 1500;
00334                         break;
00335                 case 2:
00336                         LRI = 1100;
00337                         HRI = 2000;
00338                         break;
00339                 case 3:
00340                         LRI = 300;
00341                         HRI = 500;
00342                         break;
00343                 default:
00344                         LRI = 1100;
00345                         HRI = 1500;
00346                         break;
00347             }
00348         
00349         while(!sense_received && ((timer.read_ms()) < RI));
00350         if (sense_received)
00351         {
00352             //pc.printf("sense received\n");
00353             sense_received = 0;
00354             // Let monitor know there was a heartbeaat
00355             sense_flag = 1;
00356             RI = HRI;
00357             hp = true;
00358             timer.reset();
00359             senseBeatLED = 1;
00360             indicator.attach(&flip, 0.01);
00361         }
00362         else
00363         {
00364             // Send pace signal to heart
00365             pace();
00366             // Indicate oace was sent for monitor
00367             pace_sent = 1;
00368             //pc.printf("paced - %d\n", (timer.read_ms() - start_time));
00369             RI = LRI;
00370             hp = false;
00371             //start_time = timer.read_ms();
00372             timer.reset();
00373         }
00374         // Wait for VRP
00375         receive_sense.disable_irq();
00376         while((timer.read_ms()) < VRP);
00377         receive_sense.enable_irq();
00378         hp_enable = hp;
00379     }
00380 }
00381     
00382 int main() 
00383 {
00384     
00385     led_slow_alarm = 0;
00386     led_fast_alarm = 0;
00387     pc.baud(9600);
00388     LcdControl.cls();
00389     LcdControl.printf("PACEMAKER");
00390     // Enable the ISR to receive snse signals from heart simulator
00391     wifi.set_credentials(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD);
00392     wifi.connect();
00393     int rc = network.connect(hostname, port);
00394     pc.printf("Connecting to %s:%d\r\n", hostname, port);
00395     rc = mqttNetwork.connect(hostname, port);
00396     data.MQTTVersion = 3;
00397     data.clientID.cstring = "26013f37-13006018ae2a8ca752c368e3f5001e81";
00398     data.username.cstring = "mbed";
00399     data.password.cstring = "homework";
00400     if ((rc = client.connect(data)) != 0)
00401         pc.printf("rc from MQTT connect is %d\r\n", rc);
00402     receive_sense.rise(&receive_sense_ISR);
00403     case1_sense.rise(&case1_sense_ISR);
00404     case2_sense.rise(&case2_sense_ISR);
00405     case3_sense.rise(&case3_sense_ISR);
00406     
00407     // Start both the threads - pacemaker and observer
00408     monitor_observe.start(monitor_obs);
00409     monitor_calculate.start(monitor_calc);
00410     pacemaker_thread.start(pacemaker);
00411 }