Project tutorial
Arduino Advent Candle

Arduino Advent Candle © MIT

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

  • 1,884 views
  • 3 comments
  • 11 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
White Plastic Tube
×1
Lite on ltl 1che
3 mm LED: Red
×25
RTC DS3231
×1
Yellow LED Flickering Candle
×1
Rechargeable Li-ion Battery Pack 1200mAh
×1
10722 01
Speaker: 0.25W, 8 ohms
×1
Omron b3f 1000 image 75px
SparkFun Pushbutton switch 12mm
×1
E switch eg1218 image 75px
Slide Switch
×1
11026 02
Jumper wires (generic)
×1
Round wood box
×1

Necessary tools and machines

Hy gluegun
Hot glue gun (generic)
Driller
09507 01
Soldering iron (generic)

Apps and online services

About this project

I was always used to have an Advent Candle during December, but this year we were not able to buy one in time. So I decided to build an electronic one and control it with Arduino. Indeed it was a lot of work and it was ready only by the 10th of December but, well, next year it will still be working and I can program new effects!

I am controlling 25 LEDs with 10 GPIO pins, so I needed to build a matrix of LEDs and make some multiplexing.

At the beginning, I was thinking to use a Raspberry Pi but I switched soon to Arduino since such a board has been lying in a drawer for a long time. The code is pretty naive at the moment. I hope to have a better understanding of how to manage this kind of "parallel" stuff in Arduino in the future: listening for a button press while controlling a LED animation can be pretty tricky when you don't have threads. Do you? I took inspiration from https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

Candle on 14th of December

Acknowledgements

This is actually my first "real" hardware project, involving more than 70 solder joints. I thought I would have never managed such a thing and now I am pretty excited to have accomplished it. I need to thank my uncle Stefano for inspiring, Edo for remembering I had an Arduino and letting me discover Hackster.io, Daniele D.S. for providing the main hardware component, my wife, Julia, for bearing with me while I was playing with this stuff and my nephew Richard for encouragement with his enthusiasm and helping with soldering.

Code

Xmas Advent CandleArduino
#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;
  }
  
   
}

Schematics

F57xxeBrDg5d90Vs7DXO.png
F57xxebrdg5d90vs7dxo

Comments

Similar projects you might like

Integrated Solar ChargeController, Inverter, PowerBank, Lamp

Project tutorial by Shahariar

  • 7,733 views
  • 16 comments
  • 30 respects

Programmable Pocket Power Supply with OLED Display

Project tutorial by Shahariar

  • 6,325 views
  • 6 comments
  • 28 respects

Scent-terrific Smart Candle

Project tutorial by Darian Johnson

  • 2,894 views
  • 0 comments
  • 32 respects

PIR Automated Intelligent Zebra Crossing

Project showcase by Adersh B

  • 2,266 views
  • 1 comment
  • 5 respects

The "Tennis Ball" Garage Stop Light

Project tutorial by Team Stuart Mace

  • 9,656 views
  • 2 comments
  • 36 respects

Wireless weather station (Arduino + ESP8266 + Thingspeak)

Project tutorial by Alin-Constantin Paun

  • 8,873 views
  • 2 comments
  • 12 respects
Add projectSign up / Login