#include "HX711.h"
#include <LiquidCrystal.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>
#define calibration_factor -7050.0 // This value is obtained using the SparkFun_HX711_Calibration sketch
#define LOADCELL_DOUT_PIN 3
#define LOADCELL_SCK_PIN 2
HX711 scale;
const float EMPTY_THRESHOLD = 5.0; // Adjust this value based on the weight of an empty container (in grams)
int pushVal = 0;
int val;
int val2;
int addr = 0;
RTC_DS3231 rtc;
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; // LCD pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define getWellsoon 0
#define HELP_SCREEN 1
#define TIME_SCREEN 2
int pushpressed = 0;
const int ledPin = LED_BUILTIN; // Buzzer and LED pin
int ledState = LOW;
int Signal = 0;
int buzz = 13;
int push1state, push2state, push3state, stopinState = 0;
int push1Flag, push2Flag, Push3Flag = false; // Push button flags
int push1pin = 9;
int push2pin = 8;
int push3pin = 7;
int stopPin = A0;
int screens = 0; // Screen to show
int maxScreen = 2; // Screen count
bool isScreenChanged = true;
long previousMillis = 0;
long interval = 500; // Buzzing interval
unsigned long currentMillis;
long previousMillisLCD = 0; // For LCD screen update
long intervalLCD = 2000; // Screen cycling interval
unsigned long currentMillisLCD;
// Set Reminder Change Time
int buzz8amHH = 8; // HH - hours
int buzz8amMM = 00; // MM - Minute
int buzz8amSS = 00; // SS - Seconds
int buzz2pmHH = 14; // HH - hours
int buzz2pmMM = 00; // MM - Minute
int buzz2pmSS = 00; // SS - Seconds
int buzz8pmHH = 20; // HH - hours
int buzz8pmMM = 00; // MM - Minute
int buzz8pmSS = 00; // SS - Seconds
int nowHr, nowMin, nowSec; // To show current mm, hh, ss
void gwsMessage() { // Print get well soon message
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Stay Healthy :)"); // Give some cheers
lcd.setCursor(0, 1);
lcd.print("Get Well Soon :)"); // Wish
}
void helpScreen() { // Function to display 1st screen on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Press Buttons");
lcd.setCursor(0, 1);
lcd.print("for Reminder...!");
}
void timeScreen() { // Function to display Date and time on LCD screen
DateTime now = rtc.now(); // Take RTC time and print on display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Time:");
lcd.setCursor(6, 0);
lcd.print(nowHr = now.hour(), DEC);
lcd.print(":");
lcd.print(nowMin = now.minute(), DEC);
lcd.print(":");
lcd.print(nowSec = now.second(), DEC);
lcd.setCursor(0, 1);
lcd.print("Date: ");
lcd.print(now.day(), DEC);
lcd.print("/");
lcd.print(now.month(), DEC);
lcd.print("/");
lcd.print(now.year(), DEC);
}
void setup() {
Serial.begin(9600); // Start serial debugging
if (!rtc.begin()) { // Check if RTC is connected
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
}
rtc.adjust(DateTime(2019, 1, 10, 7, 59, 30)); // Manual time set
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Welcome To"); // Print a message at startup
lcd.setCursor(0, 1);
lcd.print("SMART PILL");
delay(2000); // Display welcome message for 2 seconds
lcd.clear();
pinMode(push1pin, INPUT); // Define push button pins type
pinMode(push2pin, INPUT);
pinMode(push3pin, INPUT);
pinMode(stopPin, INPUT);
pinMode(ledPin, OUTPUT);
delay(200);
Serial.println(EEPROM.read(addr));
val2 = EEPROM.read(addr); // Read previously saved value of push button to start from where it was left previously
switch (val2) {
case 1:
Serial.println("Set for 1/day");
push1state = 1;
push2state = 0;
push3state = 0;
pushVal = 1;
break;
case 2:
Serial.println("Set for 2/day");
push1state = 0;
push2state = 1;
push3state = 0;
pushVal = 2;
break;
case 3:
Serial.println("Set for 3/day");
push1state = 0;
push2state = 0;
push3state = 1;
pushVal = 3;
break;
}
// Load Cell Setup
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(calibration_factor); // This value is obtained by using the SparkFun_HX711_Calibration sketch
scale.tare(); // Assuming there is no weight on the scale at startup, reset the scale to 0
Serial.println("Readings:");
}
void loop() {
// Load Cell Reading
float weight = scale.get_units() * 453.592; // Convert lbs to grams (1 lb = 453.592 grams)
Serial.print("Reading: ");
Serial.print(weight, 1); // Display weight in grams
Serial.println(" g");
if (weight < EMPTY_THRESHOLD) {
Serial.println("Warning: The container is empty or nearly empty!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Container Empty!");
delay(2000);
lcd.clear();
}
// Medicine Reminder Logic
push1(); // Call to set once/day
push2(); // Call to set twice/day
push3(); // Call to set thrice/day
if (pushVal == 1) { // If push button 1 pressed then remind at 8am
at8am(); // Function to start buzzing at 8am
}
else if (pushVal == 2) { // If push button 2 pressed then remind at 8am and 8pm
at8am();
at8pm(); // Function to start buzzing at 8pm
}
else if (pushVal == 3) { // If push button 3 pressed then remind at 8am, 2pm, and 8pm
at8am();
at2pm(); // Function to start buzzing at 2pm
at8pm();
}
currentMillisLCD = millis(); // Start millis for LCD screen switching at defined interval of time
push1state = digitalRead(push1pin); // Start reading all push button pins
push2state = digitalRead(push2pin);
push3state = digitalRead(push3pin);
stopinState = digitalRead(stopPin);
stopPins(); // Call to stop buzzing
changeScreen(); // Screen cycle function
delay(1000); // Delay to prevent spamming the Serial monitor
}
void push1() { // Function to set reminder once/day
if (push1state == 1) {
push1state = 0;
push2state = 0;
push3state = 0;
EEPROM.write(addr, 1);
Serial.print("Push1 Written: "); Serial.println(EEPROM.read(addr)); // For debugging
pushVal = 1; // Save the state of push button-1
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Once/day !");
delay(1200);
lcd.clear();
}
}
void push2() { // Function to set reminder twice/day
if (push2state == 1) {
push2state = 0;
push1state = 0;
push3state = 0;
EEPROM.write(addr, 2);
Serial.print("Push2 Written: "); Serial.println(EEPROM.read(addr));
pushVal = 2;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Twice/day !");
delay(1200);
lcd.clear();
}
}
void push3() { // Function to set reminder thrice/day
if (push3state == 1) {
push3state = 0;
push1state = 0;
push2state = 0;
EEPROM.write(addr, 3);
Serial.print("Push3 Written: "); Serial.println(EEPROM.read(addr));
pushVal = 3;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reminder set ");
lcd.setCursor(0, 1);
lcd.print("for Thrice/day !");
delay(1200);
lcd.clear();
}
}
void stopPins() { // Function to stop buzzing when user pushes stop push button
if (stopinState == 1) {
pushpressed = 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Take Medicine ");
lcd.setCursor(0, 1);
lcd.print("with Warm Water");
delay(1200);
lcd.clear();
}
}
void startBuzz() { // Function to start buzzing when time reaches the defined interval
if (pushpressed == 0) {
Serial.println("pushpressed is false in blink");
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the last time you blinked the LED
Serial.println("Start Buzzing");
if (ledState == LOW) { // If the LED is off, turn it on and vice-versa:
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
} else if (pushpressed == 1) {
Serial.println("pushpressed is true");
ledState = LOW;
digitalWrite(ledPin, ledState);
}
}
void at8am() { // Function to start buzzing at 8am
DateTime now = rtc.now();
if (int(now.hour()) >= buzz8amHH) {
if (int(now.minute()) >= buzz8amMM) {
if (int(now.second()) > buzz8amSS) {
startBuzz();
}
}
}
}
void at2pm() { // Function to start buzzing at 2pm
DateTime now = rtc.now();
if (int(now.hour()) >= buzz2pmHH) {
if (int(now.minute()) >= buzz2pmMM) {
if (int(now.second()) > buzz2pmSS) {
startBuzz();
}
}
}
}
void at8pm() { // Function to start buzzing at 8pm
DateTime now = rtc.now();
if (int(now.hour()) >= buzz8pmHH) {
if (int(now.minute()) >= buzz8pmMM) {
if (int(now.second()) > buzz8pmSS) {
startBuzz();
}
}
}
}
void changeScreen() { // Function for Screen Cycling
if (currentMillisLCD - previousMillisLCD > intervalLCD) { // Save the last time you changed the display
previousMillisLCD = currentMillisLCD;
screens++;
if (screens > maxScreen) {
screens = 0; // All screens over -> start from 1st
}
isScreenChanged = true;
}
if (isScreenChanged) { // Only update the screen if the screen is changed
isScreenChanged = false; // Reset for next iteration
switch (screens) {
case getWellsoon:
gwsMessage(); // Get well soon message
break;
case HELP_SCREEN:
helpScreen(); // Instruction screen
break;
case TIME_SCREEN:
timeScreen(); // To print date and time
break;
default:
break;
}
}
}