Maurizio Manetti
Published © MIT

Arduino Advent Candle

A simple Advent Candle controlled by Arduino (various light effects and also plays "Jingle Bells" upon button press)

IntermediateFull instructions providedOver 1 day5,038
Arduino Advent Candle

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
White Plastic Tube
×1
3 mm LED: Red
3 mm LED: Red
×25
RTC DS3231
×1
Yellow LED Flickering Candle
×1
Rechargeable Li-ion Battery Pack 1200mAh
×1
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Slide Switch
Slide Switch
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Round wood box
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Driller
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

F57xxeBrDg5d90Vs7DXO.png

Code

Xmas Advent Candle

Arduino
#include "Wire.h"
#include "pitches.h"
#define DS3231_I2C_ADDRESS 0x68

const int LOOPS = 7; // number of loops
const int BUTTON = 13; // pin number of button
const int SPEAKER = 14; // pin number of speaker

int cathods[] = {2,4,7,8,12}; // pins of cathodes
int anodes[] = {3,5,6,9,10}; // pins of anodes
int current_led = 1; // current ON led
int current_loop = 0; // current loop

int delays[] = {1,20,50,100,150,100,50,20};

unsigned long previousMillis = 0; 
unsigned long previousLoop = 0; 

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}

// switch on a single led (switch off all other)
void led_on(int index) {
  int myAnode = (index - 1) / 5; 
  int myCathode = (index - 1) % 5;  
  
  for (int i = 0; i < 5; i++) {
     digitalWrite(anodes[i], LOW);
     digitalWrite(cathods[i], HIGH);
  }

  digitalWrite(anodes[myAnode], HIGH);
  digitalWrite(cathods[myCathode], LOW);

}

// get day of month from RTC clock
byte get_day() {
  byte second;
  byte minute;
  byte hour;
  byte dayOfWeek;
  byte dayOfMonth;
  byte month;
  byte year;
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  second = bcdToDec(Wire.read() & 0x7f);
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  return dayOfMonth;
}

// play music switching on leds until the one of today
void play(byte today) {
 
  // jingle bells  
  
  int melody[] = {
    NOTE_E3, NOTE_E3, NOTE_E3, 
    NOTE_E3, NOTE_E3, NOTE_E3, 
    NOTE_E3, NOTE_G3, NOTE_C3, NOTE_D3, 
    NOTE_E3,
    NOTE_F3, NOTE_F3, NOTE_F3, NOTE_F3,
    NOTE_F3, NOTE_E3, NOTE_E3, NOTE_E3, NOTE_E3,
    NOTE_E3, NOTE_D3, NOTE_D3, NOTE_E3,
    NOTE_D3, NOTE_G3,
    NOTE_E3, NOTE_E3, NOTE_E3, 
    NOTE_E3, NOTE_E3, NOTE_E3, 
    NOTE_E3, NOTE_G3, NOTE_C3, NOTE_D3, 
    NOTE_E3,
    NOTE_F3, NOTE_F3, NOTE_F3, NOTE_F3, 
    NOTE_F3, NOTE_E3, NOTE_E3, NOTE_E3, NOTE_E3,
    NOTE_G3, NOTE_G3, NOTE_F3, NOTE_D3,
    NOTE_C3
  };

  // note durations: 4 = half note 2 = quarter note, 1 = eighth note, etc.:
  int noteDurations[] = {2,2,4, 2,2,4, 2,2,3,1, 8, 2,2,3,1, 2,2,2,1,1, 2,2,2,2, 4,4, 2,2,4, 2,2,4, 2,2,3,1, 8, 2,2,2,2, 2,2,2,1,1, 2,2,2,2, 8};

  // play music
  for (int thisNote = 0; thisNote < 51; thisNote++) {

    led_on((thisNote % today)+1);
    
    // every quarter lasts 250 ms    
    int noteDuration = noteDurations[thisNote]*125;
    tone(SPEAKER, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(SPEAKER);

    // stop music on button press
    int sensorVal = digitalRead(BUTTON);
    if (sensorVal == LOW) {
      Serial.println("Button pressed, stopping music");
      delay(300);
      // stop the tone playing:
      noTone(SPEAKER);
      break;
    }
    
  }
  
}

// setup
void setup() {
  Wire.begin();
  Serial.begin(9600);
  pinMode(BUTTON, INPUT_PULLUP);
  // switch off all
  for (int i = 0; i < 5; i++) {
    pinMode(cathods[i], OUTPUT);
    pinMode(anodes[i], OUTPUT);
    digitalWrite(cathods[i], LOW);  
    digitalWrite(anodes[i], LOW);  
  }
}


// loop
void loop() {
  
  byte today = get_day();
  unsigned long currentMillis = millis();
  int loop_interval = 3000;

  int myDelay = delays[current_loop];
  
  if (myDelay == 1) {
    loop_interval = 5000;
  } else {
    loop_interval = myDelay * today * 5;
  }
    
  // play song on press button
  int sensorVal = digitalRead(BUTTON);
  if (sensorVal == LOW) {
    Serial.println("Button pressed, starting music");
    play(today);
  }
  
  // different led in the loop (stay "myDelay" on)
  if (currentMillis - previousMillis >= myDelay) {
    led_on(current_led);
    current_led ++;
    if (current_led > today) {
      // start over after today
      current_led = 1;
    }
    previousMillis = currentMillis;
  }

  // different loops 
  if (currentMillis - previousLoop >= loop_interval) {
    current_loop ++;
    if (current_loop > LOOPS) {
      // start over from first loop
      current_loop = 0;
    }
    previousLoop = currentMillis;
  }
  
   
}

Credits

Maurizio Manetti

Maurizio Manetti

0 projects • 4 followers
Web developer since late '90s. Moved from Florence, Italy to Hamburg, Germany in 2014. Proud dad of two wonderful kids.

Comments