// **** LED Ring Watch with ATtiny85 ****
//Verändert zum Original in Zeile 6 da Library nicht in Wokwi (Original Pfeil links Pfeil Rechts jetzt " ")
// **** Required libraries ****
#include <TinyWireM.h>
#include <TimeLib.h>
#include <TinyDS1307.h>
#include <Adafruit_NeoPixel.h>
// **** Configuration ****
#define LED_COUNT 16
#define PIN_LED 1
#define PIN_BTN_UP 3
#define PIN_BTN_DN 4
#define LED_BRIGHTNESS 127 // Overall brightness of the LEDs.
#define LOOP_MAX 84 // Number of cycles for the "glow" effect.
#define PIXEL_SHIFT 13 // Number of pixels to be shifted to make the digits display match the LEDs.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(LED_COUNT, PIN_LED, NEO_GRB + NEO_KHZ800);
long count = 0;
long deltaTime = 0; // Delta time from tuning in milliseconds.
long numLoops = 0; // Keeps track of the "acceleration" of the tuning buttons.
bool timeWasTuned = false;
tmElements_t actTime;
// **** Initialization ****
void setup(){
int k;
static const char monthNames[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
int year, month, day, hour, minute, second;
char monthStr[12];
// Prepare Buttons.
pinMode(PIN_BTN_UP, INPUT_PULLUP);
pinMode(PIN_BTN_DN, INPUT_PULLUP);
// Prepare the LEDs and the RTC.
pixels.begin();
TinyWireM.begin();
tinyrtc.begin();
// Get the compile date and time from the corresponding macros.
// Split the __DATE__.
sscanf(__DATE__, "%s %d %d", monthStr, &day, &year);
month = (strstr(monthNames, monthStr) - monthNames) / 3 + 1;
// Split the __TIME__.
sscanf(__TIME__, "%d:%d:%d", &hour, &minute, &second);
// Check whether thr RTC is running and whether it is up-to-date.
if(!tinyrtc.isrunning()){
tinyrtc.adjust(year, month, day, hour, minute, second);
// Set all LEDs to blue for a second to show that the RTC has received a new time value.
for(k = 0; k < 16; k++){
pixels.setPixelColor(k, 0x00007F);
}
pixels.show();
delay(1000);
}
for(k = 0; k < 16; k++){
pixels.setPixelColor(k, 0x000000);
}
pixels.show();
}
// **** Loop ****
void loop(){
unsigned long color;
unsigned long coeff;
long seconds, minutes, hours;
long tuningDirection;
int k;
time_t totalSeconds;
// Check whether a button was pressed.
tuningDirection = !digitalRead(PIN_BTN_UP) - !digitalRead(PIN_BTN_DN);
if(tuningDirection != 0){
deltaTime += tuningDirection * 100 * numLoops;
numLoops++;
timeWasTuned = true;
}
if((tuningDirection == 0) && timeWasTuned){ // Buttons were released.
// Store the new time to the RTC.
tinyrtc.adjust(actTime.Year + 1970, actTime.Month, actTime.Day, actTime.Hour, actTime.Minute, actTime.Second);
numLoops = 0;
deltaTime = 0;
timeWasTuned = false;
}
tinyrtc.read();
actTime.Second = tinyrtc.second();
actTime.Minute = tinyrtc.minute();
actTime.Hour = tinyrtc.hour();
actTime.Day = tinyrtc.day();
actTime.Month = tinyrtc.month();
actTime.Year = tinyrtc.year() - 1970;
// A) Sum up the last known time stamp to milliseconds since 01.01.1970.
totalSeconds = makeTime(actTime);
// B) Add delta.
totalSeconds += (deltaTime/1000);
// C) Break it down to elements again.
breakTime(totalSeconds, actTime);
seconds = actTime.Second;
minutes = actTime.Minute;
hours = actTime.Hour;
for(k = 0; k < 6; k++){
coeff = abs(((count + LOOP_MAX/6 * k) % LOOP_MAX) - LOOP_MAX/2);
color = (coeff << 16) + (40 << 8);
if(seconds & (0x01 << k)){
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, color);
}
else{
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, 0x000000);
}
}
for(k = 6; k < 12; k++){
coeff = abs(((count + LOOP_MAX/6 * k) % LOOP_MAX) - LOOP_MAX/2);
color = ((coeff*2 + 40) << 16) + (coeff/3);
if(minutes & (0x01 << (k-6))){
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, color);
}
else{
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, 0x000000);
}
}
hours %= 12;
if(hours == 0){
hours = 12; // Midnight --> 0:00 = 12:00 a.m.; Noon --> 12:00 = 12:00 p.m.
}
for(k = 12; k < 16; k++){
coeff = abs(((count + LOOP_MAX/4 * k) % LOOP_MAX) - LOOP_MAX/2);
color = (((unsigned long)(coeff*1.5)) << 8) + (coeff + 40);
if(hours & (0x01 << (k-12))){
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, color);
}
else{
pixels.setPixelColor((k + PIXEL_SHIFT) % 16, 0x000000);
}
}
pixels.show();
delay(20);
count = (count + 1)%LOOP_MAX;
}