/*
This is an attempt to construct an analogue real-time clock from a ring of just 12 LEDs.
The correct reading requires knowledge of the logic used.
The hours are indicated by the colour red, the minutes are divided into two colours: every 5 minutes the colour is green, while the single minute is cyan. For a correct reading of the minutes, the green and cyan LEDs must be added together in mind (e.g. 17 minutes will be indicated by the third green LED -> 15', plus the second cyan LED -> 2').
When the hands overlap, the colour of the led will be the sum of the colours of the respective hands. La sovrapposizione riguarda solo due colori, non ho ritenuto necessario valutare la sovrapposizione di tre colori.
The flashing LED indicates the reference mark (0/12h).
When there are no hands on that hour it will flash white/grey, otherwise it will flash the colour of the hand; at noon/midnight there will only be the red LED flashing.
An offset can be entered to correct any rotation of the ring.
*/
#include <WiFi.h>
#include <time.h>
#include <Ticker.h> //Ticker Library
#include <FastLED.h>
#define LED_PIN 2
#define NUM_LEDS 12
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define BRIGHTNESS 255
Ticker blinker;
CRGB leds[NUM_LEDS];
const char* Timezone = "CET-1CEST,M3.5.0,M10.5.0/3"; // Central Europe
byte ledState = 0;
byte hour_hand, minute5_hand, minute_hand, previous_second;
byte _offset = 0; // in case of rotation of the ring
time_t now;
CRGBPalette256 currentPalette;
void changeState()
{
if (hour_hand == 0)
leds[hour_hand] = CRGB(BRIGHTNESS*ledState,0,0);
else if (minute5_hand == 0)
leds[minute5_hand] = CRGB(0,BRIGHTNESS*ledState,0);
else if (minute_hand == 0)
leds[minute_hand] = CRGB(0,BRIGHTNESS*ledState,BRIGHTNESS*ledState);
else
leds[_offset] = CRGB(BRIGHTNESS/2*ledState,BRIGHTNESS/2*ledState,BRIGHTNESS/2*ledState);
ledState = !ledState;
FastLED.show();
}
void drawHands()
{
FastLED.clear(true);
Serial.print("Time "); Serial.print(localtime(&now)->tm_hour);Serial.print(":");Serial.print(localtime(&now)->tm_min);Serial.print(":");Serial.println(localtime(&now)->tm_sec);
Serial.print("Date "); Serial.print(localtime(&now)->tm_wday);Serial.print(" - "); Serial.print(localtime(&now)->tm_mday);Serial.print("/");Serial.print(localtime(&now)->tm_mon+1);Serial.print("/");Serial.println(localtime(&now)->tm_year+1900);
hour_hand += _offset;
if (hour_hand >= 12) hour_hand = hour_hand-12;
minute5_hand += _offset;
if (minute5_hand >= 12) minute5_hand = minute5_hand-12;
minute_hand += _offset;
if (minute_hand >= 12) minute_hand = minute_hand-12;
leds[hour_hand] = CRGB::Red;
leds[minute5_hand] = CRGB::Lime;
leds[minute_hand] = CRGB(64, 127, 255);
// if hour and minute and second are the same led, use a different color to show that
if (hour_hand==minute5_hand) {
leds[minute5_hand] = CRGB::Orange;
} else
if (minute_hand)
{
if (hour_hand==minute_hand){
leds[minute_hand] = CRGB(255, 0, 255);
}else
if (minute5_hand == minute_hand)
{
leds[minute_hand] = CRGB(0, 255, 255);
}
else
if (minute5_hand == minute_hand && minute_hand==hour_hand)
{
leds[minute_hand] = CRGB(127, 127, 127);
}
}
FastLED.show();
}
void setup() {
Serial.begin(115200);
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
setenv("TZ", Timezone, 1);
// Time_format = "M"; // or StartTime("I"); for Imperial 12:00 PM format and Date format MM-DD-CCYY e.g. 12:30PM 31-Mar-2019
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
blinker.attach(0.5, changeState);
}
void loop() {
time(&now);
minute5_hand=localtime(&now)->tm_min;
if (localtime(&now)->tm_hour >= 12) {
hour_hand = ((localtime(&now)->tm_hour - 12));
}
else {
hour_hand = (localtime(&now)->tm_hour);
}
minute_hand = minute5_hand % 5;
minute5_hand = (int)(minute5_hand/5.0);
if (minute_hand!=previous_second) {
previous_second=minute_hand;
drawHands();
}
}