From 4cb1007062de0316a6afc58be37d02d50d0191b6 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 10:59:30 +0200 Subject: [PATCH 1/7] Indention fixed. --- firmware/html/bottom.js | 1 + firmware/timing_control.ino | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/firmware/html/bottom.js b/firmware/html/bottom.js index 502b416..20deffc 100644 --- a/firmware/html/bottom.js +++ b/firmware/html/bottom.js @@ -329,6 +329,7 @@ function updateLightState() { 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); + //console.log('data light ' + i + ' = ' + data); if (data.on == true) { onLinkOn.classList.add('pure-button-primary'); onLinkOff.classList.remove('pure-button-primary'); diff --git a/firmware/timing_control.ino b/firmware/timing_control.ino index d605dc9..67e1258 100644 --- a/firmware/timing_control.ino +++ b/firmware/timing_control.ino @@ -151,8 +151,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,10 +167,10 @@ 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; + light_state[i] = false; + bri[i] = 0; + current_bri[i] = 0; + current_pwm[i] = 0; transitiontime[i] = 4; process_lightdata(i, transitiontime[i]); } From 6e4b75025fb327542c278794d4cc4e594ea84cc8 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 11:48:07 +0200 Subject: [PATCH 2/7] Reduced memory consumption. Reduced steps per second to reach the brightness. --- firmware/config.h | 2 +- firmware/firmware.ino | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/config.h b/firmware/config.h index a1763db..625d9d1 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -18,7 +18,7 @@ #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 5 #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 diff --git a/firmware/firmware.ino b/firmware/firmware.ino index 69180ef..ef60651 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -381,7 +381,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 +448,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; @@ -688,7 +688,7 @@ void init_webserver() ESP.reset(); } - // ***** Generate HTML page ***** // + // ***** Generate static HTML page ***** // String tmp1 = genHMTLTop(); From 790c848cc076d874ed7f99753a8227e567103068 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 14:18:59 +0200 Subject: [PATCH 3/7] Updated case 3D stl file --- 3d/Super Vihelmo-Trug-5.stl | Bin 269284 -> 269084 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/3d/Super Vihelmo-Trug-5.stl b/3d/Super Vihelmo-Trug-5.stl index 655fdbfd06d51b1ed0522cc2b1fb3c57acbaf789..b07a2905ceb5f267771b7ff97bdfc153f8bfb900 100644 GIT binary patch delta 53971 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 Date: Thu, 11 May 2023 16:48:59 +0200 Subject: [PATCH 4/7] Added a pwm test function --- firmware/config.h | 10 ++ firmware/data/bottom.js | 28 +++ firmware/data/index_template_top.html | 1 + firmware/firmware.ino | 236 ++++++++++++++++++++++++-- firmware/html/bottom.js | 43 ++++- firmware/html/index_template_top.html | 1 + firmware/timing_control.ino | 2 +- 7 files changed, 305 insertions(+), 16 deletions(-) diff --git a/firmware/config.h b/firmware/config.h index 625d9d1..d925ab8 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -24,3 +24,13 @@ #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 ef60651..b87bf44 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -55,17 +55,25 @@ 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; @@ -345,6 +353,9 @@ void setup() void loop() { server.handleClient(); + + ESP.wdtFeed(); + lightEngine(); if (tc_enabled == TIMING_CONTROL_ENABLED) @@ -352,6 +363,11 @@ void loop() //Serial.println("tc_enabled = " + (String)tc_enabled); tc_update_loop(); } + + ESP.wdtFeed(); + + test_pwm_main(); + delay(100); } //********************************// @@ -463,18 +479,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(); @@ -935,3 +960,190 @@ String formatBytes(size_t bytes) } //********************************// + +void test_pwm_main() +{ + if (test_pwm == false) + { + return; + } + + 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 (current_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 (current_bri[0] > 0) + { + bri[0] -= TEST_PWM_CHG_CNT; + transitiontime[0] = 1; + process_lightdata(0, transitiontime[0]); + + } else { + + light_state[0] = false; + transitiontime[0] = 0; + light_state[1] = true; + test_pwm_state = TEST_PWM_STATE_CH2_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH2_INC: + + if (current_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 (current_bri[1] > 0) + { + bri[1] -= TEST_PWM_CHG_CNT; + transitiontime[1] = 1; + process_lightdata(1, transitiontime[1]); + + } else { + + light_state[1] = false; + transitiontime[1] = 0; + light_state[2] = true; + test_pwm_state = TEST_PWM_STATE_CH3_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH3_INC: + + if (current_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 (current_bri[2] > 0) + { + bri[2] -= TEST_PWM_CHG_CNT; + transitiontime[2] = 1; + process_lightdata(2, transitiontime[2]); + + } else { + + light_state[2] = false; + transitiontime[2] = 0; + light_state[3] = true; + test_pwm_state = TEST_PWM_STATE_CH4_INC; + } + break; + + // ----------------------- // + case TEST_PWM_STATE_CH4_INC: + + if (current_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 (current_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]); + } + } + 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 20deffc..91a7463 100644 --- a/firmware/html/bottom.js +++ b/firmware/html/bottom.js @@ -328,8 +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); - //console.log('data light ' + i + ' = ' + data); if (data.on == true) { onLinkOn.classList.add('pure-button-primary'); onLinkOff.classList.remove('pure-button-primary'); @@ -708,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 67e1258..17fea0a 100644 --- a/firmware/timing_control.ino +++ b/firmware/timing_control.ino @@ -171,7 +171,7 @@ void tc_update_main() bri[i] = 0; current_bri[i] = 0; current_pwm[i] = 0; - transitiontime[i] = 4; + transitiontime[i] = 0; process_lightdata(i, transitiontime[i]); } From 0773d7717f576fd1d48ffcb4d0e123ec7c5bca76 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 18:17:08 +0200 Subject: [PATCH 5/7] PWM test implementation bugfix --- firmware/firmware.ino | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/firmware/firmware.ino b/firmware/firmware.ino index b87bf44..c9fe43a 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -495,7 +495,7 @@ void init_webserver() { test_pwm = true; tc_enabled_old = tc_enabled; - tc_enabled == TIMING_CONTROL_DISABLED; + tc_enabled = TIMING_CONTROL_DISABLED; server.send(200, "text/html", "OK"); }); @@ -966,9 +966,7 @@ void test_pwm_main() if (test_pwm == false) { return; - } - - if ((test_pwm_lastcheck_ms + PWM_TEST_INTERVA_MS) <= millis()) + } else if ((test_pwm_lastcheck_ms + PWM_TEST_INTERVA_MS) <= millis()) { test_pwm_lastcheck_ms = millis(); @@ -994,7 +992,7 @@ void test_pwm_main() // ----------------------- // case TEST_PWM_STATE_CH1_INC: - if (current_bri[0] < 255) + if (bri[0] < 255) { bri[0] += TEST_PWM_CHG_CNT; transitiontime[0] = 1; @@ -1008,7 +1006,7 @@ void test_pwm_main() case TEST_PWM_STATE_CH1_DEC: - if (current_bri[0] > 0) + if (bri[0] > 0) { bri[0] -= TEST_PWM_CHG_CNT; transitiontime[0] = 1; @@ -1017,7 +1015,12 @@ void test_pwm_main() } 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; } @@ -1026,7 +1029,7 @@ void test_pwm_main() // ----------------------- // case TEST_PWM_STATE_CH2_INC: - if (current_bri[1] < 255) + if (bri[1] < 255) { bri[1] += TEST_PWM_CHG_CNT; transitiontime[1] = 1; @@ -1040,7 +1043,7 @@ void test_pwm_main() case TEST_PWM_STATE_CH2_DEC: - if (current_bri[1] > 0) + if (bri[1] > 0) { bri[1] -= TEST_PWM_CHG_CNT; transitiontime[1] = 1; @@ -1049,7 +1052,12 @@ void test_pwm_main() } 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; } @@ -1058,7 +1066,7 @@ void test_pwm_main() // ----------------------- // case TEST_PWM_STATE_CH3_INC: - if (current_bri[2] < 255) + if (bri[2] < 255) { bri[2] += TEST_PWM_CHG_CNT; transitiontime[2] = 1; @@ -1072,7 +1080,7 @@ void test_pwm_main() case TEST_PWM_STATE_CH3_DEC: - if (current_bri[2] > 0) + if (bri[2] > 0) { bri[2] -= TEST_PWM_CHG_CNT; transitiontime[2] = 1; @@ -1080,8 +1088,13 @@ void test_pwm_main() } else { - light_state[2] = false; + 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; } @@ -1090,7 +1103,7 @@ void test_pwm_main() // ----------------------- // case TEST_PWM_STATE_CH4_INC: - if (current_bri[3] < 255) + if (bri[3] < 255) { bri[3] += TEST_PWM_CHG_CNT; transitiontime[3] = 1; @@ -1104,7 +1117,7 @@ void test_pwm_main() case TEST_PWM_STATE_CH4_DEC: - if (current_bri[3] > 0) + if (bri[3] > 0) { bri[3] -= TEST_PWM_CHG_CNT; transitiontime[3] = 1; @@ -1123,8 +1136,8 @@ void test_pwm_main() transitiontime[i] = 0; process_lightdata(i, transitiontime[i]); } + test_pwm_state = TEST_PWM_STATE_INIT; } - test_pwm_state = TEST_PWM_STATE_INIT; break; // ----------------------- // From 1efca24ff28095764272fa1d6d8722255f328dd1 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 18:21:55 +0200 Subject: [PATCH 6/7] timing counter call added to the pwm test, updated the tc_update functions to check if the tc is anabled. --- firmware/firmware.ino | 10 +++++----- firmware/timing_control.ino | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/firmware/firmware.ino b/firmware/firmware.ino index c9fe43a..885bab6 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -358,11 +358,8 @@ void loop() 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(); @@ -1136,6 +1133,9 @@ void test_pwm_main() transitiontime[i] = 0; process_lightdata(i, transitiontime[i]); } + + tc_update_main(); // load the tc if required + test_pwm_state = TEST_PWM_STATE_INIT; } break; diff --git a/firmware/timing_control.ino b/firmware/timing_control.ino index 17fea0a..83f9c07 100644 --- a/firmware/timing_control.ino +++ b/firmware/timing_control.ino @@ -130,6 +130,11 @@ 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(); @@ -144,6 +149,11 @@ 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 From 9d02e054f582b15dd4ab0ba13db1d1f3cb48baa4 Mon Sep 17 00:00:00 2001 From: Kai Lauterbach Date: Thu, 11 May 2023 19:37:17 +0200 Subject: [PATCH 7/7] Added brightness range check to brightness webserver set feature. Added a reset function to the timing control module. Fixed the pwm test feature by adding tc reset function call. --- firmware/config.h | 4 ++-- firmware/firmware.ino | 18 ++++++++++++++---- firmware/timing_control.ino | 8 +++++++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/firmware/config.h b/firmware/config.h index d925ab8..40795f4 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -18,7 +18,7 @@ #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 5 +#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 @@ -33,4 +33,4 @@ #define BRI_TO_PWM_FACTOR 1.0 // 24V-0V = 24V range #define PWM_TEST_INTERVA_MS 1000 -#define TEST_PWM_CHG_CNT 5 +#define TEST_PWM_CHG_CNT 5 diff --git a/firmware/firmware.ino b/firmware/firmware.ino index 885bab6..36c6819 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -78,10 +78,10 @@ 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]; @@ -637,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 "); @@ -1124,6 +1132,7 @@ void test_pwm_main() test_pwm = false; tc_enabled = tc_enabled_old; + for (uint8_t i = 0; i < LIGHTS_COUNT; i++) { light_state[i] = false; @@ -1134,6 +1143,7 @@ void test_pwm_main() process_lightdata(i, transitiontime[i]); } + tc_reset(); tc_update_main(); // load the tc if required test_pwm_state = TEST_PWM_STATE_INIT; diff --git a/firmware/timing_control.ino b/firmware/timing_control.ino index 83f9c07..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,6 +128,11 @@ void tc_init() //********************************// +void tc_reset() +{ + current_target_data_block = 255; +} + void tc_update_loop() { static uint8_t last_min_check = 255; @@ -146,7 +153,6 @@ 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)