Code for automatic pill box dispenser

Dependencies:   mbed-rtos mbed sMotor

Committer:
cchoi63
Date:
Wed Dec 13 04:43:36 2017 +0000
Revision:
1:71eb56bcafce
Parent:
0:d223f8829ec0
removed commented code, changed bracket style

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cchoi63 0:d223f8829ec0 1 /*
cchoi63 0:d223f8829ec0 2 ----- Authors -----
cchoi63 0:d223f8829ec0 3
cchoi63 0:d223f8829ec0 4 Sahithi Bonala
cchoi63 0:d223f8829ec0 5 Stephen Brotman
cchoi63 0:d223f8829ec0 6 Christie Choi
cchoi63 0:d223f8829ec0 7 Brandon Sheu
cchoi63 0:d223f8829ec0 8
cchoi63 0:d223f8829ec0 9 ----- Acknowledgements -----
cchoi63 0:d223f8829ec0 10
cchoi63 0:d223f8829ec0 11 Samuel Matildes (sam.naeec@gmail.com) for the sMotor v0.1 Test Program that
cchoi63 0:d223f8829ec0 12 interfaces between the mbed and 4-phase stepper motors.
cchoi63 0:d223f8829ec0 13
cchoi63 0:d223f8829ec0 14 */
cchoi63 0:d223f8829ec0 15
cchoi63 0:d223f8829ec0 16 #include "mbed.h"
cchoi63 0:d223f8829ec0 17 #include "sMotor.h"
cchoi63 0:d223f8829ec0 18 #include "rtos.h"
cchoi63 0:d223f8829ec0 19
cchoi63 0:d223f8829ec0 20 //Interrupts
cchoi63 0:d223f8829ec0 21 InterruptIn touchsensor(p12); // Touch sensor
cchoi63 0:d223f8829ec0 22
cchoi63 0:d223f8829ec0 23 //Digital Inputs
cchoi63 0:d223f8829ec0 24 DigitalIn refill_pb(p30); // Pushbutton to refill
cchoi63 0:d223f8829ec0 25
cchoi63 0:d223f8829ec0 26 //Digital Outputs
cchoi63 0:d223f8829ec0 27 DigitalOut myled(LED1);
cchoi63 0:d223f8829ec0 28 DigitalOut myled2(LED2);
cchoi63 0:d223f8829ec0 29
cchoi63 0:d223f8829ec0 30 //PWM Outputs
cchoi63 0:d223f8829ec0 31 PwmOut led_red(p21); // Red LED of an RGB LED
cchoi63 0:d223f8829ec0 32 PwmOut led_green(p22); // Green LED of an RGB LED
cchoi63 0:d223f8829ec0 33 PwmOut led_blue(p23); // Blue LED of an RGB LED
cchoi63 0:d223f8829ec0 34
cchoi63 0:d223f8829ec0 35 //Serial Connection
cchoi63 0:d223f8829ec0 36 Serial pc(USBTX, USBRX);
cchoi63 0:d223f8829ec0 37
cchoi63 0:d223f8829ec0 38 //sMotor Interface
cchoi63 0:d223f8829ec0 39 sMotor motor(p8, p9, p10, p11); // Creates new stepper motor: IN1, IN2, IN3, IN4
cchoi63 0:d223f8829ec0 40
cchoi63 0:d223f8829ec0 41 //Threads
cchoi63 0:d223f8829ec0 42 Thread thread_motor; // Motor thread
cchoi63 0:d223f8829ec0 43 Thread thread_refill; // Refill thread
cchoi63 0:d223f8829ec0 44 Thread thread_control; // Timing controller thread
cchoi63 0:d223f8829ec0 45 Thread thread_led; // LED thread
cchoi63 0:d223f8829ec0 46 Thread thread_cmd; // Serial command thread
cchoi63 0:d223f8829ec0 47
cchoi63 0:d223f8829ec0 48 //Timing
cchoi63 0:d223f8829ec0 49 Timer timer;
cchoi63 0:d223f8829ec0 50 Ticker ticker;
cchoi63 0:d223f8829ec0 51
cchoi63 0:d223f8829ec0 52 //Initialization for LED
cchoi63 0:d223f8829ec0 53 float led_red_value = 0.0; //current red LED value
cchoi63 0:d223f8829ec0 54 float led_green_value = 0.0; //current green LED value
cchoi63 0:d223f8829ec0 55 float led_blue_value = 0.0; //current blue LED value
cchoi63 0:d223f8829ec0 56 int led_color = 0x000000; //color of the LED
cchoi63 0:d223f8829ec0 57 int led_gradient_duration = 3; //duration of gradient between LED colors
cchoi63 0:d223f8829ec0 58 bool led_blink = false; //whether to blink the LED
cchoi63 0:d223f8829ec0 59 bool led_update = false; //whether to update the color of the LED
cchoi63 0:d223f8829ec0 60
cchoi63 0:d223f8829ec0 61 //Initialization for stepper motor
cchoi63 0:d223f8829ec0 62 int step_speed = 1200; //set default motor speed
cchoi63 0:d223f8829ec0 63 int numstep = 512 ; //defines full turn of 360 degree
cchoi63 0:d223f8829ec0 64 bool motor_turn = false; //whether to turn the motor or not
cchoi63 0:d223f8829ec0 65
cchoi63 0:d223f8829ec0 66 //Initialization for the pill container
cchoi63 0:d223f8829ec0 67 float pill_interval = 15.0; //time between pills (seconds)
cchoi63 0:d223f8829ec0 68 int pill_taken_counter = 0;
cchoi63 0:d223f8829ec0 69 int pill_refill_counter = 0;
cchoi63 0:d223f8829ec0 70 bool pill_taken = false;
cchoi63 0:d223f8829ec0 71 bool pill_refilled = false;
cchoi63 0:d223f8829ec0 72
cchoi63 0:d223f8829ec0 73 bool cmd_send = false;
cchoi63 0:d223f8829ec0 74 int cmd_type = 0; //1 is time, 2 is pill
cchoi63 0:d223f8829ec0 75
cchoi63 0:d223f8829ec0 76 void SendCmdTime() {
cchoi63 0:d223f8829ec0 77 //Send a command through Serial telling the mySQL database to update the
cchoi63 1:71eb56bcafce 78 //time
cchoi63 0:d223f8829ec0 79 cmd_type = 1;
cchoi63 0:d223f8829ec0 80 cmd_send = true;
cchoi63 0:d223f8829ec0 81 }
cchoi63 0:d223f8829ec0 82
cchoi63 0:d223f8829ec0 83 void SendCmdPill() {
cchoi63 0:d223f8829ec0 84 // Send a command through Serial telling the mySQL database to update the
cchoi63 0:d223f8829ec0 85 // pill status
cchoi63 0:d223f8829ec0 86 cmd_type = 2;
cchoi63 0:d223f8829ec0 87 cmd_send = true;
cchoi63 0:d223f8829ec0 88 }
cchoi63 0:d223f8829ec0 89
cchoi63 1:71eb56bcafce 90 void ControlCmd() {
cchoi63 0:d223f8829ec0 91 while (true) {
cchoi63 0:d223f8829ec0 92 if (cmd_send) {
cchoi63 0:d223f8829ec0 93 switch (cmd_type) {
cchoi63 0:d223f8829ec0 94 case 1:
cchoi63 0:d223f8829ec0 95 pc.printf("cmdTime\n");
cchoi63 0:d223f8829ec0 96 break;
cchoi63 0:d223f8829ec0 97 case 2:
cchoi63 0:d223f8829ec0 98 pc.printf("cmdPill\n");
cchoi63 0:d223f8829ec0 99 break;
cchoi63 0:d223f8829ec0 100 }
cchoi63 0:d223f8829ec0 101 cmd_type = 0;
cchoi63 0:d223f8829ec0 102 cmd_send = false;
cchoi63 0:d223f8829ec0 103 }
cchoi63 0:d223f8829ec0 104 Thread::wait(200);
cchoi63 0:d223f8829ec0 105 }
cchoi63 0:d223f8829ec0 106 }
cchoi63 0:d223f8829ec0 107
cchoi63 0:d223f8829ec0 108 void TouchDetected() {
cchoi63 0:d223f8829ec0 109 // Called when the touch sensor detects a touch
cchoi63 0:d223f8829ec0 110 pill_taken = true;
cchoi63 0:d223f8829ec0 111 myled2 = true;
cchoi63 0:d223f8829ec0 112
cchoi63 0:d223f8829ec0 113 // Update the status in the database
cchoi63 0:d223f8829ec0 114 SendCmdPill();
cchoi63 0:d223f8829ec0 115 }
cchoi63 0:d223f8829ec0 116
cchoi63 0:d223f8829ec0 117 void TouchRemoved() {
cchoi63 0:d223f8829ec0 118 // Called to reset variables when the touch sensor no longer detects a touch
cchoi63 0:d223f8829ec0 119 pill_taken = false;
cchoi63 0:d223f8829ec0 120 myled2 = false;
cchoi63 0:d223f8829ec0 121 }
cchoi63 0:d223f8829ec0 122
cchoi63 0:d223f8829ec0 123 void UpdateLed(int color, bool blink = false, int duration = 3) {
cchoi63 0:d223f8829ec0 124 // Update the color of the LED
cchoi63 0:d223f8829ec0 125 led_color = color;
cchoi63 0:d223f8829ec0 126 led_blink = blink;
cchoi63 0:d223f8829ec0 127 led_gradient_duration = duration;
cchoi63 0:d223f8829ec0 128 led_update = true;
cchoi63 0:d223f8829ec0 129 }
cchoi63 0:d223f8829ec0 130
cchoi63 0:d223f8829ec0 131 void ControlLed() {
cchoi63 0:d223f8829ec0 132 //thread for RGB LED that uses global variables
cchoi63 0:d223f8829ec0 133 //(int) led_color - a hexadecimal value for the color, e.g. 0xFF0000 for red
cchoi63 0:d223f8829ec0 134 //(int) led_blink (optional) - whether to blink or not
cchoi63 0:d223f8829ec0 135 //(int) led_gradient_duration (optional) - duration for gradient in seconds
cchoi63 0:d223f8829ec0 136
cchoi63 0:d223f8829ec0 137 while (true) {
cchoi63 0:d223f8829ec0 138 if (led_update) {
cchoi63 0:d223f8829ec0 139 float r = ((float)((0xFF0000 & led_color)>>16))/255.0;
cchoi63 0:d223f8829ec0 140 float g = ((float)((0x00FF00 & led_color)>>8))/255.0;
cchoi63 0:d223f8829ec0 141 float b = ((float)(0x0000FF & led_color))/255.0;
cchoi63 0:d223f8829ec0 142 //pc.printf("R: %0.2f, G: %0.2f, B: %0.2f\n", r, g, b);
cchoi63 0:d223f8829ec0 143 float dR = (r-led_red_value)/(100.0);
cchoi63 0:d223f8829ec0 144 float dG = (g-led_green_value)/(100.0);
cchoi63 0:d223f8829ec0 145 float dB = (b-led_blue_value)/(100.0);
cchoi63 0:d223f8829ec0 146 for (int i = 1; i <= 100; i++) {
cchoi63 0:d223f8829ec0 147 led_red.write(led_red_value + (dR*i));
cchoi63 0:d223f8829ec0 148 led_green.write(led_green_value + (dG*i));
cchoi63 0:d223f8829ec0 149 led_blue.write(led_blue_value + (dB*i));
cchoi63 0:d223f8829ec0 150 wait(((float)led_gradient_duration)/(100.0));
cchoi63 0:d223f8829ec0 151 }
cchoi63 0:d223f8829ec0 152
cchoi63 0:d223f8829ec0 153 if (led_blink) {
cchoi63 0:d223f8829ec0 154 float time_wait = (float)led_gradient_duration*0.125;
cchoi63 0:d223f8829ec0 155 for (int i = 0; i < 4; i++) {
cchoi63 0:d223f8829ec0 156 // Turn off LED
cchoi63 0:d223f8829ec0 157 led_red.write(0.0);
cchoi63 0:d223f8829ec0 158 led_green.write(0.0);
cchoi63 0:d223f8829ec0 159 led_blue.write(0.0);
cchoi63 0:d223f8829ec0 160 wait(time_wait);
cchoi63 0:d223f8829ec0 161
cchoi63 0:d223f8829ec0 162 // Turn on LED
cchoi63 0:d223f8829ec0 163 led_red.write(r);
cchoi63 0:d223f8829ec0 164 led_green.write(g);
cchoi63 0:d223f8829ec0 165 led_blue.write(b);
cchoi63 0:d223f8829ec0 166 wait(time_wait);
cchoi63 0:d223f8829ec0 167 }
cchoi63 0:d223f8829ec0 168 }
cchoi63 0:d223f8829ec0 169
cchoi63 0:d223f8829ec0 170 led_red_value = r;
cchoi63 0:d223f8829ec0 171 led_green_value = g;
cchoi63 0:d223f8829ec0 172 led_blue_value = b;
cchoi63 0:d223f8829ec0 173
cchoi63 0:d223f8829ec0 174 led_update = false;
cchoi63 0:d223f8829ec0 175 }
cchoi63 0:d223f8829ec0 176 Thread::wait(500);
cchoi63 0:d223f8829ec0 177 }
cchoi63 0:d223f8829ec0 178 }
cchoi63 0:d223f8829ec0 179
cchoi63 0:d223f8829ec0 180 void ControlTiming() {
cchoi63 0:d223f8829ec0 181 timer.start();
cchoi63 0:d223f8829ec0 182 ticker.attach(&SendCmdTime, pill_interval);
cchoi63 0:d223f8829ec0 183
cchoi63 0:d223f8829ec0 184 while(true) {
cchoi63 0:d223f8829ec0 185 int delay = (pill_taken_counter+1)*pill_interval;
cchoi63 0:d223f8829ec0 186 float time_difference = timer.read()-delay;
cchoi63 0:d223f8829ec0 187 float time_limit_warn = pill_interval/5.0;
cchoi63 0:d223f8829ec0 188 float time_limit_alert = pill_interval/4.0;
cchoi63 0:d223f8829ec0 189
cchoi63 0:d223f8829ec0 190 if (pill_taken) {
cchoi63 0:d223f8829ec0 191 // Pill is taken
cchoi63 0:d223f8829ec0 192 UpdateLed(0x000000, false);
cchoi63 0:d223f8829ec0 193
cchoi63 0:d223f8829ec0 194 if (timer.read() >= delay) {
cchoi63 0:d223f8829ec0 195 // Increment container
cchoi63 0:d223f8829ec0 196 motor_turn = true;
cchoi63 0:d223f8829ec0 197 } else {
cchoi63 0:d223f8829ec0 198 motor_turn = false;
cchoi63 0:d223f8829ec0 199 }
cchoi63 0:d223f8829ec0 200 } else if (time_difference >= -pill_interval &&
cchoi63 0:d223f8829ec0 201 time_difference < time_limit_warn) {
cchoi63 0:d223f8829ec0 202 // Pill is ready to be taken
cchoi63 0:d223f8829ec0 203 UpdateLed(0x00FF00, false);
cchoi63 0:d223f8829ec0 204 } else if (time_difference >= time_limit_warn &&
cchoi63 0:d223f8829ec0 205 time_difference < time_limit_alert) {
cchoi63 0:d223f8829ec0 206 // Pill still not taken, warning
cchoi63 0:d223f8829ec0 207 // change LED color
cchoi63 0:d223f8829ec0 208 UpdateLed(0xFFFF00, true);
cchoi63 0:d223f8829ec0 209 } else if (time_difference >= time_limit_alert) {
cchoi63 0:d223f8829ec0 210 // Pill still not taken, alert
cchoi63 0:d223f8829ec0 211 UpdateLed(0xFF0000, true);
cchoi63 0:d223f8829ec0 212 } else {
cchoi63 0:d223f8829ec0 213 UpdateLed(0x000000, false);
cchoi63 0:d223f8829ec0 214 }
cchoi63 0:d223f8829ec0 215
cchoi63 0:d223f8829ec0 216 if (pill_taken_counter == 7) {
cchoi63 0:d223f8829ec0 217 UpdateLed(0x0000FF, false);
cchoi63 0:d223f8829ec0 218 }
cchoi63 0:d223f8829ec0 219
cchoi63 0:d223f8829ec0 220 if (pill_refilled) {
cchoi63 0:d223f8829ec0 221 ticker.detach();
cchoi63 0:d223f8829ec0 222 timer.stop();
cchoi63 0:d223f8829ec0 223 timer.reset();
cchoi63 0:d223f8829ec0 224 timer.start();
cchoi63 0:d223f8829ec0 225 ticker.attach(&SendCmdTime, pill_interval);
cchoi63 0:d223f8829ec0 226
cchoi63 0:d223f8829ec0 227 pill_refilled = false;
cchoi63 0:d223f8829ec0 228
cchoi63 0:d223f8829ec0 229 UpdateLed(0x000000, false);
cchoi63 0:d223f8829ec0 230 }
cchoi63 0:d223f8829ec0 231
cchoi63 0:d223f8829ec0 232 Thread::wait(100);
cchoi63 0:d223f8829ec0 233 }
cchoi63 0:d223f8829ec0 234 }
cchoi63 0:d223f8829ec0 235
cchoi63 0:d223f8829ec0 236 void ControlMotor() {
cchoi63 0:d223f8829ec0 237 while(true) {
cchoi63 0:d223f8829ec0 238 while (pill_taken_counter < 7) {
cchoi63 0:d223f8829ec0 239 if (motor_turn == true) {
cchoi63 0:d223f8829ec0 240 motor.step(numstep/7, 0, step_speed); // Number of steps, direction, speed
cchoi63 0:d223f8829ec0 241 pill_taken_counter++;
cchoi63 0:d223f8829ec0 242
cchoi63 0:d223f8829ec0 243 // Reest touch sensor variables
cchoi63 0:d223f8829ec0 244 TouchRemoved();
cchoi63 0:d223f8829ec0 245 motor_turn = false;
cchoi63 0:d223f8829ec0 246 }
cchoi63 0:d223f8829ec0 247 }
cchoi63 0:d223f8829ec0 248 Thread::wait(500);
cchoi63 0:d223f8829ec0 249 }
cchoi63 0:d223f8829ec0 250 }
cchoi63 0:d223f8829ec0 251
cchoi63 0:d223f8829ec0 252 void ControlRefill() {
cchoi63 0:d223f8829ec0 253 //refill_pb.mode(PullUp);
cchoi63 0:d223f8829ec0 254 while(true) {
cchoi63 0:d223f8829ec0 255 while (pill_taken_counter == 7) {
cchoi63 0:d223f8829ec0 256 myled = 1;
cchoi63 0:d223f8829ec0 257 wait(0.2);
cchoi63 0:d223f8829ec0 258 myled = 0;
cchoi63 0:d223f8829ec0 259 wait(0.2);
cchoi63 0:d223f8829ec0 260 if (refill_pb == 0 && pill_refill_counter < 6) {
cchoi63 0:d223f8829ec0 261 pill_refill_counter++;
cchoi63 0:d223f8829ec0 262 motor.step(numstep/7, 0, step_speed);
cchoi63 0:d223f8829ec0 263 }
cchoi63 0:d223f8829ec0 264
cchoi63 0:d223f8829ec0 265 if (pill_refill_counter == 6 && refill_pb == 0) {
cchoi63 0:d223f8829ec0 266 motor.step(numstep/7, 0, step_speed);
cchoi63 0:d223f8829ec0 267 pill_taken_counter = 0;
cchoi63 0:d223f8829ec0 268 pill_refill_counter = 0;
cchoi63 0:d223f8829ec0 269 pill_refilled = true;
cchoi63 0:d223f8829ec0 270 }
cchoi63 0:d223f8829ec0 271 }
cchoi63 0:d223f8829ec0 272 Thread::wait(500);
cchoi63 0:d223f8829ec0 273 }
cchoi63 0:d223f8829ec0 274 }
cchoi63 0:d223f8829ec0 275
cchoi63 0:d223f8829ec0 276 int main() {
cchoi63 0:d223f8829ec0 277 //Set refill pushbutton as a pull-up
cchoi63 0:d223f8829ec0 278 refill_pb.mode(PullUp);
cchoi63 0:d223f8829ec0 279
cchoi63 0:d223f8829ec0 280 //Initiate touch sensor interrupt
cchoi63 0:d223f8829ec0 281 touchsensor.fall(&TouchDetected);
cchoi63 0:d223f8829ec0 282
cchoi63 0:d223f8829ec0 283 //Start threads
cchoi63 0:d223f8829ec0 284 thread_motor.start(ControlMotor);
cchoi63 0:d223f8829ec0 285 thread_refill.start(ControlRefill);
cchoi63 0:d223f8829ec0 286 thread_control.start(ControlTiming);
cchoi63 0:d223f8829ec0 287 thread_led.start(ControlLed);
cchoi63 0:d223f8829ec0 288 thread_cmd.start(ControlCmd);
cchoi63 0:d223f8829ec0 289
cchoi63 0:d223f8829ec0 290 //Write LED values
cchoi63 0:d223f8829ec0 291 led_red.period(0.0005); //2kHz period for less flicker
cchoi63 0:d223f8829ec0 292 led_green.period(0.0005); //2kHz period for less flicker
cchoi63 0:d223f8829ec0 293 led_blue.period(0.0005); //2kHz period for less flicker
cchoi63 0:d223f8829ec0 294 led_red.write(led_red_value);
cchoi63 0:d223f8829ec0 295 led_green.write(led_green_value);
cchoi63 0:d223f8829ec0 296 led_blue.write(led_blue_value);
cchoi63 0:d223f8829ec0 297 }