PIR Sensor for Medicine Reminder: Never Miss a Dose

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

Preparing Audio Files

  1. Record or download reminder messages (e.g., “It’s time to take your morning medication”).
  2. Save as MP3 files (44.1kHz, 128kbps).
  3. Name files as “001.mp3”, “002.mp3”, etc.
  4. 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

  1. Prepare audio files: Record reminder messages and place on SD card.
  2. Set RTC time: Set the DS3231 clock to current time (use example sketch).
  3. Assemble circuit: Build on breadboard and test.
  4. Mount PIR sensor: Place near medicine cabinet, angled to detect approach.
  5. Install reed switch: Mount on cabinet door and frame.
  6. Place speaker: Position where message can be heard clearly.
  7. Power up: Connect to USB power or battery.
  8. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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