![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Code for automatic pill box dispenser
Dependencies: mbed-rtos mbed sMotor
Diff: main.cpp
- Revision:
- 0:d223f8829ec0
- Child:
- 1:71eb56bcafce
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 13 04:28:37 2017 +0000 @@ -0,0 +1,300 @@ +/* +----- Authors ----- + +Sahithi Bonala +Stephen Brotman +Christie Choi +Brandon Sheu + +----- Acknowledgements ----- + +Samuel Matildes (sam.naeec@gmail.com) for the sMotor v0.1 Test Program that +interfaces between the mbed and 4-phase stepper motors. + +*/ + +#include "mbed.h" +#include "sMotor.h" +#include "rtos.h" + +//Interrupts +InterruptIn touchsensor(p12); // Touch sensor + +//Digital Inputs +DigitalIn refill_pb(p30); // Pushbutton to refill + +//Digital Outputs +DigitalOut myled(LED1); +DigitalOut myled2(LED2); + +//PWM Outputs +PwmOut led_red(p21); // Red LED of an RGB LED +PwmOut led_green(p22); // Green LED of an RGB LED +PwmOut led_blue(p23); // Blue LED of an RGB LED + +//Serial Connection +Serial pc(USBTX, USBRX); + +//sMotor Interface +sMotor motor(p8, p9, p10, p11); // Creates new stepper motor: IN1, IN2, IN3, IN4 + +//Threads +Thread thread_motor; // Motor thread +Thread thread_refill; // Refill thread +Thread thread_control; // Timing controller thread +Thread thread_led; // LED thread +Thread thread_cmd; // Serial command thread + +//Timing +Timer timer; +Ticker ticker; + +//Initialization for LED +float led_red_value = 0.0; //current red LED value +float led_green_value = 0.0; //current green LED value +float led_blue_value = 0.0; //current blue LED value +int led_color = 0x000000; //color of the LED +int led_gradient_duration = 3; //duration of gradient between LED colors +bool led_blink = false; //whether to blink the LED +bool led_update = false; //whether to update the color of the LED + +//Initialization for stepper motor +int step_speed = 1200; //set default motor speed +int numstep = 512 ; //defines full turn of 360 degree +bool motor_turn = false; //whether to turn the motor or not + +//Initialization for the pill container +float pill_interval = 15.0; //time between pills (seconds) +int pill_taken_counter = 0; +int pill_refill_counter = 0; +bool pill_taken = false; +bool pill_refilled = false; + +bool cmd_send = false; +int cmd_type = 0; //1 is time, 2 is pill + +void SendCmdTime() { + //Send a command through Serial telling the mySQL database to update the + //time + //pc.printf("cmdTime\n"); + cmd_type = 1; + cmd_send = true; +} + +void SendCmdPill() { + // Send a command through Serial telling the mySQL database to update the + // pill status + //pc.printf("cmdPill\n"); + cmd_type = 2; + cmd_send = true; +} + +void ControlCmd() +{ + while (true) { + if (cmd_send) { + switch (cmd_type) { + case 1: + pc.printf("cmdTime\n"); + break; + case 2: + pc.printf("cmdPill\n"); + break; + } + cmd_type = 0; + cmd_send = false; + } + Thread::wait(200); + } +} + +void TouchDetected() { + // Called when the touch sensor detects a touch + pill_taken = true; + myled2 = true; + + // Update the status in the database + SendCmdPill(); +} + +void TouchRemoved() { + // Called to reset variables when the touch sensor no longer detects a touch + pill_taken = false; + myled2 = false; +} + +void UpdateLed(int color, bool blink = false, int duration = 3) { + // Update the color of the LED + led_color = color; + led_blink = blink; + led_gradient_duration = duration; + led_update = true; +} + +void ControlLed() { + //thread for RGB LED that uses global variables + //(int) led_color - a hexadecimal value for the color, e.g. 0xFF0000 for red + //(int) led_blink (optional) - whether to blink or not + //(int) led_gradient_duration (optional) - duration for gradient in seconds + + while (true) { + if (led_update) { + float r = ((float)((0xFF0000 & led_color)>>16))/255.0; + float g = ((float)((0x00FF00 & led_color)>>8))/255.0; + float b = ((float)(0x0000FF & led_color))/255.0; + //pc.printf("R: %0.2f, G: %0.2f, B: %0.2f\n", r, g, b); + float dR = (r-led_red_value)/(100.0); + float dG = (g-led_green_value)/(100.0); + float dB = (b-led_blue_value)/(100.0); + for (int i = 1; i <= 100; i++) { + led_red.write(led_red_value + (dR*i)); + led_green.write(led_green_value + (dG*i)); + led_blue.write(led_blue_value + (dB*i)); + wait(((float)led_gradient_duration)/(100.0)); + } + + if (led_blink) { + float time_wait = (float)led_gradient_duration*0.125; + for (int i = 0; i < 4; i++) { + // Turn off LED + led_red.write(0.0); + led_green.write(0.0); + led_blue.write(0.0); + wait(time_wait); + + // Turn on LED + led_red.write(r); + led_green.write(g); + led_blue.write(b); + wait(time_wait); + } + } + + led_red_value = r; + led_green_value = g; + led_blue_value = b; + + led_update = false; + } + Thread::wait(500); + } +} + +void ControlTiming() { + timer.start(); + ticker.attach(&SendCmdTime, pill_interval); + + while(true) { + int delay = (pill_taken_counter+1)*pill_interval; + float time_difference = timer.read()-delay; + float time_limit_warn = pill_interval/5.0; + float time_limit_alert = pill_interval/4.0; + + if (pill_taken) { + // Pill is taken + UpdateLed(0x000000, false); + + if (timer.read() >= delay) { + // Increment container + motor_turn = true; + } else { + motor_turn = false; + } + } else if (time_difference >= -pill_interval && + time_difference < time_limit_warn) { + // Pill is ready to be taken + UpdateLed(0x00FF00, false); + } else if (time_difference >= time_limit_warn && + time_difference < time_limit_alert) { + // Pill still not taken, warning + // change LED color + UpdateLed(0xFFFF00, true); + } else if (time_difference >= time_limit_alert) { + // Pill still not taken, alert + UpdateLed(0xFF0000, true); + } else { + UpdateLed(0x000000, false); + } + + if (pill_taken_counter == 7) { + UpdateLed(0x0000FF, false); + } + + if (pill_refilled) { + ticker.detach(); + timer.stop(); + timer.reset(); + timer.start(); + ticker.attach(&SendCmdTime, pill_interval); + + pill_refilled = false; + + UpdateLed(0x000000, false); + } + + Thread::wait(100); + } +} + +void ControlMotor() { + while(true) { + while (pill_taken_counter < 7) { + if (motor_turn == true) { + motor.step(numstep/7, 0, step_speed); // Number of steps, direction, speed + pill_taken_counter++; + + // Reest touch sensor variables + TouchRemoved(); + motor_turn = false; + } + } + Thread::wait(500); + } +} + +void ControlRefill() { + //refill_pb.mode(PullUp); + while(true) { + while (pill_taken_counter == 7) { + myled = 1; + wait(0.2); + myled = 0; + wait(0.2); + if (refill_pb == 0 && pill_refill_counter < 6) { + pill_refill_counter++; + motor.step(numstep/7, 0, step_speed); + } + + if (pill_refill_counter == 6 && refill_pb == 0) { + motor.step(numstep/7, 0, step_speed); + pill_taken_counter = 0; + pill_refill_counter = 0; + pill_refilled = true; + } + } + Thread::wait(500); + } +} + +int main() { + //Set refill pushbutton as a pull-up + refill_pb.mode(PullUp); + + //Initiate touch sensor interrupt + touchsensor.fall(&TouchDetected); + + //Start threads + thread_motor.start(ControlMotor); + thread_refill.start(ControlRefill); + thread_control.start(ControlTiming); + thread_led.start(ControlLed); + thread_cmd.start(ControlCmd); + + //Write LED values + led_red.period(0.0005); //2kHz period for less flicker + led_green.period(0.0005); //2kHz period for less flicker + led_blue.period(0.0005); //2kHz period for less flicker + led_red.write(led_red_value); + led_green.write(led_green_value); + led_blue.write(led_blue_value); +} \ No newline at end of file