#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
RTC_DS1307 rtc;
Adafruit_SSD1306 Oled = Adafruit_SSD1306(128, 64, &Wire);
const float val_pi = 3.14159267 ;
const int center_of_clock_x_axis = 64; // center of oled
const int center_of_clock_y_axis = 32; // center of oled
int o = 1;
// variables used to calculate coordinates of points on the circle
int x;
int y;
int z;
int b;
// variables to store previous values read off RTC module
int seconds = 0;
int minutes;
int hours;
String current_mins = "";
String current_hours = "";
String current_secs = "";
String current_time = "";
int c_mins = 0;
int c_hours = 0;
int c_secs = 0;
void setup() {
Serial.begin(9600);
if (!Oled.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
// we set the time here from serial
char buf[6];
char tmp;
int cnt = 0;
int h, m, s;
Serial.print("Enter time in 24-hour format [hhmmss]: ");
while (cnt < 6) // we will keep here until all hours minutes and seconds have been set from serial
{
while (Serial.available() == 0) {};
tmp = Serial.read();
if ((tmp >= '0') and (tmp <= '9'))
{
buf[cnt] = tmp;
cnt++;
Serial.print(tmp);
}
}
Serial.println();
// these following conditios stop us from ebtering invalid time
h = ((buf[0] - '0') * 10) + (buf[1] - '0');
m = ((buf[2] - '0') * 10) + (buf[3] - '0');
s = ((buf[4] - '0') * 10) + (buf[5] - '0');
if ((h > 23) or (m > 59) or (s > 59))
{
Serial.println("ERROR: Invalid time");
return;
}
else
{
Serial.println(h);
Serial.println(m);
Serial.println(s);
Serial.print("time set to ");
// simple conversions of time to display on serial monitors
if (h < 10)
Serial.print("0");
Serial.print(h, DEC);
Serial.print(":");
if (m < 10)
Serial.print("0");
Serial.print(m, DEC);
Serial.print(":");
if (s < 10)
Serial.print("0");
Serial.print(s, DEC);
Serial.println("...");
}
rtc.adjust(DateTime(2022, 9, 10, h, m, s)); // set the time using builtint library fucntion
Oled.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
Oled.clearDisplay();
face_clock(); // fucntion that we used to make clock face
Oled.display();
}
void draw_second_hand(int second, int mode)
{
y = (24 * cos(val_pi - (2 * val_pi) / 60 * second)) + center_of_clock_y_axis;
x = (24 * sin(val_pi - (2 * val_pi) / 60 * second)) + center_of_clock_x_axis;
if (mode == 1) Oled.drawCircle(x, y, 2, SSD1306_WHITE);
else Oled.drawCircle(x, y, 2, SSD1306_BLACK);
}
void draw_hour_hand(int hour, int minute, int mode)
{
// calculations got from internet to make an hour hand
y = (18 * cos(val_pi - (2 * val_pi) / 12 * hour - (2 * val_pi) / 720 * minute)) + center_of_clock_y_axis;
x = (18 * sin(val_pi - (2 * val_pi) / 12 * hour - (2 * val_pi) / 720 * minute)) + center_of_clock_x_axis;
b = (18 * cos(val_pi - (2 * val_pi) / 12 * hour - (2 * val_pi) / 720 * minute)) + center_of_clock_y_axis + 1;
z = (18 * sin(val_pi - (2 * val_pi) / 12 * hour - (2 * val_pi) / 720 * minute)) + center_of_clock_x_axis + 1;
if (mode == 1) {
Oled.drawLine(center_of_clock_x_axis, center_of_clock_y_axis, x, y, SSD1306_WHITE);
Oled.drawLine(center_of_clock_x_axis + 1, center_of_clock_y_axis + 1, z, b, SSD1306_WHITE);
}
else {
Oled.drawLine(center_of_clock_x_axis, center_of_clock_y_axis, x, y, SSD1306_BLACK);
Oled.drawLine(center_of_clock_x_axis + 1, center_of_clock_y_axis + 1, z, b, SSD1306_BLACK);
}
}
void draw_minute_hand(int minute, int mode)
{
// calculations got from internet to make an minute hand
y = (24 * cos(val_pi - (2 * val_pi) / 60 * minute)) + center_of_clock_y_axis;
x = (24 * sin(val_pi - (2 * val_pi) / 60 * minute)) + center_of_clock_x_axis;
if (mode == 1)Oled.drawLine(center_of_clock_x_axis, center_of_clock_y_axis, x, y, SSD1306_WHITE); else Oled.drawLine(center_of_clock_x_axis, center_of_clock_y_axis, x, y, SSD1306_BLACK);
}
void face_clock(void)
{
// draw the center of the clock
Oled.drawCircle(center_of_clock_x_axis, center_of_clock_y_axis, 3, SSD1306_WHITE);
Oled.fillCircle(center_of_clock_x_axis, center_of_clock_y_axis, 3, SSD1306_WHITE);
// draw hour pointers around the face of a clock
for (int i = 0; i < 12; i++) {
y = (32 * cos(val_pi - (2 * val_pi) / 12 * i)) + center_of_clock_y_axis;
x = (32 * sin(val_pi - (2 * val_pi) / 12 * i)) + center_of_clock_x_axis;
b = (28 * cos(val_pi - (2 * val_pi) / 12 * i)) + center_of_clock_y_axis;
z = (28 * sin(val_pi - (2 * val_pi) / 12 * i)) + center_of_clock_x_axis;
Oled.drawLine(z, b, x, y, SSD1306_WHITE);
}
// print string "12" at the top of the face of the clock
Oled.drawCircle(26 * sin(val_pi) + center_of_clock_x_axis, (26 * cos(val_pi)) + center_of_clock_y_axis, 6, SSD1306_BLACK);
Oled.fillCircle(26 * sin(val_pi) + center_of_clock_x_axis, (26 * cos(val_pi)) + center_of_clock_y_axis, 5, SSD1306_BLACK);
Oled.setTextSize(1); // Normal 1:1 val_pixel scale
Oled.setTextColor(SSD1306_WHITE); // Draw white text
Oled.setCursor(center_of_clock_x_axis - 3, 0); // Start at top-left corner
Oled.println(F("12"));
}
void draw_face_clock_reset(void)
{
Oled.drawCircle(center_of_clock_x_axis, center_of_clock_y_axis, 3, SSD1306_WHITE);
Oled.fillCircle(center_of_clock_x_axis, center_of_clock_y_axis, 3, SSD1306_WHITE);
Oled.setCursor(center_of_clock_x_axis - 3, 0);
Oled.println(F("12"));
}
void loop()
{
// display.ClearDisplay();
// Oled.clearDisplay();
DateTime now = rtc.now();
// Oled.display();
Serial.println(current_time);
// delay(1000);
char buf1[] = "hh";
char buf2[] = "mm";
char buf3[] = "ss";
current_hours = now.toString(buf1);
current_mins = now.toString(buf2);
current_secs = now.toString(buf3);
c_mins = current_mins.toInt(); // current mins from rtc
c_hours = current_hours.toInt() ; // current hours from rtc
c_secs = current_secs.toInt(); // current secs from rtc
if (c_secs != seconds) // make oled display seconds hand moving by clearing and displaying simultaneously
{
Oled.clearDisplay();
Oled.setTextSize(0.5);
Oled.setTextColor(WHITE);
Oled.setCursor(0, 0);
char buffe[] = "hh:mm";
current_time = now.toString(buffe);
Oled.print(current_time);
face_clock();
draw_face_clock_reset();
draw_second_hand(c_secs, 0);
draw_minute_hand(c_mins, 0);
draw_hour_hand(c_hours, c_mins, 0);
draw_second_hand(c_secs, 1);
draw_minute_hand(c_mins, 1);
draw_hour_hand(c_hours, c_mins, 1);
seconds = c_secs;
minutes = c_mins;
hours = c_hours;
Oled.display();
}
}