mirror of
https://github.com/mrcory/Eva_Clock.git
synced 2026-08-02 15:24:27 -04:00
Initial Upload
Mostly works. Just some issues with the 12 hour mode.
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
//Clock Functions
|
||||
|
||||
const CHSV COLOR_BLACK = CHSV(0,255,0);
|
||||
const CHSV COLOR_RED = CHSV(0,255,150);
|
||||
|
||||
bool MODE_COUNTDOWN = false;
|
||||
bool HA_STATE = true;
|
||||
|
||||
//Define lower row "state" positions
|
||||
const byte STATE_STOP = 4;
|
||||
const byte STATE_SLOW = 5;
|
||||
const byte STATE_NORMAL = 6;
|
||||
const byte STATE_RACING = 7;
|
||||
|
||||
//Initial State
|
||||
byte CURRENT_STATE = STATE_NORMAL;
|
||||
|
||||
//Bitmap for numbers
|
||||
const byte DIGIT_ARRAY [] [7] = {
|
||||
// 0
|
||||
{1,1,1,0,1,1,1},
|
||||
// 1
|
||||
{0,1,0,0,1,0,0},
|
||||
//2
|
||||
{1,0,1,1,1,0,1},
|
||||
//3
|
||||
{1,1,0,1,1,0,1},
|
||||
//4
|
||||
{0,1,0,1,1,1,0},
|
||||
//5
|
||||
{1,1,0,1,0,1,1},
|
||||
//6
|
||||
{1,1,1,1,0,1,1},
|
||||
//7
|
||||
{0,1,0,0,1,0,1},
|
||||
//8
|
||||
{1,1,1,1,1,1,1},
|
||||
//9
|
||||
{1,1,0,1,1,1,1},
|
||||
//nil
|
||||
{0,0,0,0,0,0,0}
|
||||
};
|
||||
|
||||
//Hold the time in an array
|
||||
byte TIME_ARRAY [6] = {0};
|
||||
byte COUNTDOWN_ARRAY [6] = {0};
|
||||
|
||||
int RAINBOW_HUE = 0;
|
||||
|
||||
#ifdef NTP_ENABLE
|
||||
void CONVERT_TIME() {
|
||||
|
||||
#ifdef HOUR_12
|
||||
if (timeClient.getHours() > 12) {
|
||||
byte _temp_time = timeClient.getHours() - 12;
|
||||
TIME_ARRAY [0] = _temp_time / 10;
|
||||
TIME_ARRAY [1] = _temp_time % 10;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HOUR_24
|
||||
TIME_ARRAY [0] = timeClient.getHours() / 10;
|
||||
TIME_ARRAY [1] = timeClient.getHours() % 10;
|
||||
#endif
|
||||
|
||||
|
||||
TIME_ARRAY [2] = timeClient.getMinutes() / 10;
|
||||
TIME_ARRAY [3] = timeClient.getMinutes() % 10;
|
||||
|
||||
TIME_ARRAY [4] = timeClient.getSeconds() / 10;
|
||||
TIME_ARRAY [5] = timeClient.getSeconds() % 10;
|
||||
|
||||
if (TIME_ARRAY[0] == 0) { //If HOUR 1 is 0, change it to nil display
|
||||
TIME_ARRAY[0] = 10;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void BLANK_DISPLAY() {
|
||||
//Blank LEDs
|
||||
fill_solid(leds, NUM_LEDS, COLOR_BLACK);
|
||||
fill_solid(leds2, NUM_LEDS2, COLOR_BLACK);
|
||||
fill_solid(leds3, NUM_LEDS3, COLOR_BLACK);
|
||||
}
|
||||
|
||||
//Display a number character to the selected position. (0-5) Number 0-9 and use 10 for nil display
|
||||
void DISPLAY_NUMBER(byte _pos, byte _digit, CHSV _color = C_7_SEGMENT ) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (DIGIT_ARRAY[_digit][i] == 1) { //If segment should be lit, light it
|
||||
leds[DIGITS[_pos][i]] = _color;
|
||||
} else {
|
||||
leds[DIGITS[_pos][i]] = COLOR_BLACK; //If blank, turn off segment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DISPLAY_TIME() {
|
||||
if (HA_STATE == true) {
|
||||
brightness == originalBrightness;
|
||||
} else {
|
||||
brightness = 0;
|
||||
}
|
||||
|
||||
BLANK_DISPLAY(); //Blank LEDs at start
|
||||
|
||||
for (int i=0; i<6; i++) { //Loop for each digit
|
||||
DISPLAY_NUMBER(i, TIME_ARRAY[i]);
|
||||
}
|
||||
|
||||
//Light colons
|
||||
leds[COLONS[0]] = C_COLONS;
|
||||
leds[COLONS[1]] = C_COLONS;
|
||||
|
||||
//Background
|
||||
fill_gradient(leds2, 18, C_BACKGROUND_HUE_START, 39, C_BACKGROUND_HUE_END, BACKWARD_HUES);
|
||||
fill_gradient(leds2, 0 , C_BACKGROUND_HUE_END, 17, C_BACKGROUND_HUE_START, LONGEST_HUES);
|
||||
|
||||
for (int i = 40;i<44;i++) { //Fill extra top left LEDs
|
||||
leds2[i] = C_BACKGROUND_HUE_END;
|
||||
}
|
||||
|
||||
|
||||
leds[INTERNAL_TEXT_LED] = COLOR_BLACK;
|
||||
leds[EXTERNAL_TEXT_LED] = C_POWER_STATUS_EXT;
|
||||
}
|
||||
|
||||
unsigned long TIMER_TRACKER [2] = {0,0};
|
||||
|
||||
bool TIMER_RUNNING = true;
|
||||
unsigned long TIMER_START = millis();
|
||||
unsigned long TIMER_END = TIMER_START + COUNTDOWN_MILLIS;
|
||||
|
||||
unsigned long _tempCount = TIMER_END - millis();
|
||||
|
||||
void COUNTDOWN_TIME() {
|
||||
|
||||
int _tempCountRemain = _tempCount;
|
||||
unsigned long _minutes = (_tempCount / 60000);
|
||||
_tempCountRemain = _tempCount - (_minutes * 60000);
|
||||
unsigned long _seconds = _tempCountRemain / 1000;
|
||||
_tempCountRemain -= (_seconds * 1000);
|
||||
unsigned long _millisec = _tempCountRemain / 10;
|
||||
|
||||
COUNTDOWN_ARRAY[0] = _minutes / 10;
|
||||
COUNTDOWN_ARRAY[1] = _minutes % 10;
|
||||
COUNTDOWN_ARRAY[2] = _seconds / 10;
|
||||
COUNTDOWN_ARRAY[3] = _seconds % 10;
|
||||
COUNTDOWN_ARRAY[4] = _millisec / 10;
|
||||
COUNTDOWN_ARRAY[5] = _millisec % 10;
|
||||
|
||||
if ((_minutes + _seconds) == 0) {
|
||||
TIMER_RUNNING = false;
|
||||
}
|
||||
|
||||
for (int i=0; i<6; i++) { //Loop for each digit
|
||||
DISPLAY_NUMBER(i, COUNTDOWN_ARRAY[i], COLOR_RED);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_LEDS2; i++) {
|
||||
leds2[i] = COLOR_RED;
|
||||
}
|
||||
|
||||
//Light colons
|
||||
leds[COLONS[0]] = COLOR_RED;
|
||||
leds[COLONS[1]] = COLOR_RED;
|
||||
|
||||
leds[EXTERNAL_TEXT_LED] = COLOR_BLACK;
|
||||
leds[INTERNAL_TEXT_LED] = C_POWER_STATUS_INT;
|
||||
}
|
||||
|
||||
void SET_RUN_STATE() {
|
||||
if (MODE_COUNTDOWN == true) {
|
||||
CURRENT_STATE = STATE_RACING;
|
||||
}
|
||||
|
||||
if (MODE_COUNTDOWN == false) {
|
||||
CURRENT_STATE = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void STATUS_LIGHTS() {
|
||||
SET_RUN_STATE();
|
||||
|
||||
leds3[0] = C_GENERAL_TEXT; //Set text leds
|
||||
leds3[1] = C_GENERAL_TEXT; //Set text leds
|
||||
leds3[2] = C_GENERAL_TEXT; //Set text leds
|
||||
leds3[3] = C_GENERAL_TEXT; //Set text leds
|
||||
|
||||
leds3[CURRENT_STATE] = C_CURRENT_STATUS; //Light up the current state
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//Enable Home Assistant Integration
|
||||
#define ENABLE_HOME_ASSISTANT
|
||||
|
||||
//Home Assistant Config
|
||||
#define UNIQUE_NAME "Eva_Clock_00"
|
||||
#define BROKER_ADDR IPAddress(192,168,254,84)
|
||||
#define BROKER_USER ""
|
||||
#define BROKER_PASS ""
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
// Unique ID must be set!
|
||||
byte mac[] = {0x87, 0x21, 0xE1, 0x7F, 0xFA, 0xF7};
|
||||
|
||||
//LED Strip Data Pins
|
||||
#define pin_INNER 22
|
||||
#define pin_OUTER 16
|
||||
#define pin_STATUS 21
|
||||
|
||||
//Naming
|
||||
#define MY_HOST_NAME "Eva Clock"
|
||||
|
||||
//Enable NTP
|
||||
#define NTP_ENABLE
|
||||
|
||||
//UTC Offset in seconds
|
||||
long TIME_OFFSET = -14400;
|
||||
|
||||
//Set to 12 hour clock
|
||||
#define HOUR_12
|
||||
//#define HOUR_24
|
||||
|
||||
//Tweakable Values
|
||||
int HUE_SPEED = 400;
|
||||
|
||||
//Color Scheme
|
||||
//Clock Characters
|
||||
const CHSV C_7_SEGMENT = CHSV(38,255,150);
|
||||
const CHSV C_COLONS = CHSV(38,255,150);
|
||||
//All Text
|
||||
const CHSV C_GENERAL_TEXT = CHSV(38,255,150);
|
||||
//Background Hue
|
||||
const CHSV C_BACKGROUND_HUE_START = CHSV(148,255,255);
|
||||
const CHSV C_BACKGROUND_HUE_END = CHSV(0,255,255);
|
||||
//Power Status LEDs
|
||||
const CHSV C_POWER_STATUS_EXT = CHSV(85,255,150);
|
||||
const CHSV C_POWER_STATUS_INT = CHSV(0,255,150);
|
||||
//Lower Status Lights
|
||||
const CHSV C_CURRENT_STATUS = CHSV(0,255,250);
|
||||
|
||||
//Countdown Colors
|
||||
|
||||
|
||||
|
||||
|
||||
/*LED Positions in the below order
|
||||
* 7
|
||||
* 6 5
|
||||
* 4
|
||||
* 3 2
|
||||
* 1
|
||||
*/
|
||||
const byte DIGITS [6] [7] = {
|
||||
{11, 13, 12, 31, 33, 32, 49}, //Hour 1
|
||||
{10, 15, 14, 30, 35, 34, 48}, //Hour 2
|
||||
{9, 17, 16, 28, 37, 36, 47}, //Minute 1
|
||||
{8, 19, 18, 27, 39, 38, 46}, //Minute 2
|
||||
{7, 21, 20, 25, 41, 40, 45}, //Second 1
|
||||
{6, 23, 22, 24, 43, 42, 44} //Second 2
|
||||
};
|
||||
|
||||
//Power leds
|
||||
const byte INTERNAL_TEXT_LED = 0;
|
||||
const byte EXTERNAL_TEXT_LED = 4;
|
||||
|
||||
//Colons that divide hour and minute
|
||||
const byte COLONS [2] = {26, 29};
|
||||
|
||||
const byte TEXT_LEFT [] = {50,51,52};
|
||||
|
||||
//Extras
|
||||
long COUNTDOWN_MILLIS = 5000;//15000;//300000;
|
||||
@@ -0,0 +1,224 @@
|
||||
#include <ArduinoOTA.h>
|
||||
#include <FastLED.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <Ethernet2.h>
|
||||
#include <mDNS.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <NTPClient.h>
|
||||
|
||||
|
||||
#include "struct.h"
|
||||
#include "universalFunc.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef ENABLE_HOME_ASSISTANT
|
||||
#include <ArduinoHA.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define ledType WS2812
|
||||
#define colorOrder GRB
|
||||
#define NUM_LEDS 52 //91
|
||||
#define NUM_LEDS2 44 //Outer
|
||||
#define NUM_LEDS3 8 //Status Lights
|
||||
|
||||
CRGB leds[NUM_LEDS]; //Digits and Text
|
||||
CRGB leds2[NUM_LEDS2]; //Background
|
||||
CRGB leds3[NUM_LEDS3]; //Lower Status light
|
||||
|
||||
#include "func.h"
|
||||
|
||||
|
||||
#ifdef NTP_ENABLE
|
||||
WiFiUDP ntpUDP;
|
||||
NTPClient timeClient(ntpUDP, TIME_OFFSET);
|
||||
#endif
|
||||
|
||||
//Copied variabls
|
||||
int brightness = 30;
|
||||
int originalBrightness = 8;
|
||||
int oldBrightness = brightness;
|
||||
int FPS = 60;
|
||||
int glitterChance = 0;
|
||||
int currentPattern = 5;
|
||||
int gHue = 0;
|
||||
int colorIndex;
|
||||
int currentPalette;
|
||||
bool hueRun = false;
|
||||
bool runDemo = false;
|
||||
int breatheB = 20; //Brightness for "breathing"
|
||||
unsigned long breatheSpeed = 10;
|
||||
int breatheMin = 120;
|
||||
int chsvTest[3] = {random(256),random(200,256),255};
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
struct LightValues {
|
||||
bool lightOn;
|
||||
int brightness;
|
||||
};
|
||||
|
||||
LightValues lightValues = { .lightOn = true, .brightness = brightness };
|
||||
|
||||
#ifdef ENABLE_HOME_ASSISTANT
|
||||
WiFiClient client;
|
||||
|
||||
HADevice device(mac, sizeof(mac));
|
||||
HAMqtt mqtt(client, device);
|
||||
|
||||
HALight light(UNIQUE_NAME, HALight::BrightnessFeature);
|
||||
|
||||
|
||||
void onStateCommand(bool state, HALight* sender) {
|
||||
Serial.print("State: ");
|
||||
Serial.println(state);
|
||||
|
||||
if (state == false) {
|
||||
oldBrightness = lightValues.brightness;
|
||||
lightValues.brightness = 0;
|
||||
}
|
||||
|
||||
if (state == true && lightValues.brightness == 0) {
|
||||
lightValues.brightness = oldBrightness;
|
||||
}
|
||||
|
||||
lightValues.lightOn = state;
|
||||
|
||||
sender->setState(state); // report state back to the Home Assistant
|
||||
}
|
||||
|
||||
void onBrightnessCommand(uint8_t brightness, HALight* sender) {
|
||||
Serial.print("Brightness: ");
|
||||
Serial.println(brightness);
|
||||
|
||||
lightValues.brightness = brightness;
|
||||
lightValues.lightOn = true;
|
||||
|
||||
|
||||
sender->setBrightness(brightness); // report brightness back to the Home Assistant
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
WiFiManager wifi;
|
||||
|
||||
#ifdef ENABLE_HOME_ASSISTANT
|
||||
device.setName(MY_HOST_NAME);
|
||||
device.setSoftwareVersion(VERSION);
|
||||
|
||||
light.setState(true); //Light starts on, so let us tell HA
|
||||
|
||||
light.setName(MY_HOST_NAME);
|
||||
|
||||
|
||||
light.onStateCommand(onStateCommand);
|
||||
light.onBrightnessCommand(onBrightnessCommand);
|
||||
|
||||
mqtt.begin(BROKER_ADDR, BROKER_USER, BROKER_PASS);
|
||||
|
||||
WiFi.macAddress(mac);
|
||||
#endif
|
||||
|
||||
|
||||
wifi.autoConnect(MY_HOST_NAME);
|
||||
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
|
||||
Serial.begin(115200);
|
||||
|
||||
|
||||
ArduinoOTA.onError([](ota_error_t error) { ESP.restart(); });
|
||||
ArduinoOTA.setPassword("admin");
|
||||
ArduinoOTA.setHostname(MY_HOST_NAME);
|
||||
|
||||
ArduinoOTA.onStart([]() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH) {
|
||||
type = "sketch";
|
||||
} else { // U_SPIFFS
|
||||
type = "filesystem";
|
||||
}
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
Serial.println("Start updating " + type);
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) {
|
||||
Serial.println("Auth Failed");
|
||||
} else if (error == OTA_BEGIN_ERROR) {
|
||||
Serial.println("Begin Failed");
|
||||
} else if (error == OTA_CONNECT_ERROR) {
|
||||
Serial.println("Connect Failed");
|
||||
} else if (error == OTA_RECEIVE_ERROR) {
|
||||
Serial.println("Receive Failed");
|
||||
} else if (error == OTA_END_ERROR) {
|
||||
Serial.println("End Failed");
|
||||
}
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
|
||||
#ifdef NTP_ENABLE
|
||||
timeClient.begin();
|
||||
timeClient.setUpdateInterval(60000);
|
||||
#endif
|
||||
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
FastLED.addLeds<ledType,pin_INNER,colorOrder>(leds,0,NUM_LEDS);
|
||||
FastLED.addLeds<ledType,pin_OUTER,colorOrder>(leds2,0,NUM_LEDS2);
|
||||
FastLED.addLeds<ledType,pin_STATUS,colorOrder>(leds3,0,NUM_LEDS3);
|
||||
|
||||
FastLED.setBrightness(brightness);
|
||||
|
||||
timerSetup();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HOME_ASSISTANT
|
||||
#include "ha.h"
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
ArduinoOTA.handle();
|
||||
#ifdef ENABLE_HOME_ASSISTANT
|
||||
if (timer(500,2)) {
|
||||
mqtt.loop();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NTP_ENABLE
|
||||
timeClient.update();
|
||||
#endif
|
||||
|
||||
if (timer(24,0)) {
|
||||
if (TIMER_RUNNING) {
|
||||
_tempCount = TIMER_END - millis();
|
||||
COUNTDOWN_TIME();
|
||||
STATUS_LIGHTS();
|
||||
} else {
|
||||
DISPLAY_TIME();
|
||||
STATUS_LIGHTS();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (timer(100,5)) {
|
||||
CONVERT_TIME();
|
||||
}
|
||||
|
||||
if (timer(HUE_SPEED,1)) {
|
||||
RAINBOW_HUE++;
|
||||
}
|
||||
|
||||
FastLED.setBrightness(lightValues.brightness);
|
||||
FastLED.show();
|
||||
FastLED.delay(1000/FPS);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//Extra Functions
|
||||
|
||||
CRGB HOLD_ARRAY[50];
|
||||
|
||||
void REVERSE_ARRAY2(int _ORIG_START, int _ORIG_NUM) {
|
||||
for (int i = 0 ; i < _ORIG_NUM ; i++) {
|
||||
HOLD_ARRAY[i] = leds2[i + _ORIG_START];
|
||||
}
|
||||
|
||||
for (int i = 0 ; i < _ORIG_NUM ; i++) {
|
||||
leds2[_ORIG_NUM - i] = HOLD_ARRAY[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
void preSetupHA() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void inSetupHA() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
struct myCHSV {
|
||||
byte hue;
|
||||
byte sat;
|
||||
byte val;
|
||||
};
|
||||
|
||||
myCHSV myLED = {
|
||||
0,
|
||||
255,
|
||||
200
|
||||
};
|
||||
|
||||
myCHSV CLOCK = {
|
||||
38,
|
||||
255,
|
||||
255
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
//Timing
|
||||
#define countDataAmount 6 //Number of timers
|
||||
unsigned long countData[countDataAmount] = {0}; //Holds count information. (Adjust for numeber of timers needed.)
|
||||
|
||||
/* Timers
|
||||
* 0 - Display time
|
||||
* 1 - Rainbow Hue
|
||||
* 2 - HA Timer
|
||||
* 3
|
||||
* 4 -
|
||||
* 5 - Temp
|
||||
*/
|
||||
|
||||
//Used by timer function
|
||||
unsigned long millisCount(int _mode, int _id) { //_mode: 0-Start 1-Stop | _id Identity number (allow more by editing the length of countData
|
||||
unsigned long _count;
|
||||
if (_mode == 0) {
|
||||
countData[_id]= millis();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_mode == 1) {
|
||||
_count = millis() - countData[_id];
|
||||
return _count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Will set all variables in timer table to 0.
|
||||
void timerSetup() {
|
||||
for (int i=0;i<countDataAmount;i++) {
|
||||
millisCount(0,i);
|
||||
}
|
||||
}
|
||||
|
||||
//Use this to check if set time has passed.
|
||||
//Will return true or false
|
||||
bool timer(unsigned long _interval,int _id) { //_interval in millis, _id in countData
|
||||
if (millisCount(1,_id) >= _interval) {
|
||||
millisCount(0,_id);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void timerReset(byte _id) { //Reset timer start time
|
||||
countData[_id]= millis();
|
||||
}
|
||||
Reference in New Issue
Block a user