/*
Forum: https://forum.arduino.cc/t/issue-with-0-96-display-code-issue/1195653
Wokwi: https://wokwi.com/projects/383021035087828993
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.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);
RTC_DS1307 rtc;
DateTime now, prev;
void setup() {
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
for (;;); // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
display.display();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
}
void loop () {
now = rtc.now();
if (now.second() != prev.second()) {
prev = now;
printTimeToSerial();
printTimeToDisplay();
}
}
void printTimeToDisplay() {
char buf[80];
sprintf(buf, " %0.2d.%0.2d.%4d %0.2d:%0.2d:%0.2d",
now.day(), now.month(), now.year(),
now.hour(), now.minute(), now.second()
);
display.clearDisplay();
display.setCursor(0, 2);
display.println(buf);
display.println();
display.println(" Still to go ...");
display.setCursor(0, 30);
display.print(" Days: ");
display.println(daysUntilXmas());
display.print(" or Hours: ");
display.println(hoursUntilXmas());
display.print(" or Minutes: ");
display.println(minutesUntilXmas());
display.print(" or Seconds: ");
display.println(secondsUntilXmas());
display.drawLine(0, 10, display.width(), 10, SSD1306_WHITE);
display.display();
}
void printTimeToSerial() {
char buf[80];
sprintf(buf, "Current time: %0.2d.%0.2d.%4d %0.2d:%0.2d:%0.2d",
now.day(), now.month(), now.year(),
now.hour(), now.minute(), now.second()
);
Serial.println(buf);
Serial.print("Days until Xmas: \t");
Serial.println(daysUntilXmas());
Serial.print("Hours until Xmas:\t");
Serial.println(hoursUntilXmas());
Serial.print("Minutes until Xmas:\t");
Serial.println(minutesUntilXmas());
Serial.print("Seconds until Xmas:\t");
Serial.println(secondsUntilXmas());
}
// "days difference" means "days" not (24 hours per day)!!!
// e.g. on 12/23 there will be "1 day to go" until 23:59:59 o'clock
long daysUntilXmas() {
int XmasYear = now.year();
if (now.month() == 12 && now.day() > 24) {
XmasYear++;
}
return daysDiff(now.year(), now.month(), now.day(),
XmasYear, 12, 24);
}
// Minutes difference based on 12/24 at 0 o'clock in the morning local RTC time
long minutesUntilXmas() {
int XmasYear = now.year();
if (now.month() == 12 && now.day() > 24) {
XmasYear++;
}
return minutesDiff(now.year(), now.month(), now.day(), now.hour(), now.minute(),
XmasYear, 12, 24, 0, 0);
}
// Full hours difference based on minutesUntilXmas
long hoursUntilXmas() {
long minutes = minutesUntilXmas();
return (minutes / 60);
}
// Seconds difference based on minutesUntilXmas() plus rest of recent minute
long secondsUntilXmas() {
long minutes = minutesUntilXmas();
return (60 - now.second() + minutes * 60);
}
//
// Source https://forum.arduino.cc/t/datetime-calculations/354776/16
// "Julian Day Number"
//
long JD(int year, int month, int day)
{ // COMPUTES THE JULIAN DATE (JD) GIVEN A GREGORIAN CALENDAR
return day - 32075 + 1461L * (year + 4800 + (month - 14) / 12) / 4 + 367 * (month - 2 - (month - 14) / 12 * 12) / 12 - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4;
}
long daysDiff(int year1, int mon1, int day1, int year2, int mon2, int day2)
{
return JD(year2, mon2, day2) - JD(year1, mon1, day1);
}
long minutesDiff(int year1, int mon1, int day1, int hour1, int min1, int year2, int mon2, int day2, int hour2, int min2 )
{
int mDiff = (hour2 * 60 + min2) - (hour1 * 60 + min1);
return daysDiff(year1, mon1, day1, year2, mon2, day2) * 1440 + mDiff;
}