// Andy Pham 103357275
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const float pi = 3.14159267 ;
const int clock_center_x=36;
const int clock_center_y=32;
int o=1;
// variables used to calculate coordinates of points on the circle
int x;
int y;
int x1;
int y1;
// variables for clock time
int clkSeconds= 0;
int clkMinutes= 0;
int clkHours= 0;
// true = clock, false = stopwatch
volatile int clkMode = 0;
// stopwatch variables
int stpSeconds = 0;
int stpMinutes = 0;
int stpHours = 0;
int btnPin = 2;
// used to check how long the btn was held
volatile int holdTime = 0;
volatile bool stopwatchOn = false;
volatile bool holding = false;
// alarm count till buzzer.
int buzzerPin = 4;
int buzzerCount = 0;
// stopwatch variables
volatile int alrmSeconds = 0;
volatile int alrmMinutes = 0;
volatile int alrmHours = 0;
bool alrmOn = false;
// time for buzzer to turn off, is always 3 ticks before buzzer count untill alrm goes off.
// used to see how long the alarm should be on for
int alrmStopTime = 0;
// Temperature reading things
const int tempPin = A3;
const float BETA = 3950; // should match the Beta Coefficient of the thermistor
// RGB LED pins
const int RPin = 8;
const int GPin = 9;
const int BPin = 10;
// RGB preset colours
const int cold[] = { 20, 191, 254 }; // sky blue
const int warm[] = { 254, 168, 84 }; // orange
const int hot[] = { 254, 40, 77 }; // watermelon red
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
draw_clock_face();
display.display();
// entering the number of clkHours
bool hourAccept = false;
Serial.print("Enter the clkHours (0 - 23): ");
while (hourAccept == false)
{
if (Serial.available() > 0) {
String incomingByte = Serial.readString();
int hourConvert = readingInput(23, incomingByte);
if (hourConvert < 24)
{
clkHours = hourConvert;
hourAccept = true;
Serial.println(clkHours);
}
else
{
Serial.println("try again");
}
}
}
// entering the number of clkMinutes
bool minAccept = false;
Serial.print("Enter the clkMinutes (0 - 59): ");
while (minAccept == false)
{
if (Serial.available() > 0) {
String incomingByte = Serial.readString();
int minConvert = readingInput(59, incomingByte);
if (minConvert < 60)
{
clkMinutes = minConvert;
minAccept = true;
Serial.println(clkMinutes);
}
else
{
Serial.println("try again");
}
}
}
// entering the number of clkSeconds
bool secAccept = false;
Serial.print("Enter the clkSeconds (0 - 59): ");
while (secAccept == false)
{
if (Serial.available() > 0) {
String incomingByte = Serial.readString();
int secConvert = readingInput(59, incomingByte);
if (secConvert < 60)
{
clkSeconds = secConvert;
secAccept = true;
Serial.println(clkSeconds);
}
else
{
Serial.println("try again");
}
}
}
pinMode(btnPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(btnPin), inputCheck, CHANGE);
pinMode(buzzerPin, OUTPUT);
}
// function for checking if the right number was entered
int readingInput(int range, String input)
{
int num = input.toInt();
if ((input != "0\n") && (num == 0)) {
return range + 1; // fail condition
}
else {
if ((num >= 0) && (num <= range)) {
return num;
}
else {
return range + 1; // fail condition
}
}
}
// checks for button release and press, debounced button
void inputCheck()
{
// holding true is when button is pressed, false when released
holding = !holding;
// holding = false is when button is released
// reset hold time
if (holding == true)
{
holdTime = 0;
}
// stops time for stopwatch when in use
if (clkMode == 1 && holding == true)
{
stopwatchOn = !stopwatchOn;
}
// changing alarm increments
if (clkMode == 2 && holding == false && holdTime < 4)
{
if (holdTime < 1)
{
alrmSeconds = alrmSeconds + 10;
}
else if (holdTime < 2)
{
alrmMinutes = alrmMinutes + 1;
}
else // held for 3 ticks
{
alrmHours = alrmHours + 1;
}
// making sure numbers are still in proper time format
if (alrmSeconds > 59)
{
alrmMinutes = 1;
alrmSeconds = alrmSeconds - 60;
}
if (alrmMinutes > 59)
{
alrmHours = 1;
alrmMinutes = alrmMinutes - 60;
}
}
// held for 4 ticks and change display
if (holdTime >= 4)
{
clkMode++;
if (clkMode > 2)
{
clkMode = 0;
}
stopwatchReset();
}
}
// resets all stopwatch times
void stopwatchReset()
{
stpHours = 0;
stpMinutes = 0;
stpSeconds = 0;
}
void loop() {
delay(1000);
display.clearDisplay();
if (clkMode == 0)
{
draw_clock();
}
else if (clkMode == 1)
{
draw_stopwatch();
}
else
{
draw_Alarm();
}
tick();
buzzerCheck();
tempDisplay();
display.display();
}
// increment time by seconds
void tick() {
// incrementing hold time
if (holding == true)
{
holdTime++;
}
// count for to tell how long the buzzer must be on for
buzzerCount++;
// only set new alrmStopTime if buzzer alrm is still counting down
if (alrmOn == false && (alrmHours > 0 || alrmMinutes > 0 || alrmSeconds > 0))
{
alrmStopTime = buzzerCount + 3;
}
// alarm clock ticking
if (alrmSeconds > 0)
{
alrmSeconds--;
}
else
{
if (alrmMinutes > 0)
{
alrmMinutes--;
alrmSeconds = 59;
}
else
{
if (alrmHours > 0)
{
alrmHours--;
alrmMinutes = 59;
alrmSeconds = 59;
}
}
}
clkSeconds++;
if (clkSeconds >= 60)
{
clkSeconds = 0;
clkMinutes++;
if (clkMinutes >= 60)
{
clkMinutes = 0;
clkHours++;
if (clkHours >= 24)
{
clkHours = 0;
}
}
}
// increment only when stopwatch is on
if (stopwatchOn == true)
{
// ticking stopwatch
stpSeconds++;
if (stpSeconds >= 60)
{
stpSeconds = 0;
stpMinutes++;
if (stpMinutes >= 60)
{
stpMinutes = 0;
stpHours++;
if (stpHours >= 24)
{
stpHours = 0;
}
}
}
}
}
// draw clocks
void draw_clock()
{
draw_clock_face();
draw_second(clkSeconds);
draw_minute(clkMinutes);
draw_hour(clkHours,clkMinutes);
redraw_clock_face_elements();
draw_digital();
}
// drawing analog clkSeconds
void draw_second(int second){
y= (24*cos(pi-(2*pi)/60*second))+clock_center_y;
x =(24*sin(pi-(2*pi)/60*second))+clock_center_x;
display.drawCircle(x, y, 2, SSD1306_WHITE);
}
// drawing analog clkHours
void draw_hour(int hour, int minute){
y= (18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y;
x =(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x;
y1=(18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y+1;
x1=(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x+1;
display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE);
display.drawLine(clock_center_x+1,clock_center_y+1,x1,y1,SSD1306_WHITE);
display.setTextColor(SSD1306_WHITE);
}
// drawing analog clkMinutes
void draw_minute(int minute)
{
y= (24*cos(pi-(2*pi)/60*minute))+clock_center_y;
x =(24*sin(pi-(2*pi)/60*minute))+clock_center_x;
display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE);
}
// clock circle frame
void draw_clock_face(void){
// draw the center of the clock
display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
// draw hour pointers around the face of a clock
for (int i=0;i<12;i++){
y= (32*cos(pi-(2*pi)/12*i))+clock_center_y;
x =(32*sin(pi-(2*pi)/12*i))+clock_center_x;
y1= (28*cos(pi-(2*pi)/12*i))+clock_center_y;
x1 =(28*sin(pi-(2*pi)/12*i))+clock_center_x;
display.drawLine(x1,y1,x,y,SSD1306_WHITE);
}
// print string "12" at the top of the face of the clock
display.drawCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 6, SSD1306_BLACK);
display.fillCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 5, SSD1306_BLACK);
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(clock_center_x-3,0); // Start at top-left corner
display.println(F("12"));
}
// redraw clock face elements
void redraw_clock_face_elements(void){
display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.setCursor(clock_center_x-3,0);
display.println(F("12"));
}
// used to display the digital time
void draw_digital() {
display.setCursor(display.width()/2 + 15,display.height()/2);
display.setTextColor(SSD1306_WHITE);
String h = "" + String(clkHours);
String m = "" + String(clkMinutes);
String sec = "" + String(clkSeconds);
if (clkHours < 10)
{
h = "0" + h;
}
if (clkMinutes < 10)
{
m = "0" + m;
}
if (clkSeconds < 10)
{
sec = "0" + sec;
}
String dTime = h + ":" + m + ":" + sec;
display.println(dTime);
}
// used to display the stopWatch time
void draw_stopwatch() {
display.setTextColor(SSD1306_WHITE);
display.setCursor(display.width()/2 - 20,display.height()/2 - 10);
display.println("STOPWATCH");
display.setCursor(display.width()/2 - 15,display.height()/2);
String h = "" + String(stpHours);
String m = "" + String(stpMinutes);
String sec = "" + String(stpSeconds);
if (stpHours < 10)
{
h = "0" + h;
}
if (stpMinutes < 10)
{
m = "0" + m;
}
if (stpSeconds < 10)
{
sec = "0" + sec;
}
String dTime = h + ":" + m + ":" + sec;
display.println(dTime);
}
// alarm count display
void draw_Alarm()
{
display.setTextColor(SSD1306_WHITE);
display.setCursor(display.width()/2 - 20,display.height()/2 - 10);
display.println("Alarm");
display.setCursor(display.width()/2 - 15,display.height()/2);
String h = "" + String(alrmHours);
String m = "" + String(alrmMinutes);
String sec = "" + String(alrmSeconds);
if (stpHours < 10)
{
h = "0" + h;
}
if (stpMinutes < 10)
{
m = "0" + m;
}
if (stpSeconds < 10)
{
sec = "0" + sec;
}
String dTime = h + ":" + m + ":" + sec;
display.println(dTime);
}
// buzzer needed check
void buzzerCheck()
{
// checking that the buzzer should be on
if (alrmHours == 0 && alrmMinutes == 0 && alrmSeconds == 0 && buzzerCount < alrmStopTime)
{
alrmOn = true;
}
if (alrmOn == true)
{
// buzzer will ring for 3 ticks,
// since alrmStopTime should be 3 more than buzzerCount when buzzer activates
if (buzzerCount >= alrmStopTime)
{
noTone(buzzerPin);
alrmOn = false;
}
else // buzzer when finished
{
tone(buzzerPin, 200);
}
}
}
void tempDisplay()
{
int analogValue = analogRead(tempPin);
float celsius = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;
display.setTextColor(SSD1306_WHITE);
display.setCursor(display.width()/2 + 13,display.height() - 16);
display.println("Temp:");
display.setCursor(display.width()/2 + 13,display.height() - 8);
display.println(String(celsius) + " C");
//led display and thresholds
if (celsius < 15) // cold
{
analogWrite(RPin, cold[0]);
analogWrite(GPin, cold[1]);
analogWrite(BPin, cold[2]);
}
else if (celsius > 30) // hot
{
analogWrite(RPin, hot[0]);
analogWrite(GPin, hot[1]);
analogWrite(BPin, hot[2]);
}
else // warm 15 - 30
{
analogWrite(RPin, warm[0]);
analogWrite(GPin, warm[1]);
analogWrite(BPin, warm[2]);
}
}