Code for automatic pill box dispenser

Dependencies:   mbed-rtos mbed sMotor

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