diff --git a/3d/Super Vihelmo-Trug-5.stl b/3d/Super Vihelmo-Trug-5.stl index 655fdbf..b07a290 100644 Binary files a/3d/Super Vihelmo-Trug-5.stl and b/3d/Super Vihelmo-Trug-5.stl differ diff --git a/firmware/config.h b/firmware/config.h index 7d4ff16..172c4e2 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -18,9 +18,19 @@ #define EEPROM_LAST_STATE_ADDRESS 4 // the first "last state" information for the first light #define EEPROM_TIMING_DATA_ADDRESS (EEPROM_LAST_STATE_ADDRESS + LIGHTS_COUNT) // Stored data date per light ELE_USED; HH; MM; CH1; CH2; CH3; CH4; -#define BRI_MOD_STEPS_PER_SEC 25.0 +#define BRI_MOD_STEPS_PER_SEC 10 #define TIME_CHECK_INTERVAL_MS (60000UL) // 60 second interval #define TIME_LIGHTENGINE_INTERVAL_MS (1000UL / BRI_MOD_STEPS_PER_SEC) // BRI_MOD_STEPS_PER_SEC steps per second to in-/decrease the brightness #define MY_NTP_SERVER "de.pool.ntp.org" + +// 10 bit PWM +#define PWM_FREQ (50000UL) +#define PWM_OFF 0 // 0V +#define PWM_MIN 0 // 0V - minimum light amount (~1%) +#define PWM_MAX 255 // 24V - maximum light amount (100%) +#define BRI_TO_PWM_FACTOR 1.0 // 24V-0V = 24V range + +#define PWM_TEST_INTERVA_MS 1000 +#define TEST_PWM_CHG_CNT 5 diff --git a/firmware/data/bottom.js b/firmware/data/bottom.js index 3b0a739..db867c4 100644 --- a/firmware/data/bottom.js +++ b/firmware/data/bottom.js @@ -581,3 +581,31 @@ toast.style.opacity = 0; }, 5000); } } +function sendPWMTestRequest(event) { +event.preventDefault(); +var button = event.target; +var xhr = new XMLHttpRequest(); +xhr.open("GET", 'http://{{IP_ADDRESS}}/test_pwm', true); +xhr.onload = function () { +if (xhr.status == 200 && xhr.responseText === "OK") { +button.innerHTML = "PWM test started"; +button.style.backgroundColor = "green"; +} else { +button.innerHTML = "Error!"; +button.style.backgroundColor = "red"; +} +setTimeout(function () { +button.innerHTML = "PWM Test"; +button.style.backgroundColor = ""; +}, 2000); +}; +xhr.onerror = function () { +button.innerHTML = "Error!"; +button.style.backgroundColor = "red"; +setTimeout(function () { +button.innerHTML = "PWM Test"; +button.style.backgroundColor = ""; +}, 2000); +}; +xhr.send(); +} diff --git a/firmware/data/index_template_top.html b/firmware/data/index_template_top.html index 7345687..5deb421 100644 --- a/firmware/data/index_template_top.html +++ b/firmware/data/index_template_top.html @@ -22,6 +22,7 @@ reset light reset timing control data alert +PWM Test
diff --git a/firmware/firmware.ino b/firmware/firmware.ino index 69180ef..36c6819 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -55,25 +55,33 @@ IPAddress dns (192, 168, 0, 1); #define SCENE_BRIGHT 1 #define SCENE_NIGHTLY 2 -// 10 bit PWM -#define PWM_FREQ (50000UL) -#define PWM_OFF 0 // 0V -#define PWM_MIN 0 // 0V - minimum light amount (~1%) -#define PWM_MAX 255 // 24V - maximum light amount (100%) -#define BRI_TO_PWM_FACTOR 1.0 // 24V-0V = 24V range +#define TEST_PWM_STATE_INIT 0 +#define TEST_PWM_STATE_CH1_INC 1 +#define TEST_PWM_STATE_CH1_DEC 2 +#define TEST_PWM_STATE_CH2_INC 3 +#define TEST_PWM_STATE_CH2_DEC 4 +#define TEST_PWM_STATE_CH3_INC 5 +#define TEST_PWM_STATE_CH3_DEC 6 +#define TEST_PWM_STATE_CH4_INC 7 +#define TEST_PWM_STATE_CH4_DEC 8 //********************************// uint8_t scene; uint8_t tc_enabled; +uint8_t tc_enabled_old; + +bool test_pwm = false; +uint32_t test_pwm_lastcheck_ms = 0; +uint8_t test_pwm_state = TEST_PWM_STATE_INIT; bool light_state[LIGHTS_COUNT]; bool in_transition; -int default_transitiontime = 4; // 4 seconds +int default_transitiontime = 4; // 4 = 4 seconds -int transitiontime[LIGHTS_COUNT]; -int bri[LIGHTS_COUNT]; +uint16_t transitiontime[LIGHTS_COUNT]; +uint16_t bri[LIGHTS_COUNT]; uint16_t current_pwm[LIGHTS_COUNT]; float step_level[LIGHTS_COUNT]; @@ -345,13 +353,18 @@ void setup() void loop() { server.handleClient(); + + ESP.wdtFeed(); + lightEngine(); - if (tc_enabled == TIMING_CONTROL_ENABLED) - { - //Serial.println("tc_enabled = " + (String)tc_enabled); - tc_update_loop(); - } + //Serial.println("tc_enabled = " + (String)tc_enabled); + tc_update_loop(); + + ESP.wdtFeed(); + + test_pwm_main(); + delay(100); } //********************************// @@ -381,7 +394,7 @@ void init_webserver() server.on("/state", HTTP_PUT, []() { // HTTP PUT request used to set a new light state - DynamicJsonDocument root(1024); + DynamicJsonDocument root(512); DeserializationError error = deserializeJson(root, server.arg("plain")); if (error) { @@ -448,9 +461,9 @@ void init_webserver() server.on("/state", HTTP_GET, []() { // HTTP GET request used to fetch current light state uint8_t light = server.arg("light").toInt() - 1; - DynamicJsonDocument root(1024); - root["on"] = light_state[light]; - root["bri"] = bri[light]; + DynamicJsonDocument root(512); + root["on"] = light_state[light]; + root["bri"] = bri[light]; root["curbri"] = (int)current_bri[light]; root["curpwm"] = current_pwm[light]; String output; @@ -463,18 +476,27 @@ void init_webserver() char macString[32] = { 0 }; sprintf(macString, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); DynamicJsonDocument root(1024); - root["name"] = LIGHT_NAME; - root["lights"] = LIGHTS_COUNT; + root["name"] = LIGHT_NAME; + root["lights"] = LIGHTS_COUNT; root["protocol"] = "native_multi"; - root["modelid"] = "LWB010"; - root["type"] = "dimmable_light"; - root["mac"] = String(macString); - root["version"] = LIGHT_VERSION; + root["modelid"] = "LWB010"; + root["type"] = "dimmable_light"; + root["mac"] = String(macString); + root["version"] = LIGHT_VERSION; String output; serializeJson(root, output); server.send(200, "text/plain", output); }); + server.on("/test_pwm", []() + { + test_pwm = true; + tc_enabled_old = tc_enabled; + tc_enabled = TIMING_CONTROL_DISABLED; + + server.send(200, "text/html", "OK"); + }); + server.on("/tc_data_blocks_read", []() { String output = tc_getJsonData(); @@ -615,7 +637,15 @@ void init_webserver() if (server.hasArg("bri" + (String)light)) { - bri[light] = (int)server.arg("bri" + (String)light).toInt(); + int tmp = (int)server.arg("bri" + (String)light).toInt(); + + if (tmp > 255) + { + tmp = 255; + } else if (tmp < 0) { + tmp = 0; + } + bri[light] = tmp; Serial.print("Brightness "); Serial.print(light); Serial.print(" set to "); @@ -688,7 +718,7 @@ void init_webserver() ESP.reset(); } - // ***** Generate HTML page ***** // + // ***** Generate static HTML page ***** // String tmp1 = genHMTLTop(); @@ -935,3 +965,208 @@ String formatBytes(size_t bytes) } //********************************// + +void test_pwm_main() +{ + if (test_pwm == false) + { + return; + } else if ((test_pwm_lastcheck_ms + PWM_TEST_INTERVA_MS) <= millis()) + { + test_pwm_lastcheck_ms = millis(); + + switch (test_pwm_state) + { + // ----------------------- // + case TEST_PWM_STATE_INIT: + // disable the lights + for (uint8_t i = 0; i < LIGHTS_COUNT; i++) + { + light_state[i] = false; + bri[i] = 0; + current_bri[i] = 0; + current_pwm[i] = 0; + transitiontime[i] = 0; + process_lightdata(i, transitiontime[i]); + } + + light_state[0] = true; + test_pwm_state = TEST_PWM_STATE_CH1_INC; + break; + + // ----------------------- // + case TEST_PWM_STATE_CH1_INC: + + if (bri[0] < 255) + { + bri[0] += TEST_PWM_CHG_CNT; + transitiontime[0] = 1; + process_lightdata(0, transitiontime[0]); + + } else { + + test_pwm_state = TEST_PWM_STATE_CH1_DEC; + } + break; + + case TEST_PWM_STATE_CH1_DEC: + + if (bri[0] > 0) + { + bri[0] -= TEST_PWM_CHG_CNT; + transitiontime[0] = 1; + process_lightdata(0, transitiontime[0]); + + } else { + + light_state[0] = false; + bri[0] = 0; + current_bri[0] = 0; + current_pwm[0] = 0; + transitiontime[0] = 0; + process_lightdata(0, transitiontime[0]); + + light_state[1] = true; + test_pwm_state = TEST_PWM_STATE_CH2_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH2_INC: + + if (bri[1] < 255) + { + bri[1] += TEST_PWM_CHG_CNT; + transitiontime[1] = 1; + process_lightdata(1, transitiontime[1]); + + } else { + + test_pwm_state = TEST_PWM_STATE_CH2_DEC; + } + break; + + case TEST_PWM_STATE_CH2_DEC: + + if (bri[1] > 0) + { + bri[1] -= TEST_PWM_CHG_CNT; + transitiontime[1] = 1; + process_lightdata(1, transitiontime[1]); + + } else { + + light_state[1] = false; + bri[1] = 0; + current_bri[1] = 0; + current_pwm[1] = 0; + transitiontime[1] = 0; + process_lightdata(1, transitiontime[1]); + + light_state[2] = true; + test_pwm_state = TEST_PWM_STATE_CH3_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH3_INC: + + if (bri[2] < 255) + { + bri[2] += TEST_PWM_CHG_CNT; + transitiontime[2] = 1; + process_lightdata(2, transitiontime[2]); + + } else { + + test_pwm_state = TEST_PWM_STATE_CH3_DEC; + } + break; + + case TEST_PWM_STATE_CH3_DEC: + + if (bri[2] > 0) + { + bri[2] -= TEST_PWM_CHG_CNT; + transitiontime[2] = 1; + process_lightdata(2, transitiontime[2]); + + } else { + + light_state[2] = false; + bri[2] = 0; + current_bri[2] = 0; + current_pwm[2] = 0; + transitiontime[2] = 0; + process_lightdata(2, transitiontime[2]); + + light_state[3] = true; + test_pwm_state = TEST_PWM_STATE_CH4_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH4_INC: + + if (bri[3] < 255) + { + bri[3] += TEST_PWM_CHG_CNT; + transitiontime[3] = 1; + process_lightdata(3, transitiontime[3]); + + } else { + + test_pwm_state = TEST_PWM_STATE_CH4_DEC; + } + break; + + case TEST_PWM_STATE_CH4_DEC: + + if (bri[3] > 0) + { + bri[3] -= TEST_PWM_CHG_CNT; + transitiontime[3] = 1; + process_lightdata(3, transitiontime[3]); + + } else { + + test_pwm = false; + tc_enabled = tc_enabled_old; + + for (uint8_t i = 0; i < LIGHTS_COUNT; i++) + { + light_state[i] = false; + bri[i] = 0; + current_bri[i] = 0; + current_pwm[i] = 0; + transitiontime[i] = 0; + process_lightdata(i, transitiontime[i]); + } + + tc_reset(); + tc_update_main(); // load the tc if required + + test_pwm_state = TEST_PWM_STATE_INIT; + } + break; + + // ----------------------- // + default: + test_pwm_state = TEST_PWM_STATE_INIT; + } + + Serial.println("---"); + for (uint8_t i = 0; i < LIGHTS_COUNT; i++) + { + Serial.println("light_state[" + (String)i + "] = " + (String)light_state[i]); + Serial.println("bri[" + (String)i + "] = " + (String)bri[i]); + Serial.println("current_bri[" + (String)i + "] = " + (String)current_bri[i]); + Serial.println("current_pwm[" + (String)i + "] = " + (String)current_pwm[i]); + Serial.println("transitiontime[" + (String)i + "] = " + (String)transitiontime[i]); + } + + } + +} + +//********************************// diff --git a/firmware/html/bottom.js b/firmware/html/bottom.js index 502b416..91a7463 100644 --- a/firmware/html/bottom.js +++ b/firmware/html/bottom.js @@ -328,7 +328,6 @@ function updateLightState() { const onLinkOff = document.getElementById(`on${i - 1}_off`); briSlider.value = data.bri; briSliderVal.innerHTML = (Math.round((data.bri * 100.0 / 255.0) * 100) / 100).toFixed(2); - //console.log('data.on ' + i + ' = ' + data.on); if (data.on == true) { onLinkOn.classList.add('pure-button-primary'); onLinkOff.classList.remove('pure-button-primary'); @@ -707,4 +706,43 @@ function showToast(message, type) { }, 5000); } } - \ No newline at end of file + +function sendPWMTestRequest(event) { + + event.preventDefault(); // Verhindert das Standardverhalten des Links + + var button = event.target; // Der geklickte Button + + var xhr = new XMLHttpRequest(); // Erstellt eine XMLHttpRequest-Instanz + xhr.open("GET", 'http://{{IP_ADDRESS}}/test_pwm', true); // Sendet eine GET-Anfrage an die angegebene URL + + xhr.onload = function () { + if (xhr.status == 200 && xhr.responseText === "OK") { + button.innerHTML = "PWM test started"; + button.style.backgroundColor = "green"; // Setzt die Hintergrundfarbe auf Grün + } else { + button.innerHTML = "Error!"; + button.style.backgroundColor = "red"; // Setzt die Hintergrundfarbe auf Rot + } + + // Nach 2 Sekunden den ursprünglichen Text wiederherstellen + setTimeout(function () { + button.innerHTML = "PWM Test"; + button.style.backgroundColor = ""; // Entfernt die Hintergrundfarbe + }, 2000); + }; + + xhr.onerror = function () { + button.innerHTML = "Error!"; + button.style.backgroundColor = "red"; // Setzt die Hintergrundfarbe auf Rot + + // Nach 2 Sekunden den ursprünglichen Text wiederherstellen + setTimeout(function () { + button.innerHTML = "PWM Test"; + button.style.backgroundColor = ""; // Entfernt die Hintergrundfarbe + }, 2000); + }; + + xhr.send(); // Sendet die Anfrage +} + diff --git a/firmware/html/index_template_top.html b/firmware/html/index_template_top.html index 48515ca..9392287 100644 --- a/firmware/html/index_template_top.html +++ b/firmware/html/index_template_top.html @@ -22,6 +22,7 @@ reset light reset timing control data alert + PWM Test

diff --git a/firmware/timing_control.ino b/firmware/timing_control.ino index d605dc9..521382a 100644 --- a/firmware/timing_control.ino +++ b/firmware/timing_control.ino @@ -25,6 +25,8 @@ bool tc_testOngoing = false; uint32_t tc_last_check = 60000; +uint8_t current_target_data_block = 255; + WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, MY_NTP_SERVER); @@ -126,10 +128,20 @@ void tc_init() //********************************// +void tc_reset() +{ + current_target_data_block = 255; +} + void tc_update_loop() { static uint8_t last_min_check = 255; + if (tc_enabled == TIMING_CONTROL_DISABLED) + { + return; + } + if ((timeClient.getMinutes() % 10) != 0 || last_min_check == timeClient.getMinutes()) // && tc_testOngoing == false { last_min_check = timeClient.getMinutes(); @@ -141,9 +153,13 @@ void tc_update_loop() void tc_update_main() { - static uint8_t current_target_data_block = 255; uint8_t target_data_block = 255; + if (tc_enabled == TIMING_CONTROL_DISABLED) + { + return; + } + tc_updateTime(); // search for the current active time slot @@ -151,8 +167,6 @@ void tc_update_main() { //Serial.println((String)tc_data[i].hh + ":" + (String)tc_data[i].mm); - /*if (tc_data[i].hh <= timeClient.getHours() && - tc_data[i].mm <= timeClient.getMinutes())*/ if (tc_data[i].hh <= hour() && tc_data[i].mm <= minute()) { @@ -169,11 +183,11 @@ void tc_update_main() // disable the lights for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { - light_state[i] = false; - bri[i] = 0; - current_bri[i] = 0; - current_pwm[i] = 0; - transitiontime[i] = 4; + light_state[i] = false; + bri[i] = 0; + current_bri[i] = 0; + current_pwm[i] = 0; + transitiontime[i] = 0; process_lightdata(i, transitiontime[i]); }