Use your idle Arduboy as a digital clock!
(Doesn’t work properly in the emulator, no serial input!)
Although the Arduboy lacks a real time clock, updates are provided via the usb serial port and kept in sync once a minute. (The drift isn’t quite that bad, but it keeps it in check)
It uses the Arduino Time Library:
And uses the processing sketch contained within examples to do the updates.
If you wanted to get serious with it then making an even smaller application that lives in the tray would be a cool upgrade.
Also works nice on the XL
/*
Clock.ino
Demonstrates a clock-like display with a very huge font.
Also shows usage of u8x8_u8toa().
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <TimeLib.h>
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define TIME_HEADER "T" // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 12, /* dc=*/ 4, /* reset=*/ 6); // Arduboy (Production, Kickstarter Edition)
tmElements_t tm;
void setup(void) {
u8g2.begin();
Serial.begin(9600);
blankClockDisplay();
while (!Serial) ; // Needed for Leonardo only
setSyncProvider( requestSync); //set function to call when sync required
Serial.println("Waiting for sync message");
}
uint8_t m = 24;
int tHour, tMin, tSec;
bool PM;
bool flicker;
int dotX = 32;
int startX;
int clockY = 48;
uint8_t syncTimer = 0;
const char monthInWords[13][10] = {" ", "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
void loop(void) {
if (Serial.available()) {
processSyncMessage();
}
if (timeStatus() != timeNotSet) {
//serialClockDisplay();
digitalClockDisplay();
}
else {
blankClockDisplay();
}
syncTimer++;
if (syncTimer > 60) {
requestSync(); // update every minute
syncTimer = 0;
}
delay(1000);
flicker = !flicker;
}
void digitalClockDisplay() {
char m_str[3];
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_logisoso32_tn);
char buf[12];
int fHour;
fHour = hour();
if (hour() > 12) {
fHour -= 12;
PM = true;
}
else if (hour() == 12) {
PM = true;
}
else {
PM = false;
}
if (fHour > 9) {
startX = -7;
}
else {
startX = 16;
}
u8g2.drawStr(startX, clockY, itoa(fHour, buf, 10));
if (flicker) u8g2.drawStr(dotX, clockY, ":");
char m_str[3];
strcpy(m_str, u8x8_u8toa(minute(), 2));
u8g2.drawStr(dotX + 8, clockY, m_str);
u8g2.setFont(u8g2_font_logisoso16_tf );
strcpy(m_str, u8x8_u8toa(second(), 2));
u8g2.drawStr(dotX + 50, clockY, m_str);
if (PM) {
u8g2.drawStr(dotX + 74, clockY, "PM");
}
else {
u8g2.drawStr(dotX + 74, clockY, "AM");
}
u8g2.setFont(u8g2_font_helvB08_tf);
char dayWord[3];
if (day() == 1) {
strcpy(dayWord, "st");
}
else if (day() == 2) {
strcpy(dayWord, "nd");
}
else if (day() == 3) {
strcpy(dayWord, "rd");
}
else if (day() >= 4 && day() <= 20) {
strcpy(dayWord, "th");
}
else if (day() == 21) {
strcpy(dayWord, "st");
}
else if (day() == 22) {
strcpy(dayWord, "nd");
}
else if (day() == 23) {
strcpy(dayWord, "rd");
}
else if (day() >= 24 && day() <= 30) {
strcpy(dayWord, "th");
}
else if (day() == 31) {
strcpy(dayWord, "st");
}
char todayInWords[80];
sprintf(todayInWords, "%s %i%s %i", monthInWords[month()], day(), dayWord, year());
u8g2.drawStr(0, 63, todayInWords);
} while ( u8g2.nextPage() );
}
void blankClockDisplay() {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_logisoso32_tn);
char buf[12];
int fHour;
fHour = 12;
PM = false;
startX = -7;
u8g2.drawStr(startX, clockY, "12");
if (flicker) u8g2.drawStr(dotX, clockY, ":");
u8g2.drawStr(dotX + 7, clockY, "00");
u8g2.setFont(u8g2_font_logisoso16_tf );
u8g2.drawStr(dotX + 49, clockY, "00");
u8g2.drawStr(dotX + 73, clockY, "AM");
} while ( u8g2.nextPage() );
}
void serialClockDisplay() {
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits) {
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void processSyncMessage() {
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
//Serial.println("timesyncattempt");
if (Serial.find(TIME_HEADER)) {
pctime = Serial.parseInt();
if ( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
//Serial.println("timeset");
}
}
}
time_t requestSync()
{
Serial.write(TIME_REQUEST);
delay(50);
return 0; // the time will be sent later in response to serial mesg
}