Skip to content

Commit

Permalink
Home Assistant extensive support (#83)
Browse files Browse the repository at this point in the history
* feat(menu): improve hour format and graphic change experience

* fix(tft): use alphaBlend method of TFT_eSPI to dimming bitmap

* fix(backlight): fix apply of dimmed itensity with rainbow effect

* fix(menu): fix offset dislay on utc adjustments

* fix(clock): update time after timezone change

* fix(tft): improve toggle and dimming of tft displays

* feat(mqtt): create layer to use as home assistant light

https://www.home-assistant.io/integrations/light.mqtt/#json-schema

Add ability to control backlight brightness

* feat(mqtt): support backlight pattern change via ha effect

* feat(mqtt): add command to change graphic

* feat(mqtt): report every free loop time, but only when changes

* fix(mqtt): send to home assistant on report "back" too

* fix(mqtt): force send state when a command is executed

* feat(mqtt): save preferences after 10 seconds of no commands

* fix(mqtt): fix some report state issues

* Home Assistant Edition

* Small Readme changes

* Revert back renew order

* Clock faces names

---------

Co-authored-by: Victor Vuelma <[email protected]>
Co-authored-by: Victor Vuelma <[email protected]>
  • Loading branch information
3 people authored Aug 22, 2024
1 parent 35987ee commit 14f935c
Show file tree
Hide file tree
Showing 13 changed files with 1,100 additions and 130 deletions.
7 changes: 7 additions & 0 deletions EleksTubeHAX_pio/data/clockfaces.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Nixie Tube
Blue Ribbon
Colors
Modern Neon
Yellow Dots
Cyan and Pink
Thin Blue
62 changes: 43 additions & 19 deletions EleksTubeHAX_pio/src/Backlights.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ void Backlights::begin(StoredConfig::Config::Backlights *config_) {
setPattern(rainbow);
setColorPhase(0);
setIntensity(max_intensity-1);
setPulseRate(72);
setBreathRate(10);
setPulseRate(60);
setBreathRate(20);
setRainbowDuration(2);
config->is_valid = StoredConfig::valid;
}

off = false;
}

Expand Down Expand Up @@ -87,34 +87,33 @@ void Backlights::loop() {
}

void Backlights::pulsePattern() {
if (pattern_needs_init) {
fill(phaseToColor(config->color_phase));
}
fill(phaseToColor(config->color_phase));

float pulse_length_millis = (60.0f * 1000) / config->breath_per_min;
float pulse_length_millis = (60.0f * 1000) / config->pulse_bpm;
float val = 1 + abs(sin(2 * M_PI * millis() / pulse_length_millis)) * 254;
if (dimming) {
val = val * BACKLIGHT_DIMMED_INTENSITY / 7;
}
} else {
val = val * config->intensity / 7;
}
setBrightness((uint8_t)val);

show();

}

void Backlights::breathPattern() {
if (pattern_needs_init) {
fill(phaseToColor(config->color_phase));
}

fill(phaseToColor(config->color_phase));

// https://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
// Avoid a 0 value as it shuts off the LEDs and we have to re-initialize.
float pulse_length_millis = (60.0f * 1000) / config->breath_per_min;
float val = (exp(sin(2 * M_PI * millis() / pulse_length_millis)) - 0.36787944f) * 108.0f;

if (dimming) {
val = val * BACKLIGHT_DIMMED_INTENSITY / 7;
}
} else {
val = val * config->intensity / 7;
}

uint8_t brightness = (uint8_t)val;
if (brightness < 1) { brightness = 1; }
Expand All @@ -133,8 +132,14 @@ void Backlights::testPattern() {

clear();
setPixelColor(digit, color);
show();

if (dimming) {
setBrightness(0xFF >> max_intensity - (uint8_t) BACKLIGHT_DIMMED_INTENSITY - 1);
} else {
setBrightness(0xFF >> max_intensity - config->intensity - 1);
}

show();
}

uint8_t Backlights::phaseToIntensity(uint16_t phase) {
Expand Down Expand Up @@ -164,15 +169,34 @@ uint32_t Backlights::phaseToColor(uint16_t phase) {
return(uint32_t(red) << 16 | uint32_t(green) << 8 | uint32_t(blue));
}

uint32_t Backlights::hueToPhase(float hue) {
hue = hue - 120.f;
if (hue < 0) {
hue = hue + 360.f;
}
uint32_t phase = uint32_t(round(768.f * (1.f - hue/360.f)));
phase = phase % max_phase;
return(phase);
}

float Backlights::phaseToHue(uint32_t phase) {
float hue = 120.f + ((768.f - float(phase))/768.f)*360.f;
//h = 120 + (1 - p/768)*360
if( hue >= 360.f ) {
hue = hue - 360.f;
}
return(round(hue));
}

void Backlights::rainbowPattern() {
// Divide by 3 to spread it out some, so the whole rainbow isn't displayed at once.
// TODO Make this /3 a parameter
const uint16_t phase_per_digit = (max_phase/NUM_DIGITS)/3;

// Divide by 10 to slow down the rainbow rotation rate.
// TODO Make this /10 a parameter
uint16_t phase = millis()/16 % max_phase;
// Rainbow roatation speed now configurable
uint16_t duration = uint16_t(round(getRainbowDuration() * 1000));
uint16_t phase = uint16_t(round(float(millis() % duration) / duration * max_phase));

for (uint8_t digit=0; digit < NUM_DIGITS; digit++) {
// Shift the phase for this LED.
uint16_t my_phase = (phase + digit*phase_per_digit) % max_phase;
Expand Down
29 changes: 19 additions & 10 deletions EleksTubeHAX_pio/src/Backlights.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class Backlights: public Adafruit_NeoPixel {
void togglePower() { off = !off; pattern_needs_init = true; }
void PowerOn() { off = false; pattern_needs_init = true; }
void PowerOff() { off = true; pattern_needs_init = true; }
bool getPower() { return !off; }

void setPattern(patterns p) { config->pattern = uint8_t(p); pattern_needs_init = true; }
patterns getPattern() { return patterns(config->pattern); }
Expand All @@ -43,8 +44,12 @@ class Backlights: public Adafruit_NeoPixel {

// Configure the patterns
void setPulseRate(uint8_t bpm) { config->pulse_bpm = bpm; }
uint8_t getPulseRate() { return config->pulse_bpm; }
void setBreathRate(uint8_t per_min) { config->breath_per_min = per_min; }

uint8_t getBreathRate() { return config->breath_per_min; }
void setRainbowDuration(float seconds) { config->rainbow_sec = seconds; }
float getRainbowDuration() { return config->rainbow_sec; }

// Used by all constant color patterns.
void setColorPhase(uint16_t phase) { config->color_phase = phase % max_phase; pattern_needs_init = true; }
void adjustColorPhase(int16_t adj);
Expand All @@ -56,7 +61,16 @@ class Backlights: public Adafruit_NeoPixel {
uint8_t getIntensity() { return config->intensity; }

bool dimming = false;


// Helper methods
uint32_t phaseToColor(uint16_t phase);
uint32_t hueToPhase(float hue);
float phaseToHue(uint32_t phase);
uint8_t phaseToIntensity(uint16_t phase);

const uint16_t max_phase = 768; // 256 up, 256 down, 256 off
const uint8_t max_intensity = 8; // 0 to 7

private:
bool pattern_needs_init;
bool off;
Expand All @@ -69,15 +83,10 @@ class Backlights: public Adafruit_NeoPixel {
void rainbowPattern();
void pulsePattern();
void breathPattern();

// Helper methods
uint8_t phaseToIntensity(uint16_t phase);
uint32_t phaseToColor(uint16_t phase);

const uint16_t max_phase = 768; // 256 up, 256 down, 256 off
const uint8_t max_intensity = 8; // 0 to 7

const uint32_t test_ms_delay = 250;

};

extern Backlights backlights;

#endif // BACKLIGHTS_H
5 changes: 3 additions & 2 deletions EleksTubeHAX_pio/src/Clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ class Clock {
uint8_t getSecondsTens() { return getSecond()/10; }
uint8_t getSecondsOnes() { return getSecond()%10; }

private:
time_t loop_time, local_time;

private:
bool time_valid;
StoredConfig::Config::Clock *config;

Expand All @@ -93,6 +94,6 @@ class Clock {
const static uint32_t refresh_ntp_every_ms = 3600000; // Get new NTP every hour, use RTC in between.
};


extern Clock uclock;

#endif // CLOCK_H
4 changes: 2 additions & 2 deletions EleksTubeHAX_pio/src/GLOBAL_DEFINES.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

// ************* Version Infomation *************
#define DEVICE_NAME "IPS-clock"
#define FIRMWARE_VERSION "SmittyHalibut & aly-fly IPS clock v1.0"
#define FIRMWARE_VERSION "SmittyHalibut & aly-fly IPS clock v1.0 HA Edition victorvuelma & gamba69"
#define SAVED_CONFIG_NAMESPACE "configs"


Expand All @@ -34,7 +34,7 @@

// ************ MQTT config *********************
#define MQTT_RECONNECT_WAIT_SEC 30 // how long to wait between retries to connect to broker
#define MQTT_REPORT_STATUS_EVERY_SEC 71 // How often report status to MQTT Broker
#define MQTT_REPORT_STATUS_EVERY_SEC 15 // How often report status to MQTT Broker


// ************ Temperature config *********************
Expand Down
Loading

0 comments on commit 14f935c

Please sign in to comment.