Initial Upload

Mostly works. Just some issues with the 12 hour mode.
This commit is contained in:
mrcory
2022-10-29 15:06:36 -04:00
parent 6b602b3a8f
commit 942830f483
7 changed files with 591 additions and 0 deletions
+195
View File
@@ -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
}
+82
View File
@@ -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;
+224
View File
@@ -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);
}
+13
View File
@@ -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];
}
}
+10
View File
@@ -0,0 +1,10 @@
void preSetupHA() {
}
void inSetupHA() {
}
+18
View File
@@ -0,0 +1,18 @@
struct myCHSV {
byte hue;
byte sat;
byte val;
};
myCHSV myLED = {
0,
255,
200
};
myCHSV CLOCK = {
38,
255,
255
};
+49
View File
@@ -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();
}