Header and sketch


The following ZIP archive contains the Arduino Sketch folder ueko-wecker-180325 with the files

  • parameterset4clock1.h
  • ueko-wecker-180325.ino
Download
ueko-wecker-180325.zip
Komprimiertes Archiv im ZIP Format 4.1 KB

parameterset4clock1.h

const int MIN_C=0, MAX_C=15 ;  // Clock Display Brightness Range (from MIN 0 to MAX 15)
const int MIN_A=0, MAX_A=15;   // Alarm Display Brightness Range (from MIN 0 to MAX 15) 
const int MIN_V=5, MAX_V=20;   // Volume Range (from MIN 0 to MAX 30)
const int MINUTE_STEP_WIDTH=1; // Working values are 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 or 30

ueko-wecker-180325.ino

/*  UEBERKOPF-WECKER (Overhead-Alarm-Clock)
    03/25/2018 - Kurt Andro - https://www.ideenzumnulltarif.de/ideen/ueberkopf-wecker/

    Hardware
    - 1 Arduino Mega 2560 R3
    - 1 Adafruit DS3231 Precision RTC Breakout
    - 1 Adafruit 1.2" 4-Digit-7-Segment-Display with I2C-Backpack red for showing the current time
    - 1 Adafruit 1.2" 4-Digit-7-Segment-Display with I2C-Backpack yellow for showing the alarm time
    - 2 switches (clock run, clock set & alarm off, alarm on, alarm set)
    - 4 push buttons (-/+ hour, -/+ minute) for adjusting the current time
    - 4 push buttons (-/+ hour, -/+ minute) for adjusting the alarm time
    - 3 potentiometers for setting the brightness of the 2 displays and the volume of the mp3 file
    - 1 DFPlayer Mini for playing the alarmsound "0001.mp3" from its SD Card
    - 1 speaker for the alarm sound
    - 1 2-channel relay-module (only one channel used)
    - 1 Adafruit I2C FRAM Breakout for storing the alarm time (I didn't like to use eeprom)
    - 1 power supply unit
    - 1 power bank (optional) for electricity failures
    - 1 box with a front plate for all the stuff above */

#include <Wire.h>                                 // For communication with I2C devices
#include <RTClib.h>                               // For the real time clock
#include <Adafruit_GFX.h>                         // For the displays
#include "Adafruit_LEDBackpack.h"                 // For the displays
#include "SoftwareSerial.h"                       // For the DFPlayer
#include "DFRobotDFPlayerMini.h"                  // -
#include "Adafruit_FRAM_I2C.h"                    // For the FRAM module
#include "parameterset4clock1.h"                  // Parameters for Clock No. x

RTC_DS3231 rtc;                                   // Create real time clock object
Adafruit_7segment clockdisp=Adafruit_7segment();  // Create clock display object
Adafruit_7segment alarmdisp=Adafruit_7segment();  // Create alarm display object
SoftwareSerial mySoftwareSerial(10, 11);          // Create DFPlayer communication object (RX, TX)
DFRobotDFPlayerMini myDFPlayer;                   // Create DFPlayer object
Adafruit_FRAM_I2C fram     = Adafruit_FRAM_I2C(); // Create FRAM object

const int POT_THRESHOLD=24;                       // Avoid display flickering and volume leaps
const int MP3_DELAY_1=125, MP3_DELAY_2=75;        // Delay 1: Time (ms) before start of MP3-File / Delay 2: Time (ms) after start of MP3-File
const unsigned long DEBOUNCE_CYCLES=50UL;         // Makes sure that push button pressures trigger only one single event

const int PIN_BUSY=12;                                                            // DFPlayer: LOW = audio file playing
const int PIN_CLOCK_SET=31;                                                       // Clock switch
const int PIN_CL_HR_DEC=33, PIN_CL_HR_INC=35, PIN_CL_MN_DEC=37, PIN_CL_MN_INC=39; // Clock buttons
const int PIN_ALARM_ON=41, PIN_ALARM_SET=43;                                      // Alarm switch
const int PIN_AL_HR_DEC=45, PIN_AL_HR_INC=47, PIN_AL_MN_DEC=49, PIN_AL_MN_INC=51; // Alarm buttons
const int PIN_CLOCK_POT=A0, PIN_ALARM_POT=A1, PIN_VOLUME_POT=A2;                  // Potentiometers
const int PIN_RELAY_1=8;                                                          // Switch relay no. 1 to connect the speaker to the DFPlayer

bool clockSet=false, alarmSet=false, alarmOn=false;                               // Input from switches
bool clockHrDec=false, clockHrInc=false, clockMnDec=false, clockMnInc=false;      // Input from clock push buttons
bool alarmHrDec=false, alarmHrInc=false, alarmMnDec=false, alarmMnInc=false;      // Input from alarm push buttons
bool audioNotPlaying=true;                                                        // Flag: is the mp3 file being played?

int clockPotNew=0, clockPotOld=0, alarmPotNew=0, alarmPotOld=0;                   // Input from display brightness potentiometers
int volume=0, volumePotNew=0, volumePotOld=0;                                     // Volume value & input from volume potentiometer
int clockHr=0, clockMn=0, clockSc=0, alarmHr=0, alarmMn=0;                        // Time values for displays

uint8_t framHr=0, framMn=0; bool framIsUpToDate=true;                             // fram variables

unsigned long iClHrDec=0UL, iClHrInc=0UL, iClMnDec=0UL, iClMnInc=0UL;             // Counters for push button debouncing
unsigned long iAlHrDec=0UL, iAlHrInc=0UL, iAlMnDec=0UL, iAlMnInc=0UL;             // -

uint8_t bitmask=0;                                                                // For leading zero suppression

void setClockBrightness();                                                        // Declare procedures
void setAlarmBrightness();                                                        // -
void setVolume();                                                                 // -
void writeClockDisplay();                                                         // -
void writeAlarmDisplay();                                                         // -
void writeClockSecondsToAlarmDisplay();                                           // -
void clearClockDisplay();                                                         // -
void clearAlarmDisplay();                                                         // -

void setup() {
  pinMode(PIN_CLOCK_SET, INPUT); pinMode(PIN_ALARM_SET, INPUT); pinMode(PIN_ALARM_ON, INPUT); pinMode(PIN_BUSY, INPUT); pinMode(PIN_RELAY_1, OUTPUT);
  pinMode(PIN_CL_HR_DEC, INPUT); pinMode(PIN_CL_HR_INC, INPUT); pinMode(PIN_CL_MN_DEC, INPUT); pinMode(PIN_CL_MN_INC, INPUT);
  pinMode(PIN_AL_HR_DEC, INPUT); pinMode(PIN_AL_HR_INC, INPUT); pinMode(PIN_AL_MN_DEC, INPUT); pinMode(PIN_AL_MN_INC, INPUT);

  digitalWrite(PIN_RELAY_1, HIGH);  // Disconnect the speaker
  
  clockdisp.begin(0x70); alarmdisp.begin(0x71); clearClockDisplay(); clearAlarmDisplay(); // Initialise and clear the displays
  clockPotNew=analogRead(PIN_CLOCK_POT); clockPotOld=clockPotNew; setClockBrightness();   // Read clock potentiometer and set brightness
  alarmPotNew=analogRead(PIN_ALARM_POT); alarmPotOld=alarmPotNew; setAlarmBrightness();   // Read alarm potentiometer and set brightness

  mySoftwareSerial.begin(9600); myDFPlayer.begin(mySoftwareSerial);   // Initialise MP3-Module
  volumePotNew=analogRead(PIN_VOLUME_POT); volumePotOld=volumePotNew; // Read volume potentiometer
  setVolume(); myDFPlayer.volume(volume);                             // Set volume
  
  fram.begin();                                     // Initialise FRAM-Module
  framHr=fram.read8(0x0); framMn=fram.read8(0x10);  // Read alarm time
  if (framHr<24 && framMn<60) {                     // Check if there are invalid values
    alarmHr=framHr; alarmMn=framMn;                 // Write to alarm hour and alarm minute variables
  } else {
    alarmHr=15; alarmMn=30;                         // Write 15:30 as kind of error message if there are no valid values
  }
  clockdisp.drawColon(true);

  DateTime now = rtc.now(); clockHr=now.hour(); clockMn=now.minute(); // Read time from real time clock (rtc)
  alarmOn=digitalRead(PIN_ALARM_ON);
  if(alarmOn==true && clockHr==alarmHr && clockMn==alarmMn) {         // Check if alarm should sound
    digitalWrite(PIN_RELAY_1, LOW);                                   // Connect speaker to mp3-module
    delay(MP3_DELAY_1); myDFPlayer.play(1); delay(MP3_DELAY_2);       // Play mp3-file
  }
}

void loop() {
  // Adjust display brightness and speaker volume
  clockPotNew=analogRead(PIN_CLOCK_POT);
  if(clockPotNew>clockPotOld+POT_THRESHOLD || clockPotNew<clockPotOld-POT_THRESHOLD) {setClockBrightness();}
  alarmPotNew=analogRead(PIN_ALARM_POT);
  if(alarmPotNew>alarmPotOld+POT_THRESHOLD || alarmPotNew<alarmPotOld-POT_THRESHOLD) {setAlarmBrightness();}
  volumePotNew=analogRead(PIN_VOLUME_POT);
  if(volumePotNew>volumePotOld+POT_THRESHOLD || volumePotNew<volumePotOld-POT_THRESHOLD) { setVolume(); myDFPlayer.volume(volume); }

  DateTime now = rtc.now(); clockHr=now.hour(); clockMn=now.minute(); clockSc=now.second(); // Read time from real time clock (rtc)

  clockSet=digitalRead(PIN_CLOCK_SET);
  if (clockSet==false) {        // Clock: Run mode
    clockdisp.blinkRate(0);
  }
  else {                        // Clock: Set mode
    if (clockHrDec==HIGH || clockHrInc==HIGH || clockMnDec==HIGH || clockMnInc==HIGH) { clockdisp.blinkRate(0); } else { clockdisp.blinkRate(1); }
    { // Clock: decrease hours
      clockHrDec=digitalRead(PIN_CL_HR_DEC);
      if(clockHrDec==HIGH && iClHrDec==0UL) {
        iClHrDec++;
        if(clockHr==0) {clockHr=23;}
        else           {clockHr--; }
        rtc.adjust(DateTime(2018, 1, 1, clockHr, clockMn, 0));
      }
      if(clockHrDec==HIGH && iClHrDec!=0UL) {iClHrDec++;}
      if(iClHrDec>DEBOUNCE_CYCLES || clockHrDec==LOW) {iClHrDec=0UL;}
    }
    { // Clock: increase hours
      clockHrInc=digitalRead(PIN_CL_HR_INC);
      if(clockHrInc==HIGH && iClHrInc==0UL) {
        iClHrInc++;
        if(clockHr==23) {clockHr=0;}
        else            {clockHr++;}
        rtc.adjust(DateTime(2018, 1, 1, clockHr, clockMn, 0));
      }
      if(clockHrInc==HIGH && iClHrInc!=0UL) {iClHrInc++;}
      if(iClHrInc>DEBOUNCE_CYCLES || clockHrInc==LOW) {iClHrInc=0UL;}
    }
    { // Clock: decrease minutes
      clockMnDec=digitalRead(PIN_CL_MN_DEC);
      if(clockMnDec==HIGH && iClMnDec==0UL) {
        iClMnDec++;
        if(clockMn==0) {
          clockMn=59;
          if(clockHr==0) {clockHr=23;}
          else           {clockHr--; }
        }
        else           {clockMn--; }
        rtc.adjust(DateTime(2018, 1, 1, clockHr, clockMn, 0));
      }
      if(clockMnDec==HIGH && iClMnDec!=0UL) {iClMnDec++;}
      if(iClMnDec>DEBOUNCE_CYCLES || clockMnDec==LOW) {iClMnDec=0UL;}
    }
    { // Clock: increase minutes
      clockMnInc=digitalRead(PIN_CL_MN_INC);
      if(clockMnInc==HIGH && iClMnInc==0UL) {
        iClMnInc++;
        if(clockMn==59) {
          clockMn=0;
          if(clockHr==23) {clockHr=0;}
          else            {clockHr++;}
        }
        else            {clockMn++;}
        rtc.adjust(DateTime(2018, 1, 1, clockHr, clockMn, 0));
      }
      if(clockMnInc==HIGH && iClMnInc!=0UL) {iClMnInc++;}
      if(iClMnInc>DEBOUNCE_CYCLES || clockMnInc==LOW) {iClMnInc=0UL;}
    }
    writeClockSecondsToAlarmDisplay();
  }
  writeClockDisplay();
 
  alarmOn=digitalRead(PIN_ALARM_ON);
  alarmSet=digitalRead(PIN_ALARM_SET);
  if (alarmOn==true && clockSet==false) {       // Alarm: On mode
    alarmdisp.blinkRate(0); alarmdisp.drawColon(true); writeAlarmDisplay();
    if (framIsUpToDate==false) {
      fram.write8(0x0, byte(alarmHr)); fram.write8(0x10, byte(alarmMn)); framIsUpToDate=true; // Update FRAM
      framHr=fram.read8(0x0); framMn=fram.read8(0x10);
    }
  }
  else if (alarmSet==true && clockSet==false) { // Alarm: Set mode
    alarmdisp.drawColon(true);
    if (alarmHrDec==HIGH || alarmHrInc==HIGH || alarmMnDec==HIGH || alarmMnInc==HIGH) { alarmdisp.blinkRate(0); } else { alarmdisp.blinkRate(1); }
    { // Alarm: decrease hours
      alarmHrDec=digitalRead(PIN_AL_HR_DEC);
      if(alarmHrDec==HIGH && iAlHrDec==0UL) {
        iAlHrDec++;
        if(alarmHr==0) {alarmHr=23;}
        else           {alarmHr--;}
        framIsUpToDate=false;
      }
      if(alarmHrDec==HIGH && iAlHrDec!=0UL) {iAlHrDec++;}
      if(iAlHrDec>DEBOUNCE_CYCLES || alarmHrDec==LOW) {iAlHrDec=0UL;}
    }
    { // Alarm: increase hours
      alarmHrInc=digitalRead(PIN_AL_HR_INC);
      if(alarmHrInc==HIGH && iAlHrInc==0UL) {
        iAlHrInc++;
        if(alarmHr==23) {alarmHr=0;}
        else            {alarmHr++;}
        framIsUpToDate=false;
      }
      if(alarmHrInc==HIGH && iAlHrInc!=0UL) {iAlHrInc++;}
      if(iAlHrInc>DEBOUNCE_CYCLES || alarmHrInc==LOW) {iAlHrInc=0UL;}
    }
    { // Alarm: decrease minutes
      alarmMnDec=digitalRead(PIN_AL_MN_DEC);
      if(alarmMnDec==HIGH && iAlMnDec==0UL) {
        iAlMnDec++;
        if(alarmMn==0) {
          alarmMn=60-MINUTE_STEP_WIDTH;
          if(alarmHr==0) {alarmHr=23;}
          else           {alarmHr--; }
        }
        else           {alarmMn-=MINUTE_STEP_WIDTH; }
        framIsUpToDate=false;
      }
      if(alarmMnDec==HIGH && iAlMnDec!=0UL) {iAlMnDec++;}
      if(iAlMnDec>DEBOUNCE_CYCLES || alarmMnDec==LOW) {iAlMnDec=0UL;}
    }
    { // Alarm: increase minutes
      alarmMnInc=digitalRead(PIN_AL_MN_INC);
      if(alarmMnInc==HIGH && iAlMnInc==0UL) {
        iAlMnInc++;
        if(alarmMn==60-MINUTE_STEP_WIDTH) {
          alarmMn=0;
          if(alarmHr==23) {alarmHr=0;}
          else            {alarmHr++;}
        }
        else            {alarmMn+=MINUTE_STEP_WIDTH;}
        framIsUpToDate=false;
      }
      if(alarmMnInc==HIGH && iAlMnInc!=0UL) {iAlMnInc++;}
      if(iAlMnInc>DEBOUNCE_CYCLES || alarmMnInc==LOW) {iAlMnInc=0UL;}
    }
    writeAlarmDisplay();
  }
  else if (clockSet==false) { // Alarm: Off mode
    clearAlarmDisplay();
  }

  audioNotPlaying=digitalRead(PIN_BUSY);
  if(audioNotPlaying==true) {digitalWrite(PIN_RELAY_1, HIGH);}  // Disconnect speaker

  if(alarmOn==true && clockHr==alarmHr && clockMn==alarmMn && clockSc==0 && audioNotPlaying==true) {  // Check if alarm time equals real time
    digitalWrite(PIN_RELAY_1, LOW);                                                                   // Connect speaker
    delay(MP3_DELAY_1); myDFPlayer.play(1); delay(MP3_DELAY_2);                                       // Ring the bell
  }
  if(alarmOn==false) {                              // If switched off while playing
    if(audioNotPlaying==false) {myDFPlayer.stop();  // Stop mp3-file
    digitalWrite(PIN_RELAY_1, HIGH);}               // Disconnect speaker
  }

} // End of loop

void setClockBrightness() { clockPotOld=clockPotNew; clockdisp.setBrightness(map(clockPotNew, 1, 1000, MIN_C, MAX_C)); }
void setAlarmBrightness() { alarmPotOld=alarmPotNew; alarmdisp.setBrightness(map(alarmPotNew, 1, 1000, MIN_A, MAX_A)); }
void setVolume()          { volumePotOld=volumePotNew;              volume = map(volumePotNew, 1, 1000, MIN_V, MAX_V); }

void writeClockDisplay() {
  if(clockHr < 10)                 {clockdisp.writeDigitRaw(0,bitmask); clockdisp.writeDigitNum(1,clockHr);}
  if(clockHr >  9 && clockHr < 20) {clockdisp.writeDigitNum(0,1);       clockdisp.writeDigitNum(1,clockHr-10);}
  if(clockHr > 19)                 {clockdisp.writeDigitNum(0,2);       clockdisp.writeDigitNum(1,clockHr-20);}
  if(clockMn < 10)                 {clockdisp.writeDigitNum(3,0);       clockdisp.writeDigitNum(4,clockMn);}
  if(clockMn >  9 && clockMn < 20) {clockdisp.writeDigitNum(3,1);       clockdisp.writeDigitNum(4,clockMn-10);}
  if(clockMn > 19 && clockMn < 30) {clockdisp.writeDigitNum(3,2);       clockdisp.writeDigitNum(4,clockMn-20);}
  if(clockMn > 29 && clockMn < 40) {clockdisp.writeDigitNum(3,3);       clockdisp.writeDigitNum(4,clockMn-30);}
  if(clockMn > 39 && clockMn < 50) {clockdisp.writeDigitNum(3,4);       clockdisp.writeDigitNum(4,clockMn-40);}
  if(clockMn > 49)                 {clockdisp.writeDigitNum(3,5);       clockdisp.writeDigitNum(4,clockMn-50);}
  clockdisp.writeDisplay();
}

void writeAlarmDisplay() {
  if(alarmHr < 10)                 {alarmdisp.writeDigitRaw(0,bitmask); alarmdisp.writeDigitNum(1,alarmHr);}
  if(alarmHr >  9 && alarmHr < 20) {alarmdisp.writeDigitNum(0,1);       alarmdisp.writeDigitNum(1,alarmHr-10);}
  if(alarmHr > 19)                 {alarmdisp.writeDigitNum(0,2);       alarmdisp.writeDigitNum(1,alarmHr-20);}
  if(alarmMn < 10)                 {alarmdisp.writeDigitNum(3,0);       alarmdisp.writeDigitNum(4,alarmMn);}
  if(alarmMn >  9 && alarmMn < 20) {alarmdisp.writeDigitNum(3,1);       alarmdisp.writeDigitNum(4,alarmMn-10);}
  if(alarmMn > 19 && alarmMn < 30) {alarmdisp.writeDigitNum(3,2);       alarmdisp.writeDigitNum(4,alarmMn-20);}
  if(alarmMn > 29 && alarmMn < 40) {alarmdisp.writeDigitNum(3,3);       alarmdisp.writeDigitNum(4,alarmMn-30);}
  if(alarmMn > 39 && alarmMn < 50) {alarmdisp.writeDigitNum(3,4);       alarmdisp.writeDigitNum(4,alarmMn-40);}
  if(alarmMn > 49)                 {alarmdisp.writeDigitNum(3,5);       alarmdisp.writeDigitNum(4,alarmMn-50);}
  alarmdisp.writeDisplay();
}

void writeClockSecondsToAlarmDisplay() {
  if(clockSc<10)            {alarmdisp.writeDigitNum(0,0);       alarmdisp.writeDigitNum(1,clockSc);}
  if(clockSc> 9&clockSc<20) {alarmdisp.writeDigitNum(0,1);       alarmdisp.writeDigitNum(1,clockSc-10);}
  if(clockSc>19&clockSc<30) {alarmdisp.writeDigitNum(0,2);       alarmdisp.writeDigitNum(1,clockSc-20);}
  if(clockSc>29&clockSc<40) {alarmdisp.writeDigitNum(0,3);       alarmdisp.writeDigitNum(1,clockSc-30);}
  if(clockSc>39&clockSc<50) {alarmdisp.writeDigitNum(0,4);       alarmdisp.writeDigitNum(1,clockSc-40);}
  if(clockSc>49)            {alarmdisp.writeDigitNum(0,5);       alarmdisp.writeDigitNum(1,clockSc-50);}
  alarmdisp.blinkRate(0); alarmdisp.drawColon(false);
  alarmdisp.writeDigitRaw(3,bitmask); alarmdisp.writeDigitRaw(4,bitmask);
  alarmdisp.writeDisplay();
}

void clearClockDisplay() {
  clockdisp.blinkRate(0); clockdisp.drawColon(false);
  clockdisp.writeDigitRaw(0,bitmask); clockdisp.writeDigitRaw(1,bitmask);
  clockdisp.writeDigitRaw(3,bitmask); clockdisp.writeDigitRaw(4,bitmask);
  clockdisp.writeDisplay();
}

void clearAlarmDisplay() {
  alarmdisp.blinkRate(0); alarmdisp.drawColon(false);
  alarmdisp.writeDigitRaw(0,bitmask); alarmdisp.writeDigitRaw(1,bitmask);
  alarmdisp.writeDigitRaw(3,bitmask); alarmdisp.writeDigitRaw(4,bitmask);
  alarmdisp.writeDisplay();
}