Arduino/Projects

Physical computing projects and web applications that solve real-world problems.

Baby Feeding & Nap Timer

A two-button tracking device that monitors elapsed time since baby's last feeding and nap using a real-time clock and LCD display. Data persists through power loss via EEPROM storage.

Key Features

  • Dual countdown timers on 16×2 LCD
  • Real-time clock for power outages
  • Fast-forward by holding buttons
  • Non-volatile memory
  • Two pushbuttons interface
Hardware Components
  • Arduino Uno
  • DS1302 RTC module with CR2032 battery
  • 16×2 LCD (HD44780)
  • 10kΩ potentiometer
  • 2 pushbuttons
  • Breadboard
Wiring Details

LCD: RS→Pin 12, E→Pin 11, D4-7→Pins 10,9,8,13

Buttons: Feed→Pin 2, Nap→Pin 3

RTC: CLK→Pin 6, DAT→Pin 5, RST→Pin 4

Operation

Display shows Feed: HH:MM:SS / Nap: HH:MM:SS

Quick press: Resets timer

Hold 0.5s: Fast-forward mode

View Complete User Manual

Basic Operation

The screen shows two timers counting upward representing time since last feeding and time since last nap:

Feed: HH:MM:SS
Nap:  HH:MM:SS

Resetting a Timer

  • Feeding Button (D2): Press once to reset feed timer to 00:00:00. Hold 0.5+ seconds for fast-forward mode.
  • Nap Button (D3): Press once to reset nap timer to 00:00:00. Hold 0.5+ seconds for fast-forward mode.

Fast-Forward Mode

If you forgot to press the button earlier, the device can catch up:

  • Holding a button for 0.5 seconds activates fast-forward mode
  • Timer advances by 1 minute every 0.2 seconds (display updates in real-time)
  • Release the button to stop fast-forward

Power Loss Behavior

The DS1302 RTC stores time using its own battery. The Arduino saves timestamps to EEPROM. You can unplug the device, move it, and plug it back in - both timers resume correctly based on real elapsed time. No need to set the clock again.

Troubleshooting

  • LCD shows blocks or very faint: Adjust the 10kΩ potentiometer
  • Timers reset after power loss: CR2032 battery missing/dead, check RTC wiring
  • Buttons don't register: Check GND connection, shorten jumper wires
  • RTC time wrong: Upload sketch with rtc.time() setter, then remove it
View Complete Arduino Code
#include <LiquidCrystal.h>
#include <DS1302.h>
#include <EEPROM.h>

// LCD pins: RS, E, D4, D5, D6, D7
LiquidCrystal lcd(12, 11, 10, 9, 8, 13);

// DS1302 pins: CE, IO, SCLK
DS1302 rtc(4, 5, 6);

// Button pins
const int feedingButtonPin = 2;
const int napButtonPin = 3;

// States
bool lastFeedingState = HIGH;
bool lastNapState = HIGH;

// Times (unix timestamps)
unsigned long feedingStart = 0;
unsigned long napStart = 0;

// Hold tracking
unsigned long feedPressedTime = 0;
unsigned long napPressedTime = 0;

bool feedingHeld = false;
bool napHeld = false;

unsigned long lastFeedAddTime = 0;
unsigned long lastNapAddTime = 0;

// Constants
const unsigned long holdThreshold = 500;       // ms
const unsigned long incrementInterval = 200;   // ms
const unsigned long oneMinute = 60;             // seconds

// EEPROM addresses (4 bytes each)
const int EEPROM_FEEDING_ADDR = 0;
const int EEPROM_NAP_ADDR = 4;

void setup() {
  pinMode(feedingButtonPin, INPUT_PULLUP);
  pinMode(napButtonPin, INPUT_PULLUP);

  lcd.begin(16, 2);
  Serial.begin(9600);

  rtc.halt(false);
  rtc.writeProtect(false);

  // Read stored timestamps
  EEPROM.get(EEPROM_FEEDING_ADDR, feedingStart);
  EEPROM.get(EEPROM_NAP_ADDR, napStart);

  // Validate EEPROM values; if invalid, initialize to current RTC time
  Time nowTime = rtc.time();
  unsigned long now = nowTime.unixtime();

  if (feedingStart == 0xFFFFFFFF || feedingStart == 0) feedingStart = now;
  if (napStart == 0xFFFFFFFF || napStart == 0) napStart = now;
}

void loop() {
  Time nowTime = rtc.time();
  unsigned long currentTime = nowTime.unixtime();

  // Feeding button logic
  bool currentFeedingState = digitalRead(feedingButtonPin);
  if (lastFeedingState == HIGH && currentFeedingState == LOW) {
    feedPressedTime = millis();
    feedingHeld = false;
  } else if (lastFeedingState == LOW && currentFeedingState == LOW) {
    if (!feedingHeld && (millis() - feedPressedTime >= holdThreshold)) {
      feedingHeld = true;
      lastFeedAddTime = millis();
    }
    if (feedingHeld && (millis() - lastFeedAddTime >= incrementInterval)) {
      feedingStart -= oneMinute;
      lastFeedAddTime = millis();
      EEPROM.put(EEPROM_FEEDING_ADDR, feedingStart);
    }
  } else if (lastFeedingState == LOW && currentFeedingState == HIGH) {
    if (!feedingHeld) {
      feedingStart = currentTime;
      EEPROM.put(EEPROM_FEEDING_ADDR, feedingStart);
    }
  }
  lastFeedingState = currentFeedingState;

  // Nap button logic
  bool currentNapState = digitalRead(napButtonPin);
  if (lastNapState == HIGH && currentNapState == LOW) {
    napPressedTime = millis();
    napHeld = false;
  } else if (lastNapState == LOW && currentNapState == LOW) {
    if (!napHeld && (millis() - napPressedTime >= holdThreshold)) {
      napHeld = true;
      lastNapAddTime = millis();
    }
    if (napHeld && (millis() - lastNapAddTime >= incrementInterval)) {
      napStart -= oneMinute;
      lastNapAddTime = millis();
      EEPROM.put(EEPROM_NAP_ADDR, napStart);
    }
  } else if (lastNapState == LOW && currentNapState == HIGH) {
    if (!napHeld) {
      napStart = currentTime;
      EEPROM.put(EEPROM_NAP_ADDR, napStart);
    }
  }
  lastNapState = currentNapState;

  // Calculate elapsed times
  unsigned long feedElapsed = currentTime - feedingStart;
  unsigned long napElapsed = currentTime - napStart;

  // Display on LCD
  displayElapsedTime(0, "Feed: ", feedElapsed);
  displayElapsedTime(1, "Nap:  ", napElapsed);

  delay(50);
}

void displayElapsedTime(int row, const char* label, unsigned long elapsedSeconds) {
  unsigned long hours = elapsedSeconds / 3600;
  unsigned long minutes = (elapsedSeconds % 3600) / 60;
  unsigned long seconds = elapsedSeconds % 60;

  lcd.setCursor(0, row);
  lcd.print(label);

  if (hours < 10) lcd.print('0');
  lcd.print(hours);
  lcd.print(':');

  if (minutes < 10) lcd.print('0');
  lcd.print(minutes);
  lcd.print(':');

  if (seconds < 10) lcd.print('0');
  lcd.print(seconds);
  lcd.print("  ");
}

Toddler Sleep Clock

A custom microcontroller-based alarm clock using color cues to help young children understand sleep schedules with color transitions.

Key Features

  • Morning (Red→Amber→Green) and Evening (Green→Amber→Red) progressions
  • Daytime power saving
  • Smooth 10-second LED transitions
  • Backup battery
  • Three-button configuration menu
Hardware Components
  • Arduino Uno
  • DS1302 RTC with CR2032
  • 16x2 LCD (HD44780)
  • RGB LED (common cathode KY-016)
  • 3 push buttons
  • 4x 220Ω resistors
  • 10kΩ pot
Wiring Details

Buttons: D2, D3, D4 to ground

RGB LED: R→D9, G→D10, B→D8

RTC: Clock→D7, Data→D6, Reset→D5

LCD: RS→D12, Enable→D11, Data→A0-A3

Software & Setup

Libraries: LiquidCrystal, Rtc by Makuna, EEPROM

Setup: Hold SELECT 1s (LED turns blue), use UP/DOWN to adjust, SELECT to confirm

Configuration Options
  • Current time
  • Wake amber/green times
  • Bedtime amber/red times
  • Optional nap times
View Complete User Manual

Normal Operation

  • Top Line: Displays current time
  • Bottom Line: Displays next event (Wake or Bedtime)
  • LED: Changes color automatically based on schedule

Entering Setup Mode

  • Press and hold SELECT for 1 second
  • LED will turn Blue
  • Use UP/DOWN to adjust the flashing number
  • Press SELECT to confirm and move to next setting

Setup Sequence

  1. Set Time: Adjust current Hour → Minute
  2. Set Wake (R→Y): When light turns Amber (Wake up soon)
  3. Set Wake (Y→G): When light turns Green (Okay to get up)
  4. Set Bed (G→Y): When light turns Amber (Wind down/Evening)
  5. Set Bed (Y→R): When light turns Red (Bedtime)

Power Saving

Lights automatically fade to OFF 2 hours after morning "Green" time. Lights fade back ON 2 hours before evening "Amber" time.

Nap Feature

Setup:

  • Screen 1: "Total Naps?" → Choose 0, 1, or 2
  • If 1 nap selected: Set "Nap 1 Start" and "Nap 1 End"
  • If 2 naps selected: Set both nap start/end times

Nap Colors:

  • 15 mins before nap: Light turns Amber
  • Nap Time: Light turns Red
  • Nap End: Light turns Green (stays green for 1+ hour)
View Complete Arduino Code
// Toddler Sleep Clock - Complete Arduino Code
// This is a placeholder for the complete Toddler Sleep Clock code
// The actual implementation includes RTC management, LCD display control,
// RGB LED color transitions, EEPROM settings storage, and button input handling

Read-a-Thon Tracking System

Overview

I developed a custom web application to track and visualize reading progress for MMFS Middle School's annual Read-a-Thon fundraiser. The system provides real-time data visualization and community engagement features that encourage participation and celebrate student achievement.

The Challenge

Our school needed a way to track reading progress across the middle school, display results publicly to motivate students, and connect the fundraiser to charitable causes. Traditional paper-based tracking lacked the immediacy and visual impact to sustain engagement throughout the event.

Technical Implementation

The system uses a streamlined tech stack focused on accessibility and ease of use:

Data Collection:

Google Forms provides a simple, mobile-friendly interface for students to submit reading time or pages completed immediately after finishing a book.

Data Processing:

Responses feed into a Google Sheets backend that aggregates individual submissions into class and school-wide totals.

Visualization:

A custom web interface displays:

  • Thermometer-style progress gauge showing total reading against the school goal
  • Real-time feed of recent submissions with student names and books read
  • Information about supported charitable organizations

Impact

The tracker transformed our Read-a-Thon from an administrative task into a community event. Students check progress throughout the day, teachers display it in classrooms, and the real-time updates create friendly competition and collective goal pursuit. The public display of charitable causes connects student effort directly to community impact.

Technical Skills Demonstrated
  • Frontend development (HTML, CSS, JavaScript)
  • Google Apps Script integration
  • API integration with Google Sheets
  • Real-time data visualization
  • Responsive design for multiple devices
  • User experience design for student audiences

Educational Approach

These projects demonstrate practical applications of technology to solve real-world problems, from physical computing with microcontrollers to web-based data visualization systems that engage entire communities.