Build a DIY CD Tray Timer with Arduino: Step-by-Step Guide
This project shows how to build a simple CD tray timer that automatically opens or closes a CD/DVD drive tray after a user-set delay. It’s useful for demonstrations, kiosk resets, timed media ejection, or just as a fun hardware-and-code exercise. The design uses an Arduino Nano (or Uno), a small servo motor or a linear actuator, a pushbutton to start/reset the timer, an optional potentiometer to set the delay, and a few basic components.
Parts and tools
- Arduino Nano or Uno (or any Arduino-compatible board)
- Micro servo (e.g., SG90) or a small 5–6V linear actuator (servo recommended for simplicity)
- N-channel MOSFET or small relay (if you use a drive-control mechanism that requires higher current) — not needed for servo approach
- Pushbutton (momentary)
- 10 kΩ resistor (for button pull-down/pull-up)
- 10 kΩ potentiometer (optional — to adjust timer)
- Breadboard and jumper wires
- 5V power supply (Arduino USB or separate 5V source if using many servos)
- Small mechanical linkage (e.g., 3D-printed bracket, zip-tie, or plexiglass arm) to connect servo horn to CD tray
- Hot glue, screws, double-sided tape for mounting
- Basic tools: screwdriver, pliers, wire stripper
How it works (overview)
A servo is mounted to the CD drive bezel and connected by a small arm to physically push the tray open/closed. The Arduino reads the start button and optional potentiometer (sets delay). When the button is pressed, the Arduino starts a countdown; after the delay it moves the servo to the “eject” or “close” position. The button can cancel or restart the timer.
Safety and notes
- Do not force the CD tray; ensure your linkage moves smoothly and does not stress the drive motor.
- If using a laptop internal drive, be careful opening the case; prefer external USB drives for ease.
- Servos draw current—power from Arduino USB is usually fine for one small servo; use a separate 5V supply if needed.
Wiring diagram (servo approach)
- Servo signal → Arduino digital pin D9 (PWM)
- Servo Vcc → 5V (Arduino or external 5V)
- Servo GND → Arduino GND (common ground if external supply used)
- Button → Arduino digital pin D2; other button leg → GND; use internal pull-up or external 10 kΩ to 5V
- Potentiometer (optional) → middle pin to A0, left to 5V, right to GND
Arduino sketch
// CD Tray Timer - Servo version
#include
Servo trayServo;
const int buttonPin = 2;
const int potPin = A0;// optional delay control
const int servoPin = 9;
int buttonState = HIGH;
int lastButton = HIGH;
unsigned long debounce = 50;
unsigned long lastDebounceTime = 0;
bool timerRunning = false;
unsigned long startTime = 0;
unsigned long delayMs = 10000; // default 10s
// servo angles - adjust to suit your linkage
const int closedPos = 90; // tray closed resting position
const int openPos = 0; // tray open position
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
trayServo.attach(servoPin);
trayServo.write(closedPos);
Serial.begin(9600);
}
void loop() {
int reading = digitalRead(buttonPin);
if (reading != lastButton) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounce) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) { // button pressed (active LOW)
// start or cancel timer
if (!timerRunning) {
// read pot for delay if present
int potVal = analogRead(potPin);
// map 0-1023 to 1-120 seconds
delayMs = map(potVal, 0, 1023, 1000, 120000);
startTime = millis();
timerRunning = true;
Serial.print(“Timer started: “);
Serial.print(delayMs);
Serial.println(” ms”);
} else {
timerRunning = false;
trayServo.write(closedPos); // ensure closed
Serial.println(“Timer cancelled”);
}
}
}
}
lastButton = reading;
if (timerRunning) {
unsigned long elapsed = millis() - startTime;
if (elapsed >= delayMs) {
// toggle tray
trayServo.write(openPos);
delay(1000); // allow movement
// after open, reset state (or close after set time if desired)
timerRunning = false;
Serial.println(“Tray opened”);
}
}
}
Mechanical mounting
- Identify a safe location on the drive bezel where a small linkage can push the tray without obstructing eject mechanism.
- Attach the servo to the drive’s side or to the drive bay frame using screws or double-sided tape.
- Connect servo horn with a small stiff arm (plastic or metal) to the tray face so movement of the horn pushes/pulls the tray. Aim for ~15–25 mm travel — adjust servo endpoints in code as needed.
- Test movement manually before powering the drive: gently move the tray by hand and confirm servo positions won’t bind.
Testing and tuning
- Power Arduino and servo, ensure servo moves to closedPos on start.
- Press button to start timer; observe that the servo moves to openPos after the set delay.
- If tray requires two-stage motion, add intermediate positions and small delays in code.
- Adjust closedPos/openPos values to match physical linkage limits.
Variations and improvements
- Use a second button to choose open vs. close action.
- Add an LCD/OLED to display remaining time.
- Replace servo with a small geared DC motor + limit switches for smoother force transfer on larger trays.
- Add Wi-Fi (ESP8266/ESP32) and a web UI to set timer remotely.
- Use infrared remote or serial commands for control.
Troubleshooting
- Servo jitter: ensure stable 5V supply and common ground.
- Tray doesn’t move: check linkage alignment and servo torque.
- Drive motor stalls: increase servo travel carefully or use gentler mechanical advantage.
If you want, I can provide a 3D-printable bracket design, a version using a relay/DC motor, or an ESP32 web-control sketch next.