Project showcase
Not another digital alarm clock?

Not another digital alarm clock? © GPL3+

Yes it is, but this one has Bluetooth and other great features!

  • 5,479 views
  • 8 comments
  • 17 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
4966285
Solder Wire, Lead Free

About this project

The Story

This is my third project since this pandemic arrived and it was something my Dad made in 1993 which gave me the idea. Back then, he was a little depressed, so he made a full size grandfathers clock, which now stands proudly in our hallway. He made it as a representation of time passing during his low period and this got me thinking.

I have some friends in the USA who I usually visit once or twice a year, but not since March 2020. So after making my first project (the Digital Cribbage Board), I wondered if I could use the same chassis and turn it into a modern version of my father’s grandfather clock (generally speaking).

This is the result.

Alarm Clock and Kitchen Timer Clock

As I started the project, the scope expanded and expanded, to the following list of features.

Main Hardware

  • Arduino Nano Every
  • Bespoke PCB including two power systems
  • Five 8x8 LED panels
  • Bluetooth module
  • DS3231 real time clock
  • Adafruit Sound FX board
  • Mini speaker

Software Features

  • 12/24 hour setting
  • Alarm clock
  • Sleep mode
  • MP3 sound board for alarms
  • Six colour settings for main display
  • Bluetooth module to display received character strings
  • Welcome message
  • Master reset function
  • Loss of settings protection by saving settings into EEPROM
  • Kitchen timer option with two timers

As I stated earlier, the digital alarm clock and the digital kitchen timer are both built on nearly the same chassis and design of my earlier Digital Cribbage Board, but with some modifications.

Please see it here - Digital Cribbage Board

I have kept the power systems, USB interface and LED 8x8arrays the same, but needed to enlarge the main PCB, to make way for a new real time clock as well as a Bluetooth module.

After a little investigation, I settled on the DS3231, as this is more accurate than its baby sibling the DS1307.

For the Bluetooth interface, I installed a HC10 Bluetooth module. This allows for a connection from either an Android or Apple device, so the user can send character strings to the clock, which are then displayed on the clock as scrolling text messages.

Bluetooth Demonstration

The chassis is longer, as I needed to house five 8x8 LED array panels instead of four, along with a great little device from Adafruit called a “Sound FX” board and a small 8ohm speaker. The sound board and speaker allow for either the alarm clock sounds or kitchen sounds to be triggered by a basic pin trigger from the Arduino.

Kitchen Timer Demonstration

Code

Digital Alarm ClockArduino
Main sketch for the Digital Alarm Clock
/*
 Name:    Swear_Box.ino - NeoPixel Clock using a DS3231
 Created: 7/14/2020 2:23:26 PM

 Original code kindly referenced from:	Tiziano Bianchettin

 Serioulsy hacked about by:				Christopher Cooper in 2020
*/

// Libraries.

#include <avr/pgmspace.h>			// Special memory library.
#include <DS3231.h>                 // RTC library.
#include <Wire.h>                   // I2C library.
#include <EEPROM.h> 				// EEPROM library.
#include <SoftwareSerial.h>			// Software serial library.

// Declare real time clock object.

DS3231 rtc;

// Configure software serial pins.

SoftwareSerial s1Serial(20, 21);	// RX, TX, Bluetooth module.

// Adafruit NeoPixel libraries.

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

// Configure NeoPixel.

#define PIXEL_COUNT 320				// Total number of NeoPixels.
#define PIXEL_PIN   6				// Digital IO pin connected to the NeoPixels.

// Declare NeoPixel matrix object.

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, 5, 1, 6,

	NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
	NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
	NEO_RGB + NEO_KHZ800);

// Argument 1 = Number of rows in NeoPixel array.
// Argument 2 = Number of columns in NeoPixel array.
// Argument 3 = Number of horizontal tiles.
// Argument 4 = Number of vertical tiles.
// Argument 5 = Arduino pin number.
// From adafruit help for tiled arrays matrixWidth, matrixHeight, tilesX, tilesY, pin, matrixType, ledType);

// Configure NeoPixel colours and variables.

const uint16_t colors[8] = {
  matrix.Color(255, 0, 0),
  matrix.Color(0, 255, 0),
  matrix.Color(255, 255, 0),
  matrix.Color(0, 0, 255),
  matrix.Color(255, 0, 255),
  matrix.Color(0, 255, 255),
  matrix.Color(255, 255, 255)
};

char colorArray[9][8] = { "Green", "Red", "Yellow", "Blue", "Teal", "Purple", "White" };

byte pixelPerChar = 6;					// Width of standard font characters is 8X6 pixels.
int x = matrix.width();					// Width of the NeoPixel display.
byte speedSet = 10;						// Scrolling text speed.
byte tempSpeedSet = 50;					// Used for reversing speed variable.
byte colorSet = 6;						// Color selection.
byte brightnessSet = 5;					// Display brightness.

// Configure buttons & pins.

const byte intPinAlarmOneSet = 4;		// Buttom to set alarm one.
const byte intPinMenu = 5;				// Button SET MENU' using Interupt.
const byte intPinScrollingDate = 8;		// Button to call display Date Function using Interupt.
const byte intPinWhite = 9;				// Button to call blue random strings using Interupt.
const byte intPinAlarmOneSleep = 10;	// Sleep, cancel alarm one.      

const byte bPlus = 2;					// Button +
const byte bMinus = 3;					// Button -
const byte vPlus = A0;					// Volume +
const byte vMinus = 13;					// Volume -

const byte Mahnamahna = A1;				// The Muppets Mahnamaha pin trigger.
const byte GSTQ = A2;					// God save the queen anthem pin trgger.
const byte SSB = A3;					// Star spangled banner anthem pin trigger.

// Global variables.

boolean debug = false;					// Debugging flag for serial output.

byte volumeSet = 25;					// Volume setting.
bool musicScroll = false;				// Music menu scroll prevention.
char musicArray[4][25] = { "God Save the Queen", "Star Spangled Banner" , "The Muppets - Mahnamahna" };	// Music track array.
byte musicSet = 0;						// Music setting menu.
byte musicPlay = A1;					// Music setting menu.

int  buttonDelay = 200;

bool h12;                               // 12 / 24 hour clock flag from RTC.
bool PM;                                // AM / PM clock flag from RTC.
bool set1224 = false;                   // 12 / 24 hour clock flag.
bool Century = false;                   // Century flag from RTC.
bool resetRTC = false;					// Reset RTC flag.
bool resetWelcome = false;				// Reset welcome message flag.

byte alarmBits;							// Alarm variables.
bool alarmDy;
bool alarmH12;
bool alarmPm;

bool alarmOneState = false;				// Sleep variables.
bool setSleepStart = false;
byte sleepStart;
byte sleepSet = 5;

#define ALRM1_MATCH_EVERY_SEC  0b1111   // Once a second.
#define ALRM1_MATCH_SEC        0b1110   // When seconds match.
#define ALRM1_MATCH_MIN_SEC    0b1100   // When minutes and seconds match.
#define ALRM1_MATCH_HR_MIN_SEC 0b1000   // When hours, minutes, and seconds match.

#define ALRM2_ONCE_PER_MIN     0b111    // Once per minute (00 seconds of every minute).
#define ALRM2_MATCH_MIN        0b110    // When minutes match.
#define ALRM2_MATCH_HR_MIN     0b100    // When hours and minutes match.

byte hourSet;                           // Set time variables.
byte minSet;
byte yearSet;
byte monthSet;
byte daySet;
byte dowSet;

byte alarmOneHourSet;                   // Set alarm one time variables.
byte alarmOneMinSet;
byte alarmOneSecSet = 0;
byte alarmOneYearSet;
byte alarmOneMonthSet;
byte alarmOneDaySet;
byte alarmOneDowSet;

byte alarmOneSch;
char* alarmSchArray[6] = { "Off" , "Once" , "Daily" , "M - F" , "S - S"};  // off, once, daily, weekday & weekend.

long randNumber;

volatile byte   menu = 0;               // Menu system variable for scrolling through options.

int   rtcArray[8];                      // RTC array for date time variables.
byte  rtcA1Array[7];                    // RTC alarm array.

char* dayArray[9] = { "","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" };
char* dayShortArray[9] = { "","Su","Mo","Tu","We","Th","Fr","Sa"}; // Used for DoW menu setting only. Leading "" is because "0" is not a DoW parameter acording to the DS3231 data sheet.
char* monthArray[14] = { "",
						 "January",
						 "February",
						 "March",
						 "April",
						 "May",
						 "June",
						 "July",
						 "August",
						 "September",
						 "October",
						 "November",
						 "December"
};  // Initial "" is to solve the leading Zero in the array when matching to the month select function.

char  DisplayDateString[30];            // Strings to concatinate rtc variables in the right format x 4
char  DateAndTimeString[40];
char  HourAndMinuteString[20];
char  MinuteAndSecondString[20];

// Strings, lots and lots of strings, placing them into flash to save SRAM.

const char string_0[] PROGMEM = "The greatest glory in living lies not in never falling, but in rising every time we fall - Nelson Mandela"; // "String 0" etc are strings to store - change to suit.
const char string_1[] PROGMEM = "The way to get started is to quit talking and begin doing - Walt Disney";
const char string_2[] PROGMEM = "If life were predictable it would cease to be life, and be without flavor - Eleanor Roosevelt";
const char string_3[] PROGMEM = "Great things never come from comfort zones...";
const char string_4[] PROGMEM = "If you look at what you have in life, you'll always have more. If you look at what you don't have in life, you'll never have enough - Oprah Winfrey";
const char string_5[] PROGMEM = "If you set your goals ridiculously high and it's a failure, you will fail above everyone else's success - James Cameron";
const char string_6[] PROGMEM = "Life is what happens when you're busy making other plans - John Lennon";
const char string_7[] PROGMEM = "Spread love everywhere you go. Let no one ever come to you without leaving happier - Mother Teresa";
const char string_8[] PROGMEM = "When you reach the end of your rope, tie a knot in it and hang on - Franklin D.Roosevelt";
const char string_9[] PROGMEM = "Always remember that you are absolutely unique. Just like everyone else - Margaret Mead";
const char string_10[] PROGMEM = "Don't judge each day by the harvest you reap but by the seeds that you plant - Robert Louis Stevenson";
const char string_11[] PROGMEM = "The future belongs to those who believe in the beauty of their dreams - Eleanor Roosevelt";
const char string_12[] PROGMEM = "Tell me and I forget. Teach me and I remember. Involve me and I learn - Benjamin Franklin";
const char string_13[] PROGMEM = "The best and most beautiful things in the world cannot be seen or even touched - they must be felt with the heart - Helen Keller";
const char string_14[] PROGMEM = "It is during our darkest moments that we must focus to see the light - Aristotle";
const char string_15[] PROGMEM = "Whoever is happy will make others happy too - Anne Frank";
const char string_16[] PROGMEM = "In the end, it's not the years in your life that count. It's the life in your years - Abraham Lincoln";
const char string_17[] PROGMEM = "Life is never fair, and perhaps it is a good thing for most of us that it is not - Oscar Wilde";
const char string_18[] PROGMEM = "Only a life lived for others is a life worthwhile - Albert Einstein";
const char string_19[] PROGMEM = "The purpose of our lives is to be happy - Dalai Lama";
const char string_20[] PROGMEM = "Life is really simple, but we insist on making it complicated - Confucius";
const char string_21[] PROGMEM = "Keep smiling, because life is a beautiful thing and there's so much to smile about - Marilyn Monroe";
const char string_22[] PROGMEM = "Love the life you live. Live the life you love - Bob Marley";
const char string_23[] PROGMEM = "Life is made of ever so many partings welded together - Charles Dickens";
const char string_24[] PROGMEM = "I find that the harder I work, the more luck I seem to have - Thomas Jefferson";
const char string_25[] PROGMEM = "The secret of success is to do the common thing uncommonly well - John D.Rockefeller Jr.";
const char string_26[] PROGMEM = "I never dreamed about success, I worked for it - Estee Lauder";
const char string_27[] PROGMEM = "Try not to become a man of success. Rather become a man of value - Albert Einstein";
const char string_28[] PROGMEM = "Nothing is impossible, the word itself says, ‘I'm possible!' - Audrey Hepburn";
const char string_29[] PROGMEM = "Whether you think you can or you think you can't, you're right - Henry Ford";

// Table to reference the strings.

const char* const string_table[] PROGMEM = {	string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8, string_9, 
												string_10, string_11, string_12, string_13, string_14, string_15, string_16, string_17, string_18, string_19, 
												string_20, string_21, string_22, string_23, string_24, string_25, string_26, string_27, string_28, string_29 };

char buffer[120];  // Make sure this is large enough for the largest string it must hold

// Configure BlueTooth data variables.

const byte numChars = 64;               // Size of charater array that can be received.
char receivedChars[numChars];           // An array to store the received data.
boolean newData = false;                // Flag to detech new serial data is ready to display from BlueTooth.
byte receivedNumChar = 0;               // Count to help calculate scrolling max setting.

// Configure EEEPROM. 

int ee1224Address = 0;				    // EEPROM address for 12 / 24 hour clock setting.
bool ee1224Setting;						// Actual commit for writing, 2 bytes.
bool ee1224Change = false;              // To save EEPROM writes.

int eeBrightAddress = 4;        		// EEPROM address for brightness setting.
byte eeBrightSetting;					// Actual commit for writing, 4 bytes.
bool eeBrightChange = false;            // To save EEPROM writes.

int eeColAddress = 8;        			// EEPROM address for colour setting.
byte eeColSetting;						// Actual commit for writing, 4 bytes.
bool eeColChange = false;               // To save EEPROM writes.

int eeSpeedAddress = 12;      			// EEPROM address for speed setting.
byte eeSpeedSetting;					// Actual commit for writing, 4 bytes.
bool eeSpeedChange = false;             // To save EEPROM writes.

int eeAlarmOneSchAddress = 16; 			// EEPROM address for alarm one schedule setting.
byte eeAlarmOneSchSetting;				// Actual commit for writing, 4 bytes.
bool eeAlarmOneSchChange = false;       // To save EEPROM writes.

int eeMusicAddress = 20; 				// EEPROM address for music setting.
byte eeMusicSetting;					// Actual commit for writing, 4 bytes.
bool eeMusicChange = false;				// To save EEPROM writes.

int eeSleepSetAddress = 24; 			// EEPROM address for sleep duration setting.
byte eeSleepSetSetting;					// Actual commit for writing, 4 bytes.
bool eeSleepSetChange = false;			// To save EEPROM writes.

int eeRTCResetAddress = 28; 			// EEPROM address for RTC reset.
bool eeRTCResetSetting;					// Actual commit for writing, 2 bytes.
bool eeRTCResetChange = false;			// To save EEPROM writes.

int eeWelcomeAddress = 32; 				// EEPROM address for welcome message.
bool eeWelcomeSetting;					// Actual commit for writing, 2 bytes.
bool eeWelcomeChange = false;			// To save EEPROM writes.


void setup() {

	// Configure button pin modes.

	pinMode(intPinMenu, INPUT);
	pinMode(intPinScrollingDate, INPUT);
	pinMode(intPinWhite, INPUT);
	pinMode(intPinAlarmOneSet, INPUT);
	pinMode(intPinAlarmOneSleep, INPUT);

	pinMode(bPlus, INPUT);				// Menu plus / minus pins.
	pinMode(bMinus, INPUT);

	pinMode(vPlus, OUTPUT);				// Volume plus / minus pins.
	pinMode(vMinus, OUTPUT);

	pinMode(GSTQ, OUTPUT);				// Sound trigger pins.
	pinMode(SSB, OUTPUT);
	pinMode(Mahnamahna, OUTPUT);

	digitalWrite(GSTQ, HIGH);			// Ensure sounds do not start on start up.
	digitalWrite(SSB, HIGH);
	digitalWrite(Mahnamahna, HIGH);

	// Configure interupts.

	attachInterrupt(digitalPinToInterrupt(intPinMenu), menuISR_Menu, FALLING);
	attachInterrupt(digitalPinToInterrupt(intPinScrollingDate), dateISR_ScrollingDate, FALLING);
	attachInterrupt(digitalPinToInterrupt(intPinWhite), whiteISR_ScrollingRandom, FALLING);
	attachInterrupt(digitalPinToInterrupt(intPinAlarmOneSet), alarmISR_alarmOneSet, FALLING);
	attachInterrupt(digitalPinToInterrupt(intPinAlarmOneSleep), alarmISR_alarmOneSleep, FALLING);

	// Begin serial, mySerial, wire and RTC module.

	Serial.begin(38400);
	s1Serial.begin(38400);				// Used for Bluetooth module.
	Wire.begin();

	// Display current date and time, comment out before release, debugging only.

	rtc.setClockMode(false);			// Set to 24h

	rtcArray[6] = rtc.getYear();
	rtcArray[5] = rtc.getMonth(Century);
	rtcArray[4] = rtc.getDate();
	rtcArray[3] = rtc.getDoW();
	dowSet = rtc.getDoW();
	rtcArray[2] = rtc.getHour(h12, PM);
	rtcArray[1] = rtc.getMinute();
	rtcArray[0] = rtc.getSecond();

	char* dayOfTheWeek = (dayArray[rtcArray[3]]);       // Returns actual day of the week.
	char* monthOfTheYear = (monthArray[rtcArray[5]]);   // Returns actual month of the year.

	// Function to output data to serial monitor for debugging.

	sprintf_P(DateAndTimeString, PSTR("%02d:%02d on %s %02d %s %02d"), rtcArray[2], rtcArray[1], dayOfTheWeek, rtcArray[4], monthOfTheYear, rtcArray[6]);
	Serial.println();
	Serial.print("The current time and date is ");
	Serial.println(DateAndTimeString);

	// Read EEPROM settings to see if RTC needs master reset.

	EEPROM.get(eeRTCResetAddress, eeRTCResetSetting);

	if (eeRTCResetSetting == 0) {

		resetRTC = false;
	}

	else if (eeRTCResetSetting == 1) {

		resetRTC = true;
	}

	if (resetRTC == true) {

		resetAllSettings();

	}

	// Read EEPROM settings back into volatile memory.

	EEPROM.get(ee1224Address, ee1224Setting);					// 12 / 24 Hour clock setting.

	if (ee1224Setting == 0) {

		set1224 = false;
	}

	else if (ee1224Setting == 1) {

		set1224 = true;
	}

	EEPROM.get(eeBrightAddress, eeBrightSetting);				// Brightness setting.

	brightnessSet = eeBrightSetting;

	EEPROM.get(eeColAddress, eeColSetting);						// Colour setting.

	colorSet = eeColSetting;

	EEPROM.get(eeSpeedAddress, eeSpeedSetting);					// Scrolling speed setting.

	tempSpeedSet = eeSpeedSetting;

	speedSet = 61 - tempSpeedSet;

	EEPROM.get(eeAlarmOneSchAddress, eeAlarmOneSchSetting);		// Alarm setting.

	alarmOneSch = eeAlarmOneSchSetting;

	EEPROM.get(eeMusicAddress, eeMusicSetting);					// Music setting.

	musicSet = eeMusicSetting;

	if (musicSet == 0) {										// Set which music to play just in case power fails

		musicPlay = GSTQ;

	}

	else if (musicSet == 1) {

		musicPlay = SSB;

	}

	else if (musicSet == 2) {

		musicPlay == Mahnamahna;

	}

	EEPROM.get(eeSleepSetAddress, eeSleepSetSetting);			// Sleep setting.

	sleepSet = eeSleepSetSetting;

	EEPROM.get(eeWelcomeAddress, eeWelcomeSetting);				// Welcome message on start up setting.

	if (eeWelcomeSetting == 0) {

		resetWelcome = false;
	}

	else if (eeWelcomeSetting == 1) {

		resetWelcome = true;
	}

	// Begin NeoPixel matrix.

	matrix.begin();
	matrix.setTextWrap(false);
	matrix.setBrightness(brightnessSet);
	matrix.setTextColor(colors[colorSet]);

	// Configure random number.

	randomSeed(analogRead(A3));

	// Get Alarm One current settings

	displayCurrentAlarmOne();

	// Display welcome message.

	if (resetWelcome == true) {

		menu = 32;
	}

} // Close setup.

void loop() {

	// Check menu and trigger menu functions from interupt.

	if (menu == 0)
	{
		displayCurrentTime();
	}
	if (menu == 1)
	{
		displaySetHour();
	}
	if (menu == 2)
	{
		displaySetMinute();
	}
	if (menu == 3)
	{
		displaySetYear();
	}
	if (menu == 4)
	{
		displaySetMonth();
	}
	if (menu == 5)
	{
		displaySetDay();
	}
	if (menu == 6)
	{
		displaySetDoW();
	}
	if (menu == 7)
	{
		amPm();
	}
	if (menu == 8)
	{
		displayColorSet();
	}
	if (menu == 9)
	{
		displayBrightness();
	}
	if (menu == 10)
	{
		displaySpeedSet();
	}
	if (menu == 11)
	{
		resetWelcomeMessage();
	}
	if (menu == 12)
	{
		resetClock();
	}
	if (menu == 13)
	{
		saveTimeAndDate();
	}
	if (menu == 20)
	{
		alarmOneSchedule();
	}
	if (menu == 21)
	{
		alarmOneSetHour();
	}
	if (menu == 22)
	{
		alarmOneSetMinute();
	}
	if (menu == 23)
	{
		alarmOneMusicSet();
	}
	if (menu == 24)
	{
		alarmOneSleepTime();
	}
	if (menu == 25)
	{
		alarmOneVolume();
	}
	if (menu == 26)
	{
		alarmOneSave();
	}
	if (menu == 27)
	{
		alarmOneSleepCancel();
	}
	if (menu == 30)
	{
		displayScrollingDate();
	}
	if (menu == 31)
	{
		displayRandomWhite();			// Display random stored messages from array.
	}
	if (menu == 32)
	{
		displayWelcomeMessage();		// Display welcome message on start up only.
	}

	alarmOneTriggered();                // Check if alarm one triggered.
	checkSleep();						// Check if sleep time has been reached.
	recvBTWithStartAndEndMarker();      // Receive serial data by bluetooth.
	showNewBTData();                    // Display serial data once received.

} // Close loop.

void menuISR_Menu() {

	static unsigned long  last_interrupt_time = 0;                  // Function to solve debounce
	unsigned long         interrupt_time = millis();

	if (interrupt_time - last_interrupt_time > 200)
	{
		menu++;
	}

	if (menu > 13)
	{
		menu = 0;
		digitalWrite(SSB, HIGH);		// These digital writes are to stop music playing if menu is pressed by mistake during alarm settings
		digitalWrite(GSTQ, HIGH);
		digitalWrite(Mahnamahna, HIGH);
	}

	last_interrupt_time = interrupt_time;

} // Close function.

void alarmISR_alarmOneSet() {

	static unsigned long  last_interrupt_time = 0;                  // Function to solve debounce
	unsigned long         interrupt_time = millis();

	if (interrupt_time - last_interrupt_time > 200)
	{
		if (menu == 0) {

			menu = 20;

		}

		else menu++;

	}

	last_interrupt_time = interrupt_time;

} // Close function.


void alarmISR_alarmOneSleep() {

	static unsigned long  last_interrupt_time = 0;                  // Function to solve debounce
	unsigned long         interrupt_time = millis();

	if (interrupt_time - last_interrupt_time > 200)
	{

		if (menu == 0) {

			menu = 27;
			setSleepStart = true;

		}

	}

	last_interrupt_time = interrupt_time;

} // Close function.

void dateISR_ScrollingDate() {

	static unsigned long  last_interrupt_dateISR_time = 0;          // Function to solve debounce
	unsigned long         interrupt_dateISR_time = millis();

	if (interrupt_dateISR_time - last_interrupt_dateISR_time > 200)
	{
		menu = 30;
	}

	last_interrupt_dateISR_time = interrupt_dateISR_time;

} // Close function.

void whiteISR_ScrollingRandom() {

	static unsigned long  last_interrupt_dateISR_time = 0;          // Function to solve debounce
	unsigned long         interrupt_dateISR_time = millis();

	if (interrupt_dateISR_time - last_interrupt_dateISR_time > 200)
	{
		menu = 31;
	}

	last_interrupt_dateISR_time = interrupt_dateISR_time;

} // Close function.

void displayCurrentTime() {

	// Get current date and time.

	rtcArray[6] = rtc.getYear();
	rtcArray[5] = rtc.getMonth(Century);
	rtcArray[4] = rtc.getDate();
	rtcArray[3] = rtc.getDoW();
	dowSet = rtc.getDoW();
	rtcArray[2] = rtc.getHour(h12, PM);
	rtcArray[1] = rtc.getMinute();
	rtcArray[0] = rtc.getSecond();

	// Configure either 12 or 24 hour time display.

	if (set1224 == true) {

		int hr12;

		if (rtcArray[2] > 12) {

			hr12 = rtcArray[2] - 12;
			sprintf_P(HourAndMinuteString, PSTR("%2d:%02d"), hr12, rtcArray[1]);

		}

		else if (rtcArray[2] <= 12) {

			sprintf_P(HourAndMinuteString, PSTR("%2d:%02d"), rtcArray[2], rtcArray[1]);

		}

	}

	else sprintf_P(HourAndMinuteString, PSTR("%02d:%02d"), rtcArray[2], rtcArray[1]);

	// Update setting variables, so when selecting, they are to current time.

	minSet = rtcArray[1];
	hourSet = rtcArray[2];
	dowSet = rtcArray[3];
	daySet = rtcArray[4];
	monthSet = rtcArray[5];
	yearSet = rtcArray[6];

	// Check if current time is behind displayed time to save display refreshes and flickering, display is changed.

	if (HourAndMinuteString >= HourAndMinuteString) {

		matrix.clear();

		if (set1224 == true) {         // Configure 12 hour display and set cursor positions.

			int hr12;

			if (rtcArray[2] > 12) {

				hr12 = rtcArray[2] - 12;

				if (hr12 <= 9) {

					matrix.setCursor(3, 0);

				}

				else matrix.setCursor(6, 0);

			}

			else if (rtcArray[2] <= 9) {

				matrix.setCursor(3, 0);

			}

			else matrix.setCursor(6, 0);

		}

		else matrix.setCursor(6, 0);

		// Configure & display PM sign for 12 hour clock display.

		if (set1224 == true) {

			if (rtcArray[2] >= 12) {

				if (colorSet == 0) {

					matrix.setPixelColor(300, 255, 0, 0);
					matrix.setPixelColor(301, 255, 0, 0);
					matrix.setPixelColor(308, 255, 0, 0);
					matrix.setPixelColor(309, 255, 0, 0);
					matrix.setPixelColor(316, 255, 0, 0);
				}

				else if (colorSet == 1) {

					matrix.setPixelColor(300, 0, 255, 0);
					matrix.setPixelColor(301, 0, 255, 0);
					matrix.setPixelColor(308, 0, 255, 0);
					matrix.setPixelColor(309, 0, 255, 0);
					matrix.setPixelColor(316, 0, 255, 0);
				}

				else if (colorSet == 2) {

					matrix.setPixelColor(300, 255, 255, 0);
					matrix.setPixelColor(301, 255, 255, 0);
					matrix.setPixelColor(308, 255, 255, 0);
					matrix.setPixelColor(309, 255, 255, 0);
					matrix.setPixelColor(316, 255, 255, 0);
				}

				else if (colorSet == 3) {

					matrix.setPixelColor(300, 0, 0, 255);
					matrix.setPixelColor(301, 0, 0, 255);
					matrix.setPixelColor(308, 0, 0, 255);
					matrix.setPixelColor(309, 0, 0, 255);
					matrix.setPixelColor(316, 0, 0, 255);
				}

				else if (colorSet == 4) {

					matrix.setPixelColor(300, 255, 0, 255);
					matrix.setPixelColor(301, 255, 0, 255);
					matrix.setPixelColor(308, 255, 0, 255);
					matrix.setPixelColor(309, 255, 0, 255);
					matrix.setPixelColor(316, 255, 0, 255);
				}

				else if (colorSet == 5) {

					matrix.setPixelColor(300, 0, 255, 255);
					matrix.setPixelColor(301, 0, 255, 255);
					matrix.setPixelColor(308, 0, 255, 255);
					matrix.setPixelColor(309, 0, 255, 255);
					matrix.setPixelColor(316, 0, 255, 255);
				}

				else if (colorSet == 6) {

					matrix.setPixelColor(300, 255, 255, 255);
					matrix.setPixelColor(301, 255, 255, 255);
					matrix.setPixelColor(308, 255, 255, 255);
					matrix.setPixelColor(309, 255, 255, 255);
					matrix.setPixelColor(316, 255, 255, 255);
				}
			}
		}

		// Configure & display alarm one sign.

		if (rtc.checkAlarmEnabled(1)) {

			if (colorSet == 0) {

				matrix.setPixelColor(276, 255, 0, 0);
				matrix.setPixelColor(277, 255, 0, 0);
				matrix.setPixelColor(284, 255, 0, 0);
				matrix.setPixelColor(285, 255, 0, 0);
			}

			else if (colorSet == 1) {

				matrix.setPixelColor(276, 0, 255, 0);
				matrix.setPixelColor(277, 0, 255, 0);
				matrix.setPixelColor(284, 0, 255, 0);
				matrix.setPixelColor(285, 0, 255, 0);
			}

			else if (colorSet == 2) {

				matrix.setPixelColor(276, 255, 255, 0);
				matrix.setPixelColor(277, 255, 255, 0);
				matrix.setPixelColor(284, 255, 255, 0);
				matrix.setPixelColor(285, 255, 255, 0);
			}

			else if (colorSet == 3) {

				matrix.setPixelColor(276, 0, 0, 255);
				matrix.setPixelColor(277, 0, 0, 255);
				matrix.setPixelColor(284, 0, 0, 255);
				matrix.setPixelColor(285, 0, 0, 255);
			}

			else if (colorSet == 4) {

				matrix.setPixelColor(276, 255, 0, 255);
				matrix.setPixelColor(277, 255, 0, 255);
				matrix.setPixelColor(284, 255, 0, 255);
				matrix.setPixelColor(285, 255, 0, 255);
			}

			else if (colorSet == 5) {

				matrix.setPixelColor(276, 0, 255, 255);
				matrix.setPixelColor(277, 0, 255, 255);
				matrix.setPixelColor(284, 0, 255, 255);
				matrix.setPixelColor(285, 0, 255, 255);
			}

			else if (colorSet == 6) {

				matrix.setPixelColor(276, 255, 255, 255);
				matrix.setPixelColor(277, 255, 255, 255);
				matrix.setPixelColor(284, 255, 255, 255);
				matrix.setPixelColor(285, 255, 255, 255);
			}
		}

	}

	matrix.setTextColor(colors[colorSet]);
	matrix.print(HourAndMinuteString);
	matrix.show();

} // Close function.

void displaySetHour() {

	// Set hour time setting.

	if (digitalRead(bPlus) == LOW)
	{
		if (hourSet == 23)              // 24 hour clock.
		{
			hourSet = 0;
		}
		else
		{
			hourSet = hourSet + 1;      // Increment by 1.
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (hourSet == 0)
		{
			hourSet = 23;
		}
		else
		{
			hourSet = hourSet - 1;      // Decrement by 1.
		}
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Hr :"));
	matrix.show();

	matrix.print(hourSet);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySetMinute() {

	// Setting the minutes.

	if (digitalRead(bPlus) == LOW)
	{
		if (minSet == 59)
		{
			minSet = 0;
		}
		else
		{
			minSet = minSet + 1;
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (minSet == 0)
		{
			minSet = 59;
		}
		else
		{
			minSet = minSet - 1;
		}
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Min:"));
	matrix.show();

	matrix.print(minSet);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySetYear() {

	// setting the year.

	if (digitalRead(bPlus) == LOW)
	{
		yearSet = yearSet + 1;
	}
	if (digitalRead(bMinus) == LOW)
	{
		yearSet = yearSet - 1;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Yr :"));
	matrix.show();

	int yearSet2 = yearSet; //

	matrix.print(yearSet2 % 100);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySetMonth() {

	// Setting the month.

	if (digitalRead(bPlus) == LOW)
	{
		if (monthSet == 12)
		{
			monthSet = 1;
		}
		else
		{
			monthSet = monthSet + 1;
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (monthSet == 1)
		{
			monthSet = 12;
		}
		else
		{
			monthSet = monthSet - 1;
		}
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Mth:"));
	matrix.show();

	matrix.print(monthSet);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySetDay() {

	// Configure quantity of days per month.

	byte qtyDays;

	if (monthSet == 1 || monthSet == 3 || monthSet == 5 || monthSet == 7 || monthSet == 8 || monthSet == 10 || monthSet == 12) {

		qtyDays = 31;
	}

	else if (monthSet == 4 || monthSet == 6 || monthSet == 9 || monthSet == 11) {

		qtyDays = 30;
	}

	else if (monthSet == 2) {

		qtyDays = 28;
	}

	// Setting the day.

	if (digitalRead(bPlus) == LOW)
	{
		if (daySet == qtyDays)
		{
			daySet = 1;
		}
		else
		{
			daySet = daySet + 1;
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (daySet == 1)
		{
			daySet = qtyDays;
		}
		else
		{
			daySet = daySet - 1;
		}
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Day:"));
	matrix.show();

	matrix.print(daySet);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySetDoW() {

	// Setting the DoW.

	if (digitalRead(bPlus) == LOW)
	{
		if (dowSet == 7)
		{
			dowSet = 1;
		}
		else
		{
			dowSet = dowSet + 1;
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (dowSet == 1)
		{
			dowSet = 7;
		}
		else
		{
			dowSet = dowSet - 1;
		}
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("DoW:"));
	matrix.show();

	matrix.print(dayShortArray[dowSet]);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void displaySpeedSet() {

	// Setting the display speed.

	if (digitalRead(bPlus) == LOW)
	{
		if (tempSpeedSet == 60)
		{
			tempSpeedSet = 1;
		}
		else
		{
			tempSpeedSet = tempSpeedSet + 1;
		}

		eeSpeedChange = true;
	}

	if (digitalRead(bMinus) == LOW)
	{
		if (tempSpeedSet == 1)
		{
			tempSpeedSet = 60;
		}
		else
		{
			tempSpeedSet = tempSpeedSet - 1;
		}

		eeSpeedChange = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.print(F("Spd:"));
	matrix.show();

	matrix.print(tempSpeedSet);
	matrix.show();

	speedSet = 61 - tempSpeedSet;

	if (eeSpeedChange == true)
	{
		eeSpeedSetting = tempSpeedSet;
		EEPROM.update(eeSpeedAddress, eeSpeedSetting);	// Record speed setting into EEPROM.
		eeSpeedChange = false;
	}

	delay(buttonDelay);

} // Close function.

void displayColorSet() {

	// Setting the display speed.

	if (digitalRead(bPlus) == LOW)
	{
		if (colorSet == 6)
		{
			colorSet = 0;
		}
		else
		{
			colorSet = colorSet + 1;
		}

		eeColChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (colorSet == 0)
		{
			colorSet = 6;
		}
		else
		{
			colorSet = colorSet - 1;
		}

		eeColChange = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.setTextColor(colors[colorSet]);
	matrix.print(colorArray[colorSet]);
	matrix.show();

	if (eeColChange == true)
	{
		eeColSetting = colorSet;
		EEPROM.update(eeColAddress, eeColSetting);	// Record brightness setting into EEPROM.
		eeColChange = false;
	}
	delay(buttonDelay);

} // Close function.

void displayBrightness() {

	// Setting the display brightness.

	if (digitalRead(bPlus) == LOW)
	{
		if (brightnessSet == 95)
		{
			brightnessSet = 1;
		}
		else
		{
			brightnessSet = brightnessSet + 1;
		}

		eeBrightChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (brightnessSet == 1)
		{
			brightnessSet = 95;
		}
		else
		{
			brightnessSet = brightnessSet - 1;
		}

		eeBrightChange = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.setBrightness(brightnessSet);
	matrix.print(F("Brg:"));
	matrix.show();

	matrix.print(brightnessSet);
	matrix.show();

	if (eeBrightChange == true)
	{
		eeBrightSetting = brightnessSet;
		EEPROM.update(eeBrightAddress, eeBrightSetting);	// Record brightness setting into EEPROM.
		eeBrightChange = false;
	}


	delay(buttonDelay);

} // Close function.

void amPm() {

	// Setting either 12 or 24 hour clock display.

	if (digitalRead(bPlus) == LOW)
	{
		if (set1224 == false)
		{
			set1224 = true;
		}
		else
		{
			set1224 = false;
		}

		ee1224Change = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (set1224 == true)
		{
			set1224 = false;
		}
		else
		{
			set1224 = true;
		}

		ee1224Change = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.setBrightness(brightnessSet);
	matrix.print(F("12H: "));
	matrix.show();

	char yesNo[2][2] = { "N", "Y" };

	if (set1224 == false) {

		matrix.print(yesNo[0]);
		matrix.show();
	}

	else {

		matrix.print(yesNo[1]);
		matrix.show();

	}

	// Commit to EEPROM.

	if (set1224 == false) {

		ee1224Setting = 0;
	}

	else if (set1224 == true) {

		ee1224Setting = 1;
	}

	if (ee1224Change == true)
	{
		EEPROM.update(ee1224Address, ee1224Setting);	// Record the 12 / 24 hour clock setting into EEPROM.
		ee1224Change = false;
	}

	delay(buttonDelay);

} // Close function.

void resetWelcomeMessage() {

	// Reset the welcome message on start up.

	if (digitalRead(bPlus) == LOW)
	{
		if (resetWelcome == false)
		{
			resetWelcome = true;
		}
		else
		{
			resetWelcome = false;
		}

		eeWelcomeChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (resetWelcome == true)
		{
			resetWelcome = false;
		}
		else
		{
			resetWelcome = true;
		}

		eeWelcomeChange = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.setBrightness(brightnessSet);
	matrix.print(F("Wel: "));
	matrix.show();

	char yesNo[2][2] = { "N", "Y" };

	if (resetWelcome == false) {

		matrix.print(yesNo[0]);
		matrix.show();
	}

	else {

		matrix.print(yesNo[1]);
		matrix.show();

	}

	// Commit to EEPROM.

	if (resetWelcome == false) {

		eeWelcomeSetting = 0;
	}

	else if (resetWelcome == true) {

		eeWelcomeSetting = 1;
	}

	if (eeWelcomeChange == true)
	{
		EEPROM.update(eeWelcomeAddress, eeWelcomeSetting);	// Record the welcome message flag into EEPROM.
		eeWelcomeChange = false;
	}

	delay(buttonDelay);

}

void resetClock() {

	// Reset the RTC if EEPROM corrupts.

	if (digitalRead(bPlus) == LOW)
	{
		if (resetRTC == false)
		{
			resetRTC = true;
		}
		else
		{
			resetRTC = false;
		}

		eeRTCResetChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (resetRTC == true)
		{
			resetRTC = false;
		}
		else
		{
			resetRTC = true;
		}

		eeRTCResetChange = true;
	}

	matrix.clear();
	matrix.setCursor(1, 0);
	matrix.setBrightness(brightnessSet);
	matrix.print(F("Rst: "));
	matrix.show();

	char yesNo[2][2] = { "N", "Y" };

	if (resetRTC == false) {

		matrix.print(yesNo[0]);
		matrix.show();
	}

	else {

		matrix.print(yesNo[1]);
		matrix.show();

	}

	// Commit to EEPROM.

	if (resetRTC == false) {

		eeRTCResetSetting = 0;
	}

	else if (resetRTC == true) {

		eeRTCResetSetting = 1;
	}

	if (eeRTCResetChange == true)
	{
		EEPROM.update(eeRTCResetAddress, eeRTCResetSetting);	// Record the 12 / 24 hour clock setting into EEPROM.
		eeRTCResetChange = false;
	}

	delay(buttonDelay);

}

void saveTimeAndDate() {

	// Set date / time.

	//rtc.adjust(DateTime(yearSet, monthSet, daySet, hourSet, minSet, 0));    // Send updated variables to RTC module.

	rtc.setYear(yearSet);
	rtc.setMonth(monthSet);
	rtc.setDate(daySet);
	rtc.setDoW(dowSet);
	rtc.setHour(hourSet);
	rtc.setMinute(minSet);
	//rtc.setSecond(Second);

	// Variable saving.

	matrix.clear();
	matrix.setCursor(5, 0);
	matrix.print(F("Saved"));
	matrix.show();
	delay(2000);

	menu = 0;   // Reset menu option once saved.

	//DateTime now = rtc.now();

	rtcArray[6] = rtc.getYear();
	rtcArray[5] = rtc.getMonth(Century);
	rtcArray[4] = rtc.getDate();
	rtcArray[3] = rtc.getDoW();
	rtcArray[2] = rtc.getHour(h12, PM);
	rtcArray[1] = rtc.getMinute();
	rtcArray[0] = rtc.getSecond();

	char* dayOfTheWeek = (dayArray[rtcArray[3]]);      // returns actual day of the week.
	char* monthOfTheYear = (monthArray[rtcArray[5]]);    // returns actual month of the year.

	sprintf_P(DateAndTimeString, PSTR("%02d:%02d on %s %02d %s %02d"), rtcArray[2], rtcArray[1], dayOfTheWeek, rtcArray[4], monthOfTheYear, rtcArray[6]);
	Serial.print("Time and Date have been set to: ");
	Serial.println(DateAndTimeString);

} // Close function.

void alarmOneSchedule() {

	// Get Alarm One current settings

	displayCurrentAlarmOne();

	// Alarm scheudle - off, once, daily, workday, weekend

	if (digitalRead(bPlus) == LOW)
	{
		if (alarmOneSch == 4)
		{
			alarmOneSch = 0;
		}
		else
		{
			alarmOneSch = alarmOneSch + 1;      // Increment by 1.
		}

		eeAlarmOneSchChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (alarmOneSch == 0)
		{
			alarmOneSch = 4;
		}
		else
		{
			alarmOneSch = alarmOneSch - 1;      // Decrement by 1.
		}

		eeAlarmOneSchChange = true;
	}

	matrix.clear();
	matrix.setCursor(6, 0);
	matrix.print(alarmSchArray[alarmOneSch]);
	matrix.show();

	if (eeAlarmOneSchChange == true)
	{
		eeAlarmOneSchSetting = alarmOneSch;
		EEPROM.update(eeAlarmOneSchAddress, eeAlarmOneSchSetting);	// Record alarm one schedule setting into EEPROM.
		eeAlarmOneSchChange = false;
	}
	delay(buttonDelay);

}

void alarmOneSetHour() {

	// Check schedule.

	if (alarmOneSch != 0) {

		// Alarm one set hour.

		if (digitalRead(bPlus) == LOW)
		{
			if (alarmOneHourSet == 23)           // 24 hour clock.
			{
				alarmOneHourSet = 0;
			}
			else
			{
				alarmOneHourSet = alarmOneHourSet + 1;      // Increment by 1.
			}
		}
		if (digitalRead(bMinus) == LOW)
		{
			if (alarmOneHourSet == 0)
			{
				alarmOneHourSet = 23;
			}
			else
			{
				alarmOneHourSet = alarmOneHourSet - 1;      // Decrement by 1.
			}
		}

		char alarmOneHourSetString[4];
		char alarmOneMinSetString[4];

		sprintf_P(alarmOneHourSetString, PSTR("%02d"), alarmOneHourSet);
		sprintf_P(alarmOneMinSetString, PSTR("%02d"), alarmOneMinSet);

		matrix.clear();
		matrix.setCursor(6, 0);

		if (colorSet != 1) {

			matrix.setTextColor(colors[1]);

		}

		else {

			matrix.setTextColor(colors[6]);
		}

		matrix.print(alarmOneHourSetString);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(F(":"));
		matrix.print(alarmOneMinSetString);
		matrix.show();

	}

	else    alarmOneSave();

	delay(buttonDelay);

} // Close function.

void alarmOneSetMinute() {

	// Alarm one set minute.

	if (digitalRead(bPlus) == LOW)
	{
		if (alarmOneMinSet == 59)
		{
			alarmOneMinSet = 0;
		}
		else
		{
			alarmOneMinSet = alarmOneMinSet + 1;      // Increment by 1.
		}
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (alarmOneMinSet == 0)
		{
			alarmOneMinSet = 59;
		}
		else
		{
			alarmOneMinSet = alarmOneMinSet - 1;      // Decrement by 1.
		}
	}

	char alarmOneHourSetString[4];
	char alarmOneMinSetString[4];

	sprintf_P(alarmOneHourSetString, PSTR("%02d"), alarmOneHourSet);
	sprintf_P(alarmOneMinSetString, PSTR("%02d"), alarmOneMinSet);

	matrix.clear();
	matrix.setCursor(6, 0);
	matrix.setTextColor(colors[colorSet]);
	matrix.print(alarmOneHourSetString);
	matrix.print(F(":"));

	if (colorSet != 1) {

		matrix.setTextColor(colors[1]);

	}

	else {

		matrix.setTextColor(colors[6]);
	}

	matrix.print(alarmOneMinSetString);
	matrix.show();

	delay(buttonDelay);

} // Close function.

void alarmOneSleepTime() {

	digitalWrite(musicPlay, HIGH);

	// Alarm one set sleep period.

	if (digitalRead(bPlus) == LOW)
	{
		if (sleepSet == 15)
		{
			sleepSet = 1;
		}
		else
		{
			sleepSet = sleepSet + 1;      // Increment by 1.
		}

		eeSleepSetChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (sleepSet == 1)
		{
			sleepSet = 15;
		}
		else
		{
			sleepSet = sleepSet - 1;      // Decrement by 1.
		}

		eeSleepSetChange = true;
	}

	matrix.clear();
	matrix.setCursor(0, 0);
	matrix.setTextColor(colors[colorSet]);
	matrix.print(F("Slp:"));
	matrix.show();

	matrix.print(sleepSet);
	matrix.show();

	if (eeSleepSetChange == true)
	{
		eeSleepSetSetting = sleepSet;
		EEPROM.update(eeSleepSetAddress, eeSleepSetSetting);	// Record sleep setting into EEPROM.
		eeSleepSetChange = false;
	}
	delay(buttonDelay);

}

void alarmOneMusicSet() {

	// Alarm one choose music option.

	if (digitalRead(bPlus) == LOW)
	{
		if (musicSet == 2)
		{
			musicSet = 0;
			musicScroll = true;
		}
		else
		{
			musicSet = musicSet + 1;      // Increment by 1.
			musicScroll = true;
		}

		eeMusicChange = true;
	}
	if (digitalRead(bMinus) == LOW)
	{
		if (musicSet == 0)
		{
			musicSet = 2;
			musicScroll = true;

		}
		else
		{
			musicSet = musicSet - 1;      // Decrement by 1.
			musicScroll = true;
		}

		eeMusicChange = true;
	}

	if (musicScroll == true) {

		matrix.clear();
		matrix.setCursor(0, 0);
		matrix.show();

		String msgText = (musicArray[musicSet]);

		Serial.print("Message Text From Table: ");
		Serial.println(msgText);

		int textLenght = msgText.length();
		int msgSize = (textLenght * pixelPerChar);  // Calculate message length.
		int scrollingMax = (msgSize);               // Adjust displacement for message length.

		if (!debug == true) {

			// Print variables for debugging messages lenghts

			Serial.print("Matrix Width = ");
			Serial.println(x);
			Serial.print(" Text Lenght = ");
			Serial.print(textLenght);
			Serial.print(" Message Size = ");
			Serial.print(msgSize);
			Serial.print(" Scrolling Max = ");
			Serial.println(scrollingMax);

		} // Close if.

		while (x > -scrollingMax) {        // Only display text for one pass

			matrix.fillScreen(0);
			matrix.setCursor(x, 0);
			matrix.setTextColor(colors[colorSet]);
			matrix.print(msgText);

			if (--x < -scrollingMax)
			{
				x = matrix.width();
			}
			matrix.show();
			delay(speedSet);

		} // Close while.

		x = matrix.width();

	} // Close if.

	musicScroll = false;

	matrix.clear();
	matrix.setCursor(0, 0);
	matrix.show();

	if (musicSet == 0) {

			matrix.setCursor(9, 0);
			matrix.setTextColor(colors[colorSet]);
			matrix.print("GSTQ");
			matrix.show();

	}

	else if (musicSet == 1) {

			matrix.setCursor(11, 0);
			matrix.setTextColor(colors[colorSet]);
			matrix.print("SSB");
			matrix.show();

		}
	
	else if (musicSet == 2) {

		matrix.setCursor(0, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print("Muppets");
		matrix.show();

	}

	if (musicSet == 0) {

		musicPlay = GSTQ;
		digitalWrite(GSTQ, LOW);
		digitalWrite(SSB, HIGH);
		digitalWrite(Mahnamahna, HIGH);
	}

	else if (musicSet == 1) {

		musicPlay = SSB;
		digitalWrite(GSTQ, HIGH);
		digitalWrite(SSB, LOW);
		digitalWrite(Mahnamahna, HIGH);

	}

	else if (musicSet == 2) {

		musicPlay = Mahnamahna;
		digitalWrite(GSTQ, HIGH);
		digitalWrite(SSB, HIGH);
		digitalWrite(Mahnamahna, LOW);

	}

	if (eeMusicChange == true)
	{
		eeMusicSetting = musicSet;
		EEPROM.update(eeMusicAddress, eeMusicSetting);	// Record music setting into EEPROM.
		eeAlarmOneSchChange = false;
	}
	delay(buttonDelay);

}

void alarmOneVolume() {

	// Alarm one volume.

	if (digitalRead(bPlus) == LOW)
	{
		volumeSet = volumeSet + 1;      // Increment by 1.
		digitalWrite(vPlus, LOW);
		delay(100);
		digitalWrite(vPlus, HIGH);

	}
	if (digitalRead(bMinus) == LOW)
	{
		volumeSet = volumeSet - 1;      // Decrement by 1.
		digitalWrite(vMinus, LOW);
		delay(100);
		digitalWrite(vMinus, HIGH);

	}

	matrix.clear();
	matrix.setCursor(0, 0);
	matrix.setTextColor(colors[colorSet]);
	matrix.print(F("Vol:"));
	matrix.show();

	if (volumeSet >= 26)					// For loop to ensure volume doesnt get out of sync due to earlier menu.
	{
		byte tempVol = volumeSet - 25;

		for (byte i = tempVol; i == 0; i--) {

			digitalWrite(vMinus, LOW);
			delay(100);
			digitalWrite(vMinus, HIGH);
		}

		volumeSet = 25;
	}

	if (volumeSet <= 1)
	{
		volumeSet = 1;
	}

	matrix.print(volumeSet);
	matrix.show();

	delay(buttonDelay);

}

void alarmOneSave() {

	// Alarm one save and display.

	if (alarmOneSch == 0) {					// Alarm one off.

		rtc.turnOffAlarm(1);
		digitalWrite(SSB, HIGH);
		digitalWrite(GSTQ, HIGH);
		digitalWrite(Mahnamahna, HIGH);

		if (rtc.checkAlarmEnabled(1) == false) {

			Serial.print("Alarm is disabled");

		}

		else Serial.print("Alarm is enabled");
	}


	else if (alarmOneSch == 1) {			// Alarm one once.

		rtc.setA1Time(1, alarmOneHourSet, alarmOneMinSet, 0, ALRM1_MATCH_HR_MIN_SEC, false, false, false);
		rtc.turnOnAlarm(1);
		rtc.checkAlarmEnabled(1);

		if (rtc.checkAlarmEnabled(1) == false) {

			Serial.print("Alarm is disabled");

		}

		else Serial.print("Alarm is enabled");
	}

	else if (alarmOneSch == 2 || alarmOneSch == 3 || alarmOneSch == 4 || alarmOneSch == 5) {			// Other alarm one schedules.

		rtc.setA1Time(1, alarmOneHourSet, alarmOneMinSet, 0, ALRM1_MATCH_HR_MIN_SEC, false, false, false);
		rtc.turnOnAlarm(1);
		rtc.checkAlarmEnabled(1);

		if (rtc.checkAlarmEnabled(1) == false) {

			Serial.print("Alarm is disabled");

		}

		else Serial.print("Alarm is enabled");
	}

	// Variable saving.

	matrix.clear();
	matrix.setCursor(5, 0);
	matrix.setTextColor(colors[colorSet]);
	matrix.print(F("Saved"));
	matrix.show();
	delay(2000);

	displayCurrentAlarmOne();

	char alarmOneDateAndTimeString[30];

	sprintf_P(alarmOneDateAndTimeString, PSTR("%02d:%02d"), alarmOneHourSet, alarmOneMinSet);
	Serial.print("Alarm One Set To: ");
	Serial.println(alarmOneDateAndTimeString);

	menu = 0;   // Reset menu option once saved.

} // Close function.

void alarmOneTriggered() {

	// Alarm one check if triggered - // 0 = off / 1 = once / 2 = daily / 3 = weekday / 4 = weekend

	// DoW: 1 = Sunday / 2 = Monday / 3 = Tuesday / 4 = Wednesday / 5 = Thursday / 6 = Friday / 7 = Saturday

	if (rtc.checkIfAlarm(1)) 
		
		if (alarmOneSch == 0) {

			if (debug == true) {

				Serial.println();
				Serial.print("No Alarm scheduled");
				Serial.println();
			}

		}
	
		else if (alarmOneSch == 1) {

			if (debug == true) {

				Serial.println();
				Serial.print("Alarm schedule 1 Triggered / Once");
				Serial.println();
			}

			digitalWrite(musicPlay, LOW);
			alarmOneState = true;

		}

		else if (alarmOneSch == 2) {

			if (debug == true) {

				Serial.println();
				Serial.print("Alarm schedule 2 Triggered / Daily");
				Serial.println();
			}

			digitalWrite(musicPlay, LOW);
			alarmOneState = true;

		}

		else if (alarmOneSch == 3) {

			if (dowSet == 2 || dowSet == 3 || dowSet == 4 || dowSet == 5 || dowSet == 6) {

				if (debug == true) {

					Serial.println();
					Serial.print("Alarm schedule 3 Triggered / Weekday");
					Serial.println();
				}

				digitalWrite(musicPlay, LOW);
				alarmOneState = true;

			}

		}

		else if (alarmOneSch == 4) {

			if (dowSet == 1 || dowSet == 7) {

				if (debug == true) {

					Serial.println();
					Serial.print("Alarm schedule 4 Triggered / Weekend");
					Serial.println();
				}

				digitalWrite(musicPlay, LOW);
				alarmOneState = true;

			}

		}

} // Close function.

void alarmOneSleepCancel() {

	// Alarm one sleep alarm.

	if (alarmOneState == true && setSleepStart == true) {

		digitalWrite(musicPlay, HIGH);
		sleepStart = rtc.getMinute();
		setSleepStart = false;

		matrix.clear();
		matrix.setCursor(5, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(F("Sleep"));
		matrix.show();
		delay(1250);

	}

	menu = 0;

	// Get Alarm One current settings

	displayCurrentAlarmOne();

} // Close function.

void checkSleep() {

	// Alarm one check sleep period.

	byte currentTime = rtc.getMinute();
	byte wakeTime = sleepStart + sleepSet;

	if (wakeTime > 59) {

		wakeTime = (wakeTime - 60);
	}

	if (alarmOneState == true) {

		if (currentTime == wakeTime) {

			digitalWrite(musicPlay, LOW);
			Serial.println();
			Serial.print("Sleep Time Ended");
			Serial.println();

		}

	}

}  // Close function.

void displayScrollingDate() {

	// This function is also used to cancel alarm one.

	digitalWrite(SSB, HIGH);
	digitalWrite(GSTQ, HIGH);
	digitalWrite(Mahnamahna, HIGH);
	alarmOneState = false;

	if (alarmOneSch == 0) {					// Alarm one off.

		rtc.turnOffAlarm(1);
		alarmOneSch = 0;
	}

	else if (alarmOneSch == 1) {			// Alarm one once.

		rtc.turnOffAlarm(1);
		alarmOneSch = 0;
		eeAlarmOneSchChange = true;

		if (eeAlarmOneSchChange == true)	// Record change into EEPROM.
		{
			eeAlarmOneSchSetting = alarmOneSch;
			EEPROM.update(eeAlarmOneSchAddress, eeAlarmOneSchSetting);		// Record alarm one schedule setting into EEPROM.
			eeAlarmOneSchChange = false;
		}

	}

	else if (alarmOneSch == 2 || alarmOneSch == 3 || alarmOneSch == 4) {	// Alarm one daily, weekday or weekend

		rtc.turnOnAlarm(1);
		rtc.checkAlarmEnabled(1);

	}

	// Get alarm one date and time.

	displayCurrentAlarmOne();

	// Display date.

	char* dayOfTheWeek = (dayArray[rtcArray[3]]);       // returns actual day of the week.
	char* monthOfTheYear = (monthArray[rtcArray[5]]);   // returns actual month of the year.

	sprintf_P(DisplayDateString, PSTR("%s %02d %s %02d"), dayOfTheWeek, rtcArray[4], monthOfTheYear, rtcArray[6]);

	if (!debug == true) {

		// Print date, comment out before release, debugging only.

		Serial.print("Today's Date is: ");
		Serial.println(DisplayDateString);

	} // Close if.

	String msgText = DisplayDateString;

	int textLenght = msgText.length();
	int msgSize = (textLenght * pixelPerChar) + (2 * pixelPerChar); // Calculate message length.
	int scrollingMax = (msgSize)+matrix.width() + matrix.width();   // Adjust displacement for message length.

	if (!debug == true) {

		// Print variables for debugging messages lenghts

		Serial.print("Matrix Width = ");
		Serial.println(x);
		Serial.print(" Text Lenght = ");
		Serial.print(textLenght);
		Serial.print(" Message Size = ");
		Serial.print(msgSize);
		Serial.print(" Scrolling Max = ");
		Serial.println(scrollingMax);

	} // Close if.

	while (x > -scrollingMax) {        // Only display text for one pass

		matrix.fillScreen(0);
		matrix.setCursor(x, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(F("Today's Date : "));
		matrix.print(DisplayDateString);

		if (--x < -scrollingMax)
		{
			x = matrix.width();
		}
		matrix.show();
		delay(speedSet);

	} // Close while.

	// Reset width and menu flag.

	x = matrix.width();
	delay(500);
	menu = 0;

} // Close function.
  
void displayRandomWhite() {

	// Display random messages.

	randNumber = random(30);

	Serial.print("Random Number: ");
	Serial.println(randNumber);

	strcpy_P(buffer, (char*)pgm_read_word(&(string_table[randNumber])));

	String msgText = buffer;

	Serial.print("Message Text From Table: ");
	Serial.println(msgText);

	int textLenght = msgText.length();
	int msgSize = (textLenght * pixelPerChar);  // Calculate message length.
	int scrollingMax = (msgSize);               // Adjust displacement for message length.

	if (!debug == true) {

		// Print variables for debugging messages lenghts

		Serial.print("Matrix Width = ");
		Serial.println(x);
		Serial.print(" Text Lenght = ");
		Serial.print(textLenght);
		Serial.print(" Message Size = ");
		Serial.print(msgSize);
		Serial.print(" Scrolling Max = ");
		Serial.println(scrollingMax);

	} // Close if.

	while (x > -scrollingMax) {        // Only display text for one pass

		matrix.fillScreen(0);
		matrix.setCursor(x, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(msgText);

		if (--x < -scrollingMax)
		{
			x = matrix.width();
		}
		matrix.show();
		delay(speedSet);

	} // Close while.

	// Reset width and menu flag.

	x = matrix.width();
	delay(500);
	menu = 0;

} // Close function.

void displayWelcomeMessage() {

	// Display welcome message. Edit depending on who it is going to.

	String msgText = "            Insert message here...";

	Serial.print("Welcome Message Text: ");
	Serial.println(msgText);

	int textLenght = msgText.length();
	int msgSize = (textLenght * pixelPerChar);  // Calculate message length.
	int scrollingMax = (msgSize);               // Adjust displacement for message length.

	if (!debug == true) {

		// Print variables for debugging messages lenghts

		Serial.print("Matrix Width = ");
		Serial.println(x);
		Serial.print(" Text Lenght = ");
		Serial.print(textLenght);
		Serial.print(" Message Size = ");
		Serial.print(msgSize);
		Serial.print(" Scrolling Max = ");
		Serial.println(scrollingMax);

	} // Close if.

	while (digitalRead(intPinAlarmOneSleep) == HIGH) {		// Press sleep button to continue message.
		
		while (x > -378) {        // Only display text for one pass.

			matrix.fillScreen(0);
			matrix.setCursor(x, 0);
			matrix.setTextColor(colors[colorSet]);
			matrix.print("Hold down the sleep button until music plays to continue...    ");

			if (--x < -378)
			{
				x = matrix.width();
			}
			matrix.show();
			delay(speedSet);

		} // Close while.

		x = matrix.width();				// Reset cursor position for next message.

	} // Close while.

	// Play the Muppets for a laugh...

	digitalWrite(Mahnamahna, LOW);

	while (x > -scrollingMax) {        // Only display text for one pass.

		matrix.fillScreen(0);
		matrix.setCursor(x, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(msgText);

		if (--x < -scrollingMax)
		{
			x = matrix.width();
		}
		matrix.show();
		delay(16);

	} // Close while.

	// Reset width and menu flag.

	x = matrix.width();
	delay(500);
	menu = 0;
	eeWelcomeSetting = false;
	resetWelcome = false;
	EEPROM.update(eeWelcomeAddress, eeWelcomeSetting);		// Record the welcome message flag into EEPROM.
	digitalWrite(Mahnamahna, HIGH);

} // Close function.

void recvBTWithStartAndEndMarker() {

	// Save received BlueTooth data into array.

	static boolean recvInProgress = false;
	byte ndx = 0;
	char startMarker = '(';
	char endMarker = ')';
	char rc;
	receivedNumChar = 0;

	while (s1Serial.available() > 0 && newData == false) {
		rc = s1Serial.read();

		if (recvInProgress == true) {
			if (rc != endMarker) {
				receivedChars[ndx] = rc;
				ndx++;
				receivedNumChar++;
				if (ndx >= numChars) {
					ndx = numChars - 1;
				}
			}
			else {
				receivedChars[ndx] = '\0'; // terminate the string
				recvInProgress = false;
				ndx = 0;
				newData = true;
			}
		}

		else if (rc == startMarker) {
			recvInProgress = true;
		}

	} // Close while.

} // Close function.

void showNewBTData() {

	// Call BlueTooth array data to be displayed.

	if (newData == true) {

		if (!debug == true) {

			Serial.print("This just in ... ");
			Serial.println();
			Serial.println();
			Serial.println(receivedChars);
			Serial.println();

		} // Close if.

		displayBlueToothText();

		newData = false;
	}

} // Close function.

void displayBlueToothText() {

	// Display BlueTooth array data.

	if (!debug == true) {

		Serial.print("Whats in the Received Charaters Buffer? ");
		Serial.println();
		Serial.println();
		Serial.println(receivedChars);
		Serial.println();

		Serial.print("How many received charaters? ");
		Serial.println(receivedNumChar);
		Serial.println();

	} // Close if.

	int msgSize = (receivedNumChar * pixelPerChar);			// Calculate message length.
	int scrollingMax = (msgSize);                           // Adjust displacement for message length.

	if (!debug == true) {

		Serial.print("What size is scrolling max? ");
		Serial.println(scrollingMax);
		Serial.println();

	} // Close if.

	while (x > -scrollingMax) {                             // Only display text for one pass

		matrix.fillScreen(0);
		matrix.setCursor(x, 0);
		matrix.setTextColor(colors[colorSet]);
		matrix.print(receivedChars);

		if (--x < -scrollingMax)
		{
			x = matrix.width();
		}
		matrix.show();
		delay(speedSet);

	} // Close while.

	// Clear the software serial buffer.

	while (s1Serial.available() > 0) {
		s1Serial.read();

		if (!debug == true) {

			Serial.println();
			Serial.println("Clearing software serial buffer...");

		} // Close if.

	} // Close while

	// Clear the character array.

	for (byte i = 0; i <= numChars; i++) {
		receivedChars[i] = 0;

		if (!debug == true) {
			Serial.println();
			Serial.println("Clearing character array...");

		} // Close if.

	} // Close for.

	Serial.println();
	Serial.println("Ready.");
	Serial.println();

	// Reset width, menu, received # characters and new data flags.

	x = matrix.width();

	receivedNumChar = 0;
	menu = 0;

} // Close function.

void displayCurrentAlarmOne() {

	rtc.getA1Time(alarmOneDowSet, alarmOneHourSet, alarmOneMinSet, alarmOneSecSet, alarmBits, alarmDy, alarmH12, alarmPm);

	if (debug == true) {

		Serial.println();

		if (alarmDy) {
			Serial.print("DoW: ");
		}
		else {
			Serial.print("Date: ");
		}
		Serial.print(alarmOneDowSet, DEC);

		Serial.print(" ");
		Serial.print("Alarm One Set To: ");
		Serial.print(alarmOneHourSet, DEC);
		Serial.print(':');
		Serial.print(alarmOneMinSet, DEC);
		Serial.print(':');
		Serial.print(alarmOneSecSet, DEC);
		Serial.print(' ');

		/*		if (alarmH12) {
					if (alarmPm) {
						Serial.print("pm ");
					}
					else {
						Serial.print("am ");
					}
				}
		*/

		if (rtc.checkAlarmEnabled(1)) {
			Serial.print("Alarm is enabled");
		}

		else {
			Serial.print("Alarm is disabled");
		}
		Serial.println();
	}

	Serial.println();

} // Close function.

void resetAllSettings() {

	// Set date / time and Send to RTC module.

	rtc.setYear(21);
	rtc.setMonth(01);
	rtc.setDate(01);
	rtc.setDoW(5);
	rtc.setHour(0);
	rtc.setMinute(0);
	rtc.setSecond(0);

	rtc.setA1Time(1, 0, 0, 0, ALRM1_MATCH_HR_MIN_SEC, false, false, false);	// Set alarm and send to RTC module.

	EEPROM.update(ee1224Address, 0);			// Record the 12 / 24 hour clock setting into EEPROM.
	
	EEPROM.update(eeBrightAddress, 5);			// Record brightness setting into EEPROM.

	EEPROM.update(eeColAddress, 6);				// Record brightness setting into EEPROM.

	EEPROM.update(eeSpeedAddress, 45);			// Record speed setting into EEPROM.

	EEPROM.update(eeAlarmOneSchAddress, 0);		// Record alarm one schedule setting into EEPROM.

	EEPROM.update(eeSleepSetAddress, 10);		// Record sleep setting into EEPROM.

	EEPROM.update(eeMusicAddress, 0);			// Record music setting into EEPROM.

	EEPROM.update(eeRTCResetAddress, 0);		// Record RTC reset setting back into EEPROM.
	eeRTCResetChange = false;
	resetRTC = false;

}

Schematics

Printed Circuit Board
This is my bespoke printed circuit board
swear_box_for_nano_every_v2_bi4YZoLPnm.pcb

Comments

Similar projects you might like

Complete Digital Clock Including Alarm and Motion Sensor

Project showcase by LAGSILVA

  • 31,590 views
  • 37 comments
  • 97 respects

Arduino Based Digital Alarm Clock

Project showcase by FANUEL_CONRAD

  • 4,134 views
  • 0 comments
  • 5 respects

How to Make Analog Clock & Digital clock with Led Strip

Project tutorial by DKARDU

  • 4,973 views
  • 0 comments
  • 9 respects

Simple Arduino Digital Clock Without RTC

Project in progress by Annlee Fores

  • 165,054 views
  • 40 comments
  • 155 respects

LCD Alarm Clock with many faces

Project tutorial by John Bradnam

  • 10,097 views
  • 18 comments
  • 24 respects

Remote Controlled Alarm Clock

Project showcase by Robin The Tactician

  • 3,852 views
  • 0 comments
  • 5 respects
Add projectSign up / Login