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");
}
Smart Automated Pill Dispenser
Moderators: kgudger, bfinio, MadelineB, Moderators
-
sidshootphotos
- Posts: 3
- Joined: Tue Sep 30, 2025 5:18 pm
- Occupation: Student
Smart Automated Pill Dispenser
- Attachments
-
- Screenshot 2025-09-28 at 3.01.13 PM.png (628.08 KiB) Viewed 2378 times
-
bfinio
- Expert
- Posts: 964
- Joined: Mon Aug 12, 2013 2:41 pm
- Occupation: Lead Staff Scientist, Science Buddies
- Project Question: Expert
- Project Due Date: n/a
- Project Status: Not applicable
Re: Smart Automated Pill Dispenser
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
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
-
sidshootphotos
- Posts: 3
- Joined: Tue Sep 30, 2025 5:18 pm
- Occupation: Student
Re: Smart Automated Pill Dispenser
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.
-
bfinio
- Expert
- Posts: 964
- Joined: Mon Aug 12, 2013 2:41 pm
- Occupation: Lead Staff Scientist, Science Buddies
- Project Question: Expert
- Project Due Date: n/a
- Project Status: Not applicable
Re: Smart Automated Pill Dispenser
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.
// 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.
-
sidshootphotos
- Posts: 3
- Joined: Tue Sep 30, 2025 5:18 pm
- Occupation: Student
Re: Smart Automated Pill Dispenser
I did most liekly uncomment that line but doesnt change anything
-
bfinio
- Expert
- Posts: 964
- Joined: Mon Aug 12, 2013 2:41 pm
- Occupation: Lead Staff Scientist, Science Buddies
- Project Question: Expert
- Project Due Date: n/a
- Project Status: Not applicable
Re: Smart Automated Pill Dispenser
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.

