SYSTEM_THREAD(ENABLED);
// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
/* Function prototypes -------------------------------------------------------*/
#define BLYNK_PRINT Serial
#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // this is the 'maximum' pulse length count (out of 4096)
char auth[] = "QnbZ5V15eDpxUK_o9cjSouJ_BdwNsG3r";
int previousState = 0;
int lastSync;
int ONE_DAY_MILLIS = (24 * 60 * 60 * 1000);
int alarmTime = 0;
int currentTimeInSecs ;
int LEDday[] = {0,A1, A2, A3, A4, A5, A6, A7};//Lights
int lid[] = {0,0,0,0,0,0,0,0};//lid status
// int lidDay[]= {0,D1, D2, D3, D4, D5, D6, D7};//switches
int pFull[] = {0,0,0,0,0,0,0,0}; //Pill status
int speaker = D2;//Speaker pin
int button = D3;
int takePills =0;
int openLid = 0;
int lidSpeed = 2;
char LEDdayNow;
int tTaken = 0;
int localTimeZone =0;
int clientAC =0;
int clientNumber =0;
int care1AC = 0;
int care1Number =0;
int care2AC = 0;
int care2Number =0;
int refillBox = 0;
int buttonStatus = 0;
int pillsRemaining;
int reminderTime = 15; //time in minutes
int careWarningTime = 15;
int reminderNum = 1;
int creminderNum = 1;
int pillMin = 0;
int audibleAlerts = 0;
int today = 0;
int second = 0;
int minute = 0;
int hour = 0;
int day = 0 ;
int refillToday = 0; //prevents box from alerting on the day a refill was done
int i = 0; //counter
int vFID;
int vEID;
int vUID;
char SMS[32]; //for sneding text info
char SMScare1[32];
char SMScare2[32];
char message[60];
char boxName[12];
char deviceName[20];
String deviceEN;
String deviceN;
String dayOfWeek[8];
//BLYNK Functions
BLYNK_WRITE(V0) {
String deviceEN = param[0].asStr(); //From Blynk
strcpy (deviceName, deviceEN);
EEPROM.put(300, deviceName) ;
Serial.print("Name Set to: ");
Serial.println(deviceName);
}
BLYNK_WRITE(V1) {
TimeInputParam t(param);
int startTimeInSecs = param[0].asInt();
localTimeZone = t.getTZ_Offset()/3600;
alarmTime = startTimeInSecs;
EEPROM.put(0, alarmTime);
EEPROM.put(10, localTimeZone);
}
BLYNK_WRITE(V2) {
clientAC = param[0].asInt();
EEPROM.put(20,clientAC);
}
BLYNK_WRITE(V3) {
clientNumber = param[0].asInt();
EEPROM.put(30,clientNumber);
}
BLYNK_WRITE(V4) {
care1AC = param[0].asInt();
EEPROM.put(40,care1AC);
}
BLYNK_WRITE(V5) {
care1Number = param[0].asInt();
EEPROM.put(50,care1Number);
}
BLYNK_WRITE(V6) {
care2AC = param[0].asInt();
EEPROM.put(60,care2AC);
}
BLYNK_WRITE(V7) {
care2Number = param[0].asInt();
EEPROM.put(70,care2Number);
}
BLYNK_WRITE(V9){
pillMin = param[0].asInt();
EEPROM.put(90,pillMin);
}
BLYNK_WRITE(V10) {
refillBox = param[0].asInt();
Serial.println("BLYNK STATUS - Refilling SET ");
Serial.println(refillBox);
if (refillBox == 1) {
if (currentTimeInSecs >= alarmTime) {
refillToday = 1;
}
Blynk.virtualWrite(V8, 0);
EEPROM.put(110,1);
EEPROM.put(120,1);
EEPROM.put(130,1);
EEPROM.put(140,1);
EEPROM.put(150,1);
EEPROM.put(160,1);
EEPROM.put(170,1);
int k=0;
while (k<7) {
k++;
pFull[k]=1;
vFID = (20 + k);
vEID = (30 + k);
vUID = (40 + k);
Blynk.virtualWrite(vFID, 255);
Blynk.virtualWrite(vEID, 0);
Blynk.virtualWrite(vUID, 0);
// Open all Lids
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
pwm.setPWM(k, 0, pulselen);
delay(lidSpeed);
}
}
}
if (refillBox == 0) {
int k=0;
while (k<7) {
k++;
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(k, 0, pulselen);
delay(lidSpeed);
}
}
}
}
BLYNK_WRITE(V11) {
audibleAlerts = param[0].asInt();
EEPROM.put(80,audibleAlerts);
}
BLYNK_WRITE(V12) {
reminderTime = param[0].asInt();
EEPROM.put(200,reminderTime);
}
BLYNK_WRITE(V13) {
careWarningTime = param[0].asInt();
EEPROM.put(210,careWarningTime);
}
BLYNK_WRITE(V14){
int k = param[0].asInt();
if (k == 1){
activate();
}
}
BLYNK_WRITE(V51) {
int k = param[0].asInt();
if (k == 0) {
i=1;
closeRefill();
}
if (k == 1) {
i=1;
writeRefill();
}
}
BLYNK_WRITE(V52) {
int k = param[0].asInt();
if (k == 1) {
i=2;
writeRefill();
}
if (k == 0) {
i=2;
closeRefill();
}
}
BLYNK_WRITE(V53) {
int k = param[0].asInt();
if (k == 1) {
i=3;
writeRefill();
}
if (k == 0) {
i=3;
closeRefill();
}
}
BLYNK_WRITE(V54) {
int k = param[0].asInt();
if (k == 1) {
i=4;
writeRefill();
}
if (k == 0) {
i=4;
closeRefill();
}
}
BLYNK_WRITE(V55) {
int k = param[0].asInt();
if (k == 1) {
i=5;
writeRefill();
}
if (k == 0) {
i=5;
closeRefill();
}
}
BLYNK_WRITE(V56) {
int k = param[0].asInt();
if (k == 1) {
i=6;
writeRefill();
}
if (k == 0) {
i=6;
closeRefill();
}
}
BLYNK_WRITE(V57) {
int k = param[0].asInt();
if (k == 1) {
i=7;
writeRefill();
}
if (k == 0) {
i=7;
closeRefill();
}
}
void writeRefill() {
//open the lid
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
pwm.setPWM(i, 0, pulselen);
delay(lidSpeed);
}
int l = ( 100 + (i *10));
EEPROM.put(l,1);
pillsRemaining = pillsRemaining + 1;
pFull[i] = 1;
vFID = (20 + i);
vEID = (30 + i);
vUID = (40 + i);
Blynk.virtualWrite(vFID, 255);
Blynk.virtualWrite(vEID, 0);
Blynk.virtualWrite(vUID, 0);
if (currentTimeInSecs >= alarmTime && i == today) {
refillToday = 1;
}
}
void closeRefill() {
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(i, 0, pulselen);
delay(lidSpeed);
}
}
void setup() {
// Retrive NV Variables
EEPROM.get(0, alarmTime);
EEPROM.get(110, pFull[1]);
EEPROM.get(120, pFull[2]);
EEPROM.get(130, pFull[3]);
EEPROM.get(140, pFull[4]);
EEPROM.get(150, pFull[5]);
EEPROM.get(160, pFull[6]);
EEPROM.get(170, pFull[7]);
EEPROM.get(10, localTimeZone);
EEPROM.get(20, clientAC);
EEPROM.get(30, clientNumber);
EEPROM.get(40, care1AC);
EEPROM.get(50, care1Number);
EEPROM.get(60, care2AC);
EEPROM.get(70, care2Number);
EEPROM.get(80, audibleAlerts);
EEPROM.get(90, pillMin);
EEPROM.get(200, reminderTime);
EEPROM.get(210, careWarningTime);
const int STRING_BUF_SIZE = 20;
char stringBuf[STRING_BUF_SIZE];
EEPROM.get(300, stringBuf);
strcpy (deviceName, stringBuf);
// LED Lights
pinMode(LEDday[1], OUTPUT);
pinMode(LEDday[2], OUTPUT);
pinMode(LEDday[3], OUTPUT);
pinMode(LEDday[4], OUTPUT);
pinMode(LEDday[5], OUTPUT);
pinMode(LEDday[6], OUTPUT);
pinMode(LEDday[7], OUTPUT);
pinMode(speaker,OUTPUT);
pinMode(button, INPUT_PULLDOWN);
attachInterrupt(button, buttonPressed, RISING);
// Debug console
Serial.begin(9600);
tone(speaker,1000,500);
i=0;
while (i<7) {
i++;
digitalWrite(LEDday[i], HIGH);
}
delay(3000); // Allow board to settle
i=0;
while (i<7) {
i++;
digitalWrite(LEDday[i], LOW);
}
// start and setup servos
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
//Close all Lids
i=0;
while (i<7) {
i++;
pwm.setPWM(i, 0, SERVOMIN);
delay(100);
}
Blynk.begin(auth);
pillsRemaining = 0; //calculate pills remaing for initial value
i = 0;
while (i<7) {
i++;
if (pFull[i] > 0) {
pillsRemaining = pillsRemaining + 1;
}
// write inital status to app
i=0;
while (i<7) {
i++;
vFID = (20 + i);
vEID = (30 + i);
vUID = (40 + i);
if (pFull[i] == 1) {
Blynk.virtualWrite(vFID, 255);
Blynk.virtualWrite(vEID, 0);
Blynk.virtualWrite(vUID, 0);
}
if (pFull[i] == 0){
Blynk.virtualWrite(vFID, 0);
Blynk.virtualWrite(vEID, 255);
Blynk.virtualWrite(vUID, 0);
}
if (pFull[i] == -1){
Blynk.virtualWrite(vFID, 0);
Blynk.virtualWrite(vEID, 0);
Blynk.virtualWrite(vUID, 255);
}
}
}
today = Time.weekday();
day = today;
Serial.println("Setup Complete");
}
/* This function loops forever --------------------------------------------*/
void loop()
{
Blynk.run();
updateTime();
updateLog();
// once a day - housekeeping - pills are Low
if (day != today) {
day = today;
refillToday = 0; // clear the flag if box refilled yesterday
}
delay(5000);
//Check if time for a pill
if (pFull[today] != 0 && currentTimeInSecs >= alarmTime && refillToday == 0) {
pillTime();
}
// update BLYNK status display
Blynk.virtualWrite(15, ((alarmTime - currentTimeInSecs) /60));
// check if button pressed
if (buttonStatus ==1) {
activate();
}
//check if reminder needed
if (takePills == 1) {
if (currentTimeInSecs >= (alarmTime + (reminderTime * 60 * reminderNum))) {
pillReminder();
}
if (currentTimeInSecs >= (alarmTime + (careWarningTime * 60 * creminderNum))) {
careWarning();
}
}
}
void pillsLow() {
strcpy(boxName, deviceName);
sprintf (message,"PILLMINDER: %s Pillbox is running low",boxName);
clientSMS();
careSMS();// do the SMS thing
Blynk.virtualWrite(V8, 255);
}
void buttonPressed() {
buttonStatus = 1;
}
void activate() {
Serial.println("Button Pushed");
if (takePills != 1) {
failMusic();
}
if (takePills == 1) {
//open the lid "today"
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
pwm.setPWM(today, 0, pulselen);
delay(lidSpeed);
}
wellDone();
}
buttonStatus = 0;
}
void pillReminder() {
sprintf (message,"PILLMINDER: Reminder # %i. Take your pills now.",reminderNum);
clientSMS();
reminderNum = (reminderNum + 1);
alarmMusic();
}
void careWarning() {
int m = ((currentTimeInSecs - alarmTime) * 0.01667);
strcpy(boxName, deviceName);
sprintf (message,"PILLMINDER: %s pills are now %i minutes overdue.",boxName, m);
careSMS();
creminderNum = (creminderNum + 1);
alarmMusic();
}
void pillTime() {
takePills = 1;
Serial.println("Alarm ON ");
digitalWrite(LEDday[today], HIGH);
alarmMusic();
}
void wellDone() {
digitalWrite(LEDday[1], LOW);
digitalWrite(LEDday[2], LOW);
digitalWrite(LEDday[3], LOW);
digitalWrite(LEDday[4], LOW);
digitalWrite(LEDday[5], LOW);
digitalWrite(LEDday[6], LOW);
digitalWrite(LEDday[7], LOW); // just to be sure all LEDs off
pFull[today]= 0;
vFID = (20 + today); //update app
vEID = (30 + today);
vUID = (40 + today);
Blynk.virtualWrite(vFID, 0);
Blynk.virtualWrite(vEID, 255);
Blynk.virtualWrite(vUID, 0);
int l = 100 + (today * 10);
EEPROM.put(l,0); //save the state
takePills = 0;
reminderNum = 1;
creminderNum = 1;
tTaken = currentTimeInSecs;
int takeDeltaMin = (tTaken-alarmTime)/60;
sprintf (message,"PILLMINDER: %s pills taken %i mintutes after alarm.",deviceName, takeDeltaMin);
clientSMS();
careSMS();
successMusic();
pillCount();
}
void clientSMS () {
sprintf(SMS, "Twilio-SMS/+1%i%i",clientAC,clientNumber);
Serial.printlnf("SMS: %s", message );
//Particle.publish(SMS,message,PRIVATE);
}
void careSMS () {
sprintf(SMS, "Twilio-SMS/+1%i%i",care1AC,care1Number);
// Particle.publish(SMS,message,PRIVATE);
sprintf(SMS, "Twilio-SMS/+1%i%i",care2AC,care2Number);
// Particle.publish(SMS,message,PRIVATE);
Serial.printlnf("SMS: %s", message );
}
void pillCount(){
pillsRemaining = 0;
i=0;
while (i<7) {
i++;
if (pFull[i] > 0) {
pillsRemaining = pillsRemaining + 1;
}
}
if (pillsRemaining <= pillMin) {
pillsLow();
}
else {
Blynk.virtualWrite(V8, 0);
}
}
void successMusic() {
tone(speaker,500,500);
delay(500);
tone(speaker,2000,500);
}
void failMusic() {
tone(speaker,5000,200);
delay(400);
tone(speaker,5000,200);
delay(400);
tone(speaker,5000,200);
}
void alarmMusic() {
if (audibleAlerts == 1) {
tone(speaker,1200,200);
}
}
void updateTime() {
if (millis() - lastSync > ONE_DAY_MILLIS) { //daily cloud time sync
Particle.syncTime();
lastSync = millis();
}
Time.zone(localTimeZone);
second = Time.second();
minute = Time.minute();
hour = Time.hour();
currentTimeInSecs = second + (minute*60) + (hour*60*60);
today = Time.weekday();
}
void updateLog() {
Serial.println();
Serial.printlnf("Current Alive Seconds= %i", millis()/1000);
Serial.printlnf("Name: %s ", deviceName);
Serial.printlnf("Client Number: %i-%i", clientAC, clientNumber );
Serial.printlnf("Care1 Number: %i-%i", care1AC, care1Number );
Serial.printlnf("Care2 Number: %i-%i", care2AC, care2Number );
Serial.printlnf("Local Time Zone = %i Day = %i ",localTimeZone, today);
Serial.printlnf("Alarm Time Hour = %i Alarm Time Seconds = %i ",alarmTime/3600, alarmTime );
Serial.printlnf("Current Hour = %i Current Time In Seconds = %i",Time.hour(), currentTimeInSecs);
Serial.printlnf("Client Reminder Time =%i minutes Reminder Count =%i--Care Reminder Time =%i minutes - Reminder Count = %i",reminderTime, reminderNum, careWarningTime, creminderNum);
Serial.printlnf("Take Pills= %i Pills Remaining = %i ",takePills, pillsRemaining);
Serial.printlnf("Pill Bin Status: Sun= %i Mon= %i Tues= %i Wed= %i Thur= %i Fri= %i Sat= %i", pFull[1], pFull[2], pFull[3], pFull[4], pFull[5], pFull[6], pFull[7]);
}
Comments