#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;
}
}
Comments
Please log in or sign up to comment.