#include <Servo.h>
#include <SoftwareSerial.h>
#include <Process.h>
#define VOICE_MODULE
#define DEMO_ONLY
//#define VIDEO_TAKING_ONLY
#define SPINNER_PIN 5
#define EJECTOR_PIN 6
#define DISPLAY_RX 8
#define DISPLAY_TX 9
#ifdef VOICE_MODULE
#define VOICE_RX 10
#define VOICE_TX 11
#endif
#define EJECT_ANGLE 35
#define REST_ANGLE 180
#define USER_INFO_URL "http://YOUR_IP:YOUR_PORT/user_info"
#define NEXT_SCHEDULE_URL "http://YOUR_IP:YOUR_PORT/next_schedule"
#define TAKEN_URL "http://YOUR_IP:YOUR_PORT/taken"
Servo spinner_servo;
Servo ejector_servo;
SoftwareSerial display_serial(DISPLAY_RX, DISPLAY_TX);
#ifdef VOICE_MODULE
SoftwareSerial voice_serial(VOICE_RX, VOICE_TX);
#endif
int pill_slot_angle[] = {15, 60, 105, 150};
byte buf_page_cmd[] = {'p', 'a', 'g', 'e', ' ', '0', 0xFF, 0xFF, 0xFF};
byte buf_set_str_cmd[] = {'s', 'c', 'h', 'e', '_', 's', 't', 'r', '.', 't', 'x', 't', '=', '"', '0', '0', ':', '0', '0', '"', 0xFF, 0xFF, 0xFF};
#ifdef VOICE_MODULE
// voice volume 1-30
//byte buf_voice_vol[] = {0xAA, 0x13, 0x01, 0x0F, 0xCD}; // command to set volume 15
//byte buf_voice_vol[] = {0xAA, 0x13, 0x01, 0x14, 0xD2}; // command to set volume 20
byte buf_voice_vol[] = {0xAA, 0x13, 0x01, 0x19, 0xD7}; // command to set volume 25
//byte buf_voice_vol[] = {0xAA, 0x13, 0x01, 0x1E, 0xDC}; // command to set volume 30
byte buf_play[4][6] = {
{0xAA, 0x07, 0x02, 0x00, 0x01, 0xB4}, // command to play 01.mp3
{0xAA, 0x07, 0x02, 0x00, 0x02, 0xB5}, // command to play 02.mp3
{0xAA, 0x07, 0x02, 0x00, 0x03, 0xB6}, // command to play 03.mp3
{0xAA, 0x07, 0x02, 0x00, 0x04, 0xB7} // command to play 04.mp3
};
#endif
// function declaration
void ui_page(byte page);
void wait_next_schedule();
void eject_pill(byte pill_slot);
void get_user_info();
void get_next_schedule();
void push_taken();
int cur_step = 0;
int delay_time = 0;
void setup() {
// Initialize Serial For Debug Output
Serial.begin(9600);
// Initialize Pill Ejection Module
spinner_servo.attach(SPINNER_PIN);
spinner_servo.write(0);
ejector_servo.attach(EJECTOR_PIN);
ejector_servo.write(REST_ANGLE);
// Initialize Display Module
display_serial.begin(9600);
#ifdef VOICE_MODULE
// Initialize Voice Module
voice_serial.begin(9600);
voice_serial.write(buf_voice_vol, 5);
#endif
// display loading screen
ui_page(0);
// Initialize Bridge
Bridge.begin();
// display splash screen
ui_page(1);
}
// the loop routine runs over and over again forever:
void loop() {
display_serial.listen();
while (display_serial.available() > 0) {
char in_char = display_serial.read();
Serial.write(in_char);
switch (in_char) { // check signal from which screen
case '1':
// display user info screen
ui_page(2);
break;
case '2':
// display next schedule screen
ui_page(3);
break;
#ifdef VIDEO_TAKING_ONLY
case '3': // should be triggered by timer
wait_next_schedule();
break;
#endif
case '4':
if (cur_step == 0) {
eject_pill(0);
eject_pill(1);
eject_pill(2);
ui_page(5);
} else if (cur_step == 1) {
eject_pill(0);
eject_pill(2);
ui_page(6);
} else {
eject_pill(1);
ui_page(7);
}
spinner_servo.write(0);
break;
case '5':
push_taken();
cur_step = 1;
ui_page(3);
break;
case '6':
push_taken();
cur_step = 2;
ui_page(3);
break;
case '7':
push_taken();
cur_step = 0;
ui_page(3);
break;
default:
break;
}
while (display_serial.available() > 0) {
char c = display_serial.read();
}
}
}
void ui_page(byte page) {
switch (page) {
case 0:
buf_page_cmd[5] = '0';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
break;
case 1:
buf_page_cmd[5] = '1';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
break;
case 2:
buf_page_cmd[5] = '2';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
//TODO: get and display user info from cloud server
//get_user_info();
#ifdef VOICE_MODULE
voice_serial.write(buf_play[0], 6);
#endif
break;
case 3:
buf_page_cmd[5] = '3';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
buf_set_str_cmd[0] = 's';
buf_set_str_cmd[1] = 'c';
buf_set_str_cmd[2] = 'h';
#ifdef DEMO_ONLY
if (cur_step == 0) {
buf_set_str_cmd[14] = '1';
buf_set_str_cmd[15] = '4';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
} else if (cur_step == 1) {
buf_set_str_cmd[14] = '2';
buf_set_str_cmd[15] = '0';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
} else {
buf_set_str_cmd[14] = '0';
buf_set_str_cmd[15] = '8';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
}
#else
//TODO: get and display time from cloud schedule
//get_next_schedule();
//buf_set_str_cmd[14] =
//buf_set_str_cmd[15] =
//buf_set_str_cmd[17] =
//buf_set_str_cmd[18] =
//display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
#endif
#ifdef VOICE_MODULE
voice_serial.write(buf_play[1], 6);
#endif
#ifdef VIDEO_TAKING_ONLY
// do nothing
#else
wait_next_schedule();
#endif
break;
case 4:
buf_page_cmd[5] = '4';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
buf_set_str_cmd[0] = 't';
buf_set_str_cmd[1] = 'i';
buf_set_str_cmd[2] = 'm';
#ifdef DEMO_ONLY
if (cur_step == 0) {
buf_set_str_cmd[14] = '1';
buf_set_str_cmd[15] = '4';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
} else if (cur_step == 1) {
buf_set_str_cmd[14] = '2';
buf_set_str_cmd[15] = '0';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
} else {
buf_set_str_cmd[14] = '0';
buf_set_str_cmd[15] = '8';
display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
}
#else
//TODO: display time from cloud schedule
//buf_set_str_cmd[14] =
//buf_set_str_cmd[15] =
//buf_set_str_cmd[17] =
//buf_set_str_cmd[18] =
//display_serial.write(buf_set_str_cmd, sizeof(buf_set_str_cmd));
#endif
#ifdef VOICE_MODULE
voice_serial.write(buf_play[2], 6);
#endif
break;
case 5:
buf_page_cmd[5] = '5';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
#ifdef VOICE_MODULE
voice_serial.write(buf_play[3], 6);
#endif
break;
case 6:
buf_page_cmd[5] = '6';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
#ifdef VOICE_MODULE
voice_serial.write(buf_play[3], 6);
#endif
break;
case 7:
buf_page_cmd[5] = '7';
display_serial.write(buf_page_cmd, sizeof(buf_page_cmd));
#ifdef VOICE_MODULE
voice_serial.write(buf_play[3], 6);
#endif
break;
default:
break;
}
}
void wait_next_schedule() {
//TODO: use timer
#ifdef DEMO_ONLY
Serial.println("wait 10 seconds");
delay(10000);
#else
Serial.print("wait ");
Serial.print(delay_time);
Serial.println(" milliseconds");
delay(delay_time);
#endif
ui_page(4);
}
void eject_pill(byte pill_slot) {
spinner_servo.write(pill_slot_angle[pill_slot]);
delay(1000);
ejector_servo.write(EJECT_ANGLE);
delay(1000);
ejector_servo.write(REST_ANGLE);
delay(1000);
}
void get_user_info() {
// Launch "curl" command and get Arduino ascii art logo from the network
// curl is command line program for transferring data using different internet protocols
Process p; // Create a process and call it "p"
p.begin("curl"); // Process that launch the "curl" command
// Add the URL parameter to "curl"
p.addParameter("--data");
p.addParameter("id=pill_machine");
p.addParameter(USER_INFO_URL);
p.run(); // Run the process and wait for its termination
// A process output can be read with the stream methods
while (p.available()>0) {
char c = p.read();
Serial.print(c);
//TODO: save user info to variable
}
// Ensure the last bit of data is sent.
Serial.flush();
}
void get_next_schedule() {
// Launch "curl" command and get Arduino ascii art logo from the network
// curl is command line program for transferring data using different internet protocols
Process p; // Create a process and call it "p"
p.begin("curl"); // Process that launch the "curl" command
// Add the URL parameter to "curl"
p.addParameter("--data");
p.addParameter("id=pill_machine");
p.addParameter(NEXT_SCHEDULE_URL);
p.run(); // Run the process and wait for its termination
// A process output can be read with the stream methods
while (p.available()>0) {
char c = p.read();
Serial.print(c);
//TODO: save next schedule to variable
//delay_time =
}
// Ensure the last bit of data is sent.
Serial.flush();
}
void push_taken() {
// Launch "curl" command and get Arduino ascii art logo from the network
// curl is command line program for transferring data using different internet protocols
Process p; // Create a process and call it "p"
p.begin("curl"); // Process that launch the "curl" command
// Add the URL parameter to "curl"
p.addParameter("--data");
p.addParameter("id=pill_machine");
p.addParameter(TAKEN_URL);
p.run(); // Run the process and wait for its termination
// A process output can be read with the stream methods
while (p.available()>0) {
char c = p.read();
Serial.print(c);
}
// Ensure the last bit of data is sent.
Serial.flush();
}
Comments