Anurag Muglikar
/
pacemaker_new
Pacemaker models
Embed:
(wiki syntax)
Show/hide line numbers
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 }
Generated on Tue Jul 12 2022 23:07:57 by 1.7.2