Project Overview
This project creates a medicine reminder system that helps elderly or forgetful individuals remember to take their medication. A PIR sensor detects when someone approaches the medicine cabinet, and if it’s time for medication, the system plays a reminder message and lights up LEDs.
Difficulty: Intermediate
Estimated time: 2-3 hours
Estimated cost: $30-40
How It Works
A PIR sensor at the medicine cabinet detects when someone approaches. The system checks the current time against a schedule of medication times. If it’s within the reminder window, it plays a recorded message (via DFPlayer Mini) and lights up LEDs to remind the person to take their medicine. If the person opens the cabinet (detected by a reed switch), the reminder is marked as taken and the alarm stops.
Materials Needed
- ESP32 or Arduino Uno (1)
- HC-SR501 PIR sensor (1)
- DS3231 Real-Time Clock (1)
- DFPlayer Mini MP3 module (1)
- MicroSD card (with reminder audio files)
- Small speaker (3W, 4-8Ω)
- LEDs (red, green, blue – for status indication)
- Resistors (220Ω for LEDs)
- Reed switch (for cabinet door detection)
- Magnet
- Jumper wires
- Power supply (5V 2A)
Circuit Diagram
Connection Table
| Component |
Pin |
ESP32 Pin |
PIR Sensor |
VCC
| 5V
| PIR Sensor |
GND
| GND
| PIR Sensor |
OUT
| GPIO 4
| DS3231 RTC |
VCC
| 3.3V
| DS3231 RTC |
GND
| GND
| DS3231 RTC |
SDA
| GPIO 21
| DS3231 RTC |
SCL
| GPIO 22
| DFPlayer Mini |
VCC
| 5V
| DFPlayer Mini |
GND
| GND
| DFPlayer Mini |
TX
| GPIO 16
| DFPlayer Mini |
RX
| GPIO 17
| Red LED |
Anode
| GPIO 5 (220Ω)
| Green LED |
Anode
| GPIO 18 (220Ω)
| Blue LED |
Anode
| GPIO 19 (220Ω)
| Reed Switch |
One side
| GPIO 23 (pull-up)
| Reed Switch |
Other side
| GND
|
表
Preparing Audio Files
- Record or download reminder messages (e.g., “It’s time to take your morning medication”).
- Save as MP3 files (44.1kHz, 128kbps).
- Name files as “001.mp3”, “002.mp3”, etc.
- Place on microSD card in folder “01”.
Arduino Code
// Medicine Reminder System
#include <Wire.h>
#include <RTClib.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
RTC_DS3231 rtc;
SoftwareSerial mySoftwareSerial(16, 17); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
const int pirPin = 4;
const int redLedPin = 5;
const int greenLedPin = 18;
const int blueLedPin = 19;
const int doorSensorPin = 23;
// Medication schedule (hour, minute, message file)
struct MedTime {
int hour;
int minute;
int messageFile;
bool taken;
};
MedTime medTimes[] = {
{8, 0, 1, false}, // 8:00 AM
{12, 0, 2, false}, // 12:00 PM
{18, 0, 3, false} // 6:00 PM
};
const int numMedTimes = 3;
bool reminderActive = false;
int activeMedIndex = -1;
unsigned long lastMotionTime = 0;
const unsigned long reminderDuration = 60000; // 1 minute
void setup() {
Serial.begin(115200);
pinMode(pirPin, INPUT);
pinMode(redLedPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
pinMode(blueLedPin, OUTPUT);
pinMode(doorSensorPin, INPUT_PULLUP);
digitalWrite(redLedPin, LOW);
digitalWrite(greenLedPin, LOW);
digitalWrite(blueLedPin, LOW);
if (!rtc.begin()) {
Serial.println("RTC not found");
while (1);
}
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) {
Serial.println("DFPlayer error");
while (1);
}
myDFPlayer.volume(20);
Serial.println("Medicine Reminder Ready");
delay(60000); // PIR warm-up
}
void checkScheduledTimes() {
DateTime now = rtc.now();
int currentHour = now.hour();
int currentMinute = now.minute();
for (int i = 0; i < numMedTimes; i++) {
if (!medTimes[i].taken &&
currentHour == medTimes[i].hour &&
currentMinute >= medTimes[i].minute &&
currentMinute < medTimes[i].minute + 30) {
if (!reminderActive) {
reminderActive = true;
activeMedIndex = i;
Serial.printf("Reminder active for medication %d\n", i);
// Blue LED for reminder
digitalWrite(blueLedPin, HIGH);
}
return;
}
}
}
void playReminder() {
if (activeMedIndex >= 0) {
myDFPlayer.play(medTimes[activeMedIndex].messageFile);
Serial.printf("Playing reminder %d\n", medTimes[activeMedIndex].messageFile);
}
}
void markTaken() {
if (activeMedIndex >= 0) {
medTimes[activeMedIndex].taken = true;
reminderActive = false;
activeMedIndex = -1;
digitalWrite(blueLedPin, LOW);
digitalWrite(greenLedPin, HIGH);
myDFPlayer.play(4); // "Thank you" message
delay(2000);
digitalWrite(greenLedPin, LOW);
Serial.println("Medication taken");
}
}
void loop() {
checkScheduledTimes();
bool motion = digitalRead(pirPin) == HIGH;
bool doorOpen = digitalRead(doorSensorPin) == LOW;
if (reminderActive && motion) {
if (millis() - lastMotionTime > 10000) { // Play every 10 seconds
playReminder();
lastMotionTime = millis();
}
digitalWrite(redLedPin, HIGH);
} else {
digitalWrite(redLedPin, LOW);
}
if (doorOpen && reminderActive) {
markTaken();
}
if (reminderActive && (millis() - lastMotionTime > reminderDuration)) {
digitalWrite(redLedPin, LOW);
digitalWrite(blueLedPin, LOW);
}
delay(100);
}
Enhanced Version with LCD Display
Add an LCD to show next medication time:
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void updateDisplay() {
lcd.setCursor(0, 0);
lcd.print("Next med: ");
for (int i = 0; i < numMedTimes; i++) {
if (!medTimes[i].taken) {
lcd.print(medTimes[i].hour);
lcd.print(":");
if (medTimes[i].minute < 10) lcd.print("0");
lcd.print(medTimes[i].minute);
break;
}
}
lcd.setCursor(0, 1);
if (reminderActive) {
lcd.print("Take med NOW!");
} else {
lcd.print("System ready");
}
}
Installation Steps
- Prepare audio files: Record reminder messages and place on SD card.
- Set RTC time: Set the DS3231 clock to current time (use example sketch).
- Assemble circuit: Build on breadboard and test.
- Mount PIR sensor: Place near medicine cabinet, angled to detect approach.
- Install reed switch: Mount on cabinet door and frame.
- Place speaker: Position where message can be heard clearly.
- Power up: Connect to USB power or battery.
- Test: Approach cabinet at medication time, verify reminder plays.
Project Extensions
- Remote notifications: Add Wi-Fi to send alerts to caregivers if medication not taken.
- Pill dispenser: Add servo to dispense pills when door is opened.
- Voice recognition: Add voice confirmation for taking medication.
- Data logging: Track adherence and send reports to family.
- Multiple users: Add RFID to identify which person is taking medication.
Troubleshooting
- No sound: Check DFPlayer wiring. Verify SD card formatting and file names.
- RTC not keeping time: Replace CR2032 battery on DS3231.
- PIR not detecting: Adjust sensitivity. Ensure sensor has clear view.
- False reminders: Check RTC time accuracy. Verify schedule times.
Conclusion
This medicine reminder system helps ensure medications are taken on time. With motion detection and audio reminders, it's especially helpful for elderly individuals or anyone who struggles with remembering medications.