Page 1 of 1

Smart Automated Pill Dispenser

Posted: Tue Sep 30, 2025 5:23 pm
by sidshootphotos
Hello! I am doing science fair currently and my project is a smart automated pill dispenser. Attached is my circuit board from tinkercad. So I am using an Arduino UNO R3 and I have an LCD That will display live RTC Clock, but it shows wrong time and date. It also makes me change the date and everytime I reset, it starts from 12 am. This is the only thing I need to fix and also I have to add specific timings for the beeping noise. Please help me ASAP. I will send the code. Code is attached below this. Please fix the code and rewrite it so I can add it and my project will be complete and i can be ready to order the specific parts I need! This is in tinkercad by the way and C++

Code starts:

#include <Wire.h>
#include <RTClib.h>
#include <Servo.h>
#include <LiquidCrystal.h>

RTC_DS3231 rtc; // Use DS3231 RTC
Servo servo;

const int servoPin = 6;
const int buttonPin = 9;
const int ledPin = 7;
const int buzzerPin = 8;

// LCD Pins: RS, EN, D4, D5, D6, D7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int angle = 0;
const int angleIncrement = 45;
const int maxAngle = 135; // For 4 compartments: 0°, 45°, 90°, 135°
const int movementDelay = 15; // decreased delay for smoother movement

int lastDispensedMinute = -1;

bool dispensing = false;
unsigned long dispenseStartTime = 0;
int dispenseTargetAngle = 0;

bool alerting = false;
unsigned long alertStartTime = 0;
const unsigned long alertDuration = 3000; // 3 seconds alert duration

void setup() {
Serial.begin(9600);

Wire.begin();
rtc.begin();

// Uncomment to set the RTC once, then comment it back:
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

pinMode(buttonPin, INPUT_PULLUP); // Active LOW button
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);

digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);

servo.attach(servoPin);
servo.write(angle);

lcd.begin(16, 2);
lcd.print("Pill Dispenser");
delay(2000);
lcd.clear();
lcd.print("By Sid and Izaan!");
delay(2000);
lcd.clear();
}

void loop() {
DateTime now = rtc.now();

int hour = now.hour();
int minute = now.minute();
int second = now.second();
int day = now.day();
int month = now.month();
int year = now.year();

// Update LCD display with live date and time
displayDateTime(day, month, year, hour, minute, second);

// Check if it's time to dispense (once per new minute)
if (second == 0 && minute != lastDispensedMinute && !dispensing && !alerting) {
Serial.println("Starting dispense");
dispensing = true;
dispenseTargetAngle = angle + angleIncrement;
if (dispenseTargetAngle > maxAngle) dispenseTargetAngle = 0;
}

// Handle dispensing movement non-blocking
if (dispensing) {
if (angle < dispenseTargetAngle) {
angle++;
servo.write(angle);
delay(movementDelay);
} else if (angle > dispenseTargetAngle) {
angle--;
servo.write(angle);
delay(movementDelay);
} else {
// Movement finished
dispensing = false;
lastDispensedMinute = minute;
startAlert();
}
}

// Handle alert non-blocking
if (alerting) {
unsigned long currentMillis = millis();
if (currentMillis - alertStartTime < alertDuration) {
// Blink LED and buzzer
if ((currentMillis / 300) % 2 == 0) {
digitalWrite(ledPin, HIGH);
digitalWrite(buzzerPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
}

// Show alert message
lcd.setCursor(0, 0);
lcd.print("Take medicine! ");
lcd.setCursor(0, 1);
lcd.print("Press button... ");

// Check for button press (active LOW)
if (digitalRead(buttonPin) == LOW) {
alerting = false;
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
lcd.clear();
Serial.println("Alert acknowledged by button press");
delay(300); // simple debounce
}
} else {
// Alert time expired without button press
alerting = false;
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
lcd.clear();
Serial.println("Alert time expired");
}
}
}

// New Live Clock Function
void displayDateTime(int day, int month, int year, int hour, int minute, int second) {
char line1[17];
char line2[17];

// Format: MM/DD/YYYY
snprintf(line1, sizeof(line1), "%02d/%02d/%04d", month, day, year);

// Format: HH:MM:SS
snprintf(line2, sizeof(line2), "%02d:%02d:%02d", hour, minute, second);

lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
}

// Start the alert sequence
void startAlert() {
alerting = true;
alertStartTime = millis();
Serial.println("Starting alert");
}

Re: Smart Automated Pill Dispenser

Posted: Wed Oct 01, 2025 8:53 am
by bfinio
Hello,

To be clear, are you also running this project on a physical Arduino, or are you only doing it in Tinkercad? Certain Arduino libraries do not work perfectly in Tinkercad - I have not tried an RTC library but would not be surprised if it behaves differently than it would on a physical Arduino.

Thanks,

Ben

Re: Smart Automated Pill Dispenser

Posted: Wed Oct 01, 2025 6:19 pm
by sidshootphotos
Hi! Thank you so much for replying! Well I haven't bought the parts and currently this is an online arduino and not a physical. I am doing this in tinkercad now then I would buy the parts.

Re: Smart Automated Pill Dispenser

Posted: Thu Oct 02, 2025 5:12 am
by bfinio
Ok - looking at your code in more detail, I see this:

// Uncomment to set the RTC once, then comment it back:
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

Have you tried uncommenting that line before running the Tinkercad simulation?

If that still doesn't work, I would wait until you test this on your physical Arduino. I'm not sure how Tinkercad handles time - there is a chance the simulation just starts over at midnight every time you hit the "run" button instead of using the real-world time.

Re: Smart Automated Pill Dispenser

Posted: Sat Oct 04, 2025 9:08 am
by sidshootphotos
I did most liekly uncomment that line but doesnt change anything

Re: Smart Automated Pill Dispenser

Posted: Mon Oct 06, 2025 7:12 am
by bfinio
Ok - my guess is that you need to run this on a physical Arduino because Tinkercad is starting over at 12AM every time you restart the simulation.