#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <SPI.h>
#include "RTClib.h"
#define SCREEN_WIDTH 128 // Display length of OLED in pixels
#define SCREEN_HEIGHT 64 // Display width of OLED in pixels
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define BUTTON_PIN 19
#define SPEAKER_PIN A3
#define SENSOR_PIN A4
#define RED_LED 4
#define BLUE_LED 5
#define YELLOW_LED 6
#define BETA 3950
RTC_DS1307 rtc;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
bool Analogue = false; //variables for converting between clocks
bool Digital = false;
//variables for debouncing switch
unsigned long buttonPressed;
unsigned long buttonReleased;
unsigned long buttonChange = 0;
const int debounceTime = 15;
//Variables for Analogue clock display
int CenterX = 64;
int CenterY = 32;
int Radius = 25;
float EndX;
float EndY;
//variables for stopwatch
bool changeToStopwatch = false;
bool stopwatchRunning = false;
bool alarmSetUp = false;
DateTime stopwatchTime;
TimeSpan savedTime; //Elapsed time from the pause of the stopwatch.
TimeSpan elapsedTime; //Elapsed time.
//variables for ALARM
int alarmHour;
int alarmMinute;
//variables for temperature display
bool displayTemp = false;
float celsius;
float fahrenheit;
float tempData;
enum state{
CLOCK,
STOPWATCH,
ALARM
};
state Mode = CLOCK;
enum alarmState{
SET_RESET,
SETHOUR,
SETMINUTE
};
alarmState currentState = SETHOUR;
void setup() {
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(SENSOR_PIN, INPUT);
pinMode(RED_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
while (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println("Display not connected!");
} //Checks if OLED is properly set up
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
} //Checks if RTC is properly set up
display.clearDisplay();
Serial.println("Analogue or Digital clock? A/D:");
while (Serial.available() == 0){}
char choice;
choice = Serial.read();
if (choice == 'A'){
Analogue = true;
}
if (choice == 'D'){
Digital = true;
}
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), pressed , LOW);
DateTime alarmSetTime = rtc.now() + TimeSpan(0,0,1,0);
alarmHour = alarmSetTime.hour();
alarmMinute = alarmSetTime.minute();
}
void loop() {
display.clearDisplay();
int hours;
int minutes;
int seconds;
DateTime now = rtc.now();
//Checking for the state of display (clock or stopwatch).
switch (Mode){
case CLOCK:{
hours = (now.hour());
minutes = (now.minute());
seconds = (now.second());
}
break;
case STOPWATCH:{
if (!stopwatchRunning){
stopwatchTime = now; //Setting the time difference to zero to stop the stopwatch.
}
elapsedTime = now - stopwatchTime + savedTime;
hours = (elapsedTime.hours());
minutes = (elapsedTime.minutes());
seconds = (elapsedTime.seconds());
}
break;
case ALARM:{
hours = alarmHour;
minutes = alarmMinute;
seconds = 0;
}
break;
}
if (alarmSetUp && alarmHour == now.hour() && alarmMinute == now.minute()){
tone(SPEAKER_PIN, 500, 250);
}
//Displaying either the clock or the stopwatch on analogue or digital display.
if (Analogue){
analogClock(hours, minutes, seconds);
}
else if (Digital){
digitalClock(hours, minutes, seconds);
}
if (alarmSetUp){
showAlarmText();
}
if (displayTemp){
displayTemperature();
}
else {
resetLEDs();
}
display.display();
}
void digitalClock(int hours, int minutes, int seconds){
display.setTextSize(2.5);
display.setTextColor(SSD1306_WHITE);
if (Mode != ALARM ){
display.setCursor(18,22);
char buff[9];
sprintf(buff,"%02d:%02d:%02d",hours ,minutes, seconds); //Formatting of the display to include two significant figues for the time.
buff[8] = '\0';
display.print(buff);
}
else {
display.setCursor(30,22);
char buff[6];
sprintf(buff, "%02d:%02d",hours ,minutes);
display.print(buff);
switch (currentState){
case SETHOUR:{
display.setTextSize(1.5);
display.setCursor(0,50);
display.print("Setting up alarm Hour");
}
break;
case SETMINUTE:{
display.setTextSize(1.5);
display.setCursor(0,50);
display.print("Setting up alarm Mins");
}
break;
}
}
}
void analogClock(int hours, int minutes, int seconds){
display.drawCircle(CenterX, CenterY, Radius, WHITE);
display.drawCircle(CenterX, CenterY, Radius+3, WHITE);
drawHour(hours, minutes);
drawMinute(minutes);
drawSeconds(seconds);
}
void drawHour(float hour, float mins){
float total = (hour+(mins/60));
float hoursAngle = (total*(360/12));
EndX = CenterX+(10*sin(hoursAngle*0.017453));
EndY = CenterY-(10*cos(hoursAngle*0.017453));
display.drawLine(CenterX, CenterY, EndX, EndY, WHITE);
}
void drawMinute(float min){
float minsAngle = (min*(360/60));
EndX = CenterX+(20*sin(minsAngle*0.017453));
EndY = CenterY-(20*cos(minsAngle*0.017453));
display.drawLine(EndX, EndY, CenterX, CenterY, WHITE);
}
void drawSeconds(float seconds){
float secsAngle = (seconds*(360/60));
EndX = CenterX+(22*sin(secsAngle*0.017453));
EndY = CenterY-(22*cos(secsAngle*0.017453));
display.drawLine(EndX, EndY, CenterX, CenterY, WHITE);
}
void pressed(){
if (debounceTime + buttonChange > millis()){ //Debouncing the switch.
return;
}
buttonPressed = millis();
buttonChange = millis();
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), released, HIGH);
}
void released(){
if (debounceTime + buttonChange > millis()){ //Debouncing the switch.
return;
}
buttonReleased = millis();
if ((buttonReleased - buttonPressed) >= 8000){
displayTemp = !displayTemp;
}
else if ((buttonReleased - buttonPressed) >= 5000){ //Checks if the button was pressed for longer than three seconds to change between clock and stopwatch.
if (Mode == CLOCK){
Mode = STOPWATCH;
}
else if (Mode == STOPWATCH){
Mode = ALARM;
}
else {
Mode = CLOCK;
}
stopwatchRunning = false;
savedTime = 0; //Resets the stopwatch time.
}
else if ((buttonReleased - buttonPressed) >= 3000 && Mode == ALARM){
switch (currentState){
case SET_RESET:
currentState = SETHOUR;
break;
case SETHOUR:
currentState = SETMINUTE;
break;
default:
currentState = SET_RESET;
break;
}
}
else{ //checks for stop button presses.
if (Mode == STOPWATCH){
if (stopwatchRunning){ //Saves the time if the stopwatch is paused.
savedTime = elapsedTime;
}
stopwatchRunning = !(stopwatchRunning); //toggles the state of stopwatch.
}
else if (Mode == ALARM){
switch (currentState){
case SET_RESET:{
alarmSetUp = !(alarmSetUp);
}
break;
case SETHOUR:{
alarmHour = (alarmHour + 1) % 24;
}
break;
case SETMINUTE:{
alarmMinute = (alarmMinute + 1) % 60;
}
break;
}
}
}
buttonChange = millis();
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), pressed, LOW);
}
void showAlarmText(){
display.setTextSize(1.0);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,55);
display.print("ALARM SET UP");
// display.display();
}
void displayTemperature(){
display.setTextSize(1.5);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
tempData = analogRead(SENSOR_PIN);
celsius = 1 / (log(1 / (1023. / tempData - 1)) / BETA + 1.0 / 298.15) - 273.15;
fahrenheit = (celsius*1.8)+32;
String tempDisplayText = (String(celsius, 2) + " C" + " " + String(fahrenheit, 2) + " F");
display.print(tempDisplayText);
digitalWrite(RED_LED, celsius > 40);
digitalWrite(BLUE_LED, celsius > 0 && celsius <= 40);
digitalWrite(YELLOW_LED, celsius <= 0);
}
void resetLEDs(){
digitalWrite(RED_LED, LOW);
digitalWrite(BLUE_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
}