Compare commits
3 Commits
9312ceb22b
...
42e49b6c06
| Author | SHA1 | Date | |
|---|---|---|---|
| 42e49b6c06 | |||
| 153d134f88 | |||
| d3586e697b |
@@ -26,7 +26,6 @@ static const uint8_t pwmPins[NUM_CHANNELS] = {
|
|||||||
5, // D5
|
5, // D5
|
||||||
18, // D6
|
18, // D6
|
||||||
19 // D7
|
19 // D7
|
||||||
// 23 (D8) remains as a spare
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t pwmFrequency = 25000; // 25 kHz
|
static const uint32_t pwmFrequency = 25000; // 25 kHz
|
||||||
@@ -79,9 +78,21 @@ static const unsigned long slewDuration = 1000; // 1 second smooth transition
|
|||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Animation tuning
|
// Animation tuning
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
static const float FADE_IN_FACTOR = 0.999f; // boot-up 0 → 100%
|
static const float FADE_IN_FACTOR = 0.998f; // boot-up 0 → 100%
|
||||||
static const float FADE_OUT_FACTOR = 0.999f; // watchdog 100% → 0
|
static const float FADE_OUT_FACTOR = 0.999f; // watchdog 100% → 0
|
||||||
static const unsigned long FADE_INTERVAL = 1; // ms between fade steps
|
static const unsigned long FADE_INTERVAL = 1; // ms between fade steps
|
||||||
|
// Lighting fade durations (milliseconds)
|
||||||
|
#define LIGHTING_FADE_IN_DURATION 1250
|
||||||
|
#define LIGHTING_FADE_OUT_DURATION 4250
|
||||||
|
// Clamping brightness at the low end
|
||||||
|
const uint8_t BRIGHTNESS_MIN_VISIBLE = 33;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
// Lighting (FastLED)
|
||||||
|
// -------------------------------
|
||||||
|
#define LED_PIN 23
|
||||||
|
#define NUM_LEDS 20
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Connection state machine
|
// Connection state machine
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
|
#include <FastLED.h>
|
||||||
|
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
Preferences prefs;
|
Preferences prefs;
|
||||||
@@ -26,9 +27,19 @@ float calibratedPoints[NUM_CHANNELS][5] = {
|
|||||||
{0.0f, 26.0f, 50.0f, 76.0f, 99.0f}
|
{0.0f, 26.0f, 50.0f, 76.0f, 99.0f}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CRGB leds[NUM_LEDS];
|
||||||
|
|
||||||
uint8_t lightingHue = 0;
|
uint8_t lightingHue = 0;
|
||||||
uint8_t lightingSaturation = 255;
|
uint8_t lightingSaturation = 255;
|
||||||
uint8_t lightingBrightness = 255;
|
uint8_t lightingBrightness = 255;
|
||||||
|
uint8_t lightingBrightnessSaved = 255;
|
||||||
|
|
||||||
|
// Lighting fade state
|
||||||
|
bool lightingFading = false;
|
||||||
|
uint8_t lightingFadeStart = 0;
|
||||||
|
uint8_t lightingFadeEnd = 0;
|
||||||
|
unsigned long lightingFadeStartTime = 0;
|
||||||
|
unsigned long lightingFadeDuration = 0;
|
||||||
|
|
||||||
bool overrideActive[NUM_CHANNELS] = {false};
|
bool overrideActive[NUM_CHANNELS] = {false};
|
||||||
|
|
||||||
@@ -63,6 +74,25 @@ float applyCalibration(uint8_t ch, float logicalDuty) {
|
|||||||
return calibratedPoints[ch][4];
|
return calibratedPoints[ch][4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applyLighting() {
|
||||||
|
// Convert HSV (0–255 each) to RGB
|
||||||
|
CHSV hsv(lightingHue, lightingSaturation, lightingBrightness);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_LEDS; i++) {
|
||||||
|
leds[i] = hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
FastLED.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void startLightingFade(uint8_t from, uint8_t to, unsigned long duration) {
|
||||||
|
lightingFadeStart = from;
|
||||||
|
lightingFadeEnd = to;
|
||||||
|
lightingFadeDuration = duration;
|
||||||
|
lightingFadeStartTime = millis();
|
||||||
|
lightingFading = true;
|
||||||
|
}
|
||||||
|
|
||||||
void updateConnectionStatusUI(ConnectionState state) {
|
void updateConnectionStatusUI(ConnectionState state) {
|
||||||
const char* text = "Unknown";
|
const char* text = "Unknown";
|
||||||
|
|
||||||
@@ -113,11 +143,19 @@ void coreInit() {
|
|||||||
|
|
||||||
lightingHue = prefs.getUChar("light_hue", 0);
|
lightingHue = prefs.getUChar("light_hue", 0);
|
||||||
lightingSaturation = prefs.getUChar("light_sat", 255);
|
lightingSaturation = prefs.getUChar("light_sat", 255);
|
||||||
lightingBrightness = prefs.getUChar("light_bright",255);
|
lightingBrightnessSaved = prefs.getUChar("light_bright",255);
|
||||||
|
lightingBrightness = lightingBrightnessSaved;
|
||||||
|
|
||||||
|
|
||||||
Serial.printf("Lighting loaded (0–255): H=%d S=%d B=%d\n",
|
Serial.printf("Lighting loaded (0–255): H=%d S=%d B=%d\n",
|
||||||
lightingHue, lightingSaturation, lightingBrightness);
|
lightingHue, lightingSaturation, lightingBrightness);
|
||||||
|
|
||||||
|
// FastLED init
|
||||||
|
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||||
|
FastLED.setBrightness(255); // full brightness; HSV V controls actual output
|
||||||
|
|
||||||
|
// Apply lighting immediately at boot
|
||||||
|
applyLighting();
|
||||||
|
|
||||||
// Start UDP with runtime port
|
// Start UDP with runtime port
|
||||||
udp.begin(udpPort);
|
udp.begin(udpPort);
|
||||||
@@ -157,6 +195,7 @@ void coreHandleUDP() {
|
|||||||
Serial.println("STATE CHANGE: DISCONNECTED → CONNECTING (UDP connection established)");
|
Serial.println("STATE CHANGE: DISCONNECTED → CONNECTING (UDP connection established)");
|
||||||
connectionState = STATE_CONNECTING;
|
connectionState = STATE_CONNECTING;
|
||||||
updateConnectionStatusUI(connectionState);
|
updateConnectionStatusUI(connectionState);
|
||||||
|
startLightingFade(0, lightingBrightnessSaved, LIGHTING_FADE_IN_DURATION);
|
||||||
|
|
||||||
// Initialize fade-in: start from 0 on all non-override channels
|
// Initialize fade-in: start from 0 on all non-override channels
|
||||||
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
for (int ch = 0; ch < NUM_CHANNELS; ch++) {
|
||||||
@@ -248,6 +287,7 @@ void coreUpdateState() {
|
|||||||
Serial.println("STATE CHANGE: CONNECTED → DISCONNECTED (UDP connection lost)");
|
Serial.println("STATE CHANGE: CONNECTED → DISCONNECTED (UDP connection lost)");
|
||||||
connectionState = STATE_DISCONNECTED;
|
connectionState = STATE_DISCONNECTED;
|
||||||
updateConnectionStatusUI(connectionState);
|
updateConnectionStatusUI(connectionState);
|
||||||
|
startLightingFade(lightingBrightness, 0, LIGHTING_FADE_OUT_DURATION);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,4 +377,62 @@ void coreUpdateState() {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lightingFading) {
|
||||||
|
unsigned long now = millis();
|
||||||
|
unsigned long elapsed = now - lightingFadeStartTime;
|
||||||
|
|
||||||
|
if (elapsed >= lightingFadeDuration) {
|
||||||
|
// Fade complete
|
||||||
|
lightingBrightness = lightingFadeEnd;
|
||||||
|
|
||||||
|
// If fade-out finished, jump to 0
|
||||||
|
if (lightingFadeEnd == 0) {
|
||||||
|
lightingBrightness = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lightingFading = false;
|
||||||
|
applyLighting();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute normalized progress
|
||||||
|
float t = (float)elapsed / (float)lightingFadeDuration;
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
const float gamma = 2.2f;
|
||||||
|
float t_gamma = pow(t, gamma);
|
||||||
|
|
||||||
|
// Determine effective fade range
|
||||||
|
uint8_t start = lightingFadeStart;
|
||||||
|
uint8_t end = lightingFadeEnd;
|
||||||
|
|
||||||
|
// Fade-in: 0 → 13 → 100
|
||||||
|
if (start == 0 && end > 0) {
|
||||||
|
start = BRIGHTNESS_MIN_VISIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fade-out: 100 → 13 → 0
|
||||||
|
if (end == 0 && start > 0) {
|
||||||
|
end = BRIGHTNESS_MIN_VISIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate only within the visible range
|
||||||
|
float raw = start + (end - start) * t_gamma;
|
||||||
|
|
||||||
|
// Apply jump logic:
|
||||||
|
if (lightingFadeStart == 0 && elapsed == 0) {
|
||||||
|
// Fade-in: first frame → jump to 13
|
||||||
|
lightingBrightness = BRIGHTNESS_MIN_VISIBLE;
|
||||||
|
}
|
||||||
|
else if (lightingFadeEnd == 0 && elapsed + 16 >= lightingFadeDuration) {
|
||||||
|
// Fade-out: last frame → jump to 0
|
||||||
|
lightingBrightness = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lightingBrightness = raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyLighting();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ extern bool overrideActive[NUM_CHANNELS];
|
|||||||
extern uint8_t lightingHue; // 0–255
|
extern uint8_t lightingHue; // 0–255
|
||||||
extern uint8_t lightingSaturation; // 0–255
|
extern uint8_t lightingSaturation; // 0–255
|
||||||
extern uint8_t lightingBrightness; // 0–255
|
extern uint8_t lightingBrightness; // 0–255
|
||||||
|
extern uint8_t lightingBrightnessSaved;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
extern ConnectionState connectionState;
|
extern ConnectionState connectionState;
|
||||||
@@ -48,3 +49,10 @@ void coreUpdateState(); // called from loop()
|
|||||||
// Helpers used by UI
|
// Helpers used by UI
|
||||||
float applyCalibration(uint8_t ch, float logicalDuty);
|
float applyCalibration(uint8_t ch, float logicalDuty);
|
||||||
void updateConnectionStatusUI(ConnectionState state);
|
void updateConnectionStatusUI(ConnectionState state);
|
||||||
|
|
||||||
|
// Lighting helpers
|
||||||
|
void applyLighting();
|
||||||
|
void startLightingFade(uint8_t from, uint8_t to);
|
||||||
|
|
||||||
|
// Lighting fade state
|
||||||
|
extern bool lightingFading;
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void lightingSaveCallback(Control *sender, int type) {
|
|||||||
|
|
||||||
prefs.putUChar("light_hue", lightingHue);
|
prefs.putUChar("light_hue", lightingHue);
|
||||||
prefs.putUChar("light_sat", lightingSaturation);
|
prefs.putUChar("light_sat", lightingSaturation);
|
||||||
prefs.putUChar("light_bright", lightingBrightness);
|
prefs.putUChar("light_bright", lightingBrightnessSaved);
|
||||||
|
|
||||||
Serial.printf("Lighting saved (0–255): H=%d S=%d B=%d\n",
|
Serial.printf("Lighting saved (0–255): H=%d S=%d B=%d\n",
|
||||||
lightingHue, lightingSaturation, lightingBrightness);
|
lightingHue, lightingSaturation, lightingBrightness);
|
||||||
@@ -246,6 +246,8 @@ void uiInit(uint16_t& tabSettings, uint16_t& tabLighting, uint16_t& tabCalibrati
|
|||||||
int sliderVal = sender->value.toInt(); // 0–100
|
int sliderVal = sender->value.toInt(); // 0–100
|
||||||
lightingHue = fromSlider(sliderVal); // convert to 0–255
|
lightingHue = fromSlider(sliderVal); // convert to 0–255
|
||||||
Serial.printf("Lighting Hue changed (RAM only): %d\n", lightingHue);
|
Serial.printf("Lighting Hue changed (RAM only): %d\n", lightingHue);
|
||||||
|
lightingFading = false; // cancel fade if user moves slider
|
||||||
|
applyLighting();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -260,6 +262,8 @@ void uiInit(uint16_t& tabSettings, uint16_t& tabLighting, uint16_t& tabCalibrati
|
|||||||
int sliderVal = sender->value.toInt(); // 0–100
|
int sliderVal = sender->value.toInt(); // 0–100
|
||||||
lightingSaturation = fromSlider(sliderVal);
|
lightingSaturation = fromSlider(sliderVal);
|
||||||
Serial.printf("Lighting Saturation updated (RAM only): %d\n", lightingSaturation);
|
Serial.printf("Lighting Saturation updated (RAM only): %d\n", lightingSaturation);
|
||||||
|
lightingFading = false; // cancel fade if user moves slider
|
||||||
|
applyLighting();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -272,8 +276,11 @@ void uiInit(uint16_t& tabSettings, uint16_t& tabLighting, uint16_t& tabCalibrati
|
|||||||
tabLighting,
|
tabLighting,
|
||||||
[](Control *sender, int type) {
|
[](Control *sender, int type) {
|
||||||
int sliderVal = sender->value.toInt(); // 0–100
|
int sliderVal = sender->value.toInt(); // 0–100
|
||||||
lightingBrightness = fromSlider(sliderVal);
|
lightingBrightnessSaved = fromSlider(sliderVal);
|
||||||
|
lightingBrightness = lightingBrightnessSaved;
|
||||||
Serial.printf("Lighting Brightness updated (RAM only): %d\n", lightingBrightness);
|
Serial.printf("Lighting Brightness updated (RAM only): %d\n", lightingBrightness);
|
||||||
|
lightingFading = false; // cancel fade if user moves slider
|
||||||
|
applyLighting();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
ESPUI.addControl(
|
ESPUI.addControl(
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
//
|
||||||
|
// IMPORTANT:
|
||||||
|
// before flashing this the first time,
|
||||||
|
// upload the "prepareFilesystem.ino" example sketch from ESPUI
|
||||||
|
// without that critical files are missing
|
||||||
|
//
|
||||||
|
// This was done to reduce the PROGMEM footprint of this program
|
||||||
|
//
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiManager.h>
|
#include <WiFiManager.h>
|
||||||
@@ -48,7 +57,7 @@ void setup() {
|
|||||||
uiInit(tabSettings, tabLighting, tabCalibration);
|
uiInit(tabSettings, tabLighting, tabCalibration);
|
||||||
|
|
||||||
ESPUI.sliderContinuous = true; // enables live slider updates
|
ESPUI.sliderContinuous = true; // enables live slider updates
|
||||||
ESPUI.begin("Analog Monitor UI");
|
ESPUI.beginLITTLEFS("Analog System Monitor UI");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
Reference in New Issue
Block a user