diff --git a/data/index.html b/data/index.html
index 84fb4e5..caae964 100644
--- a/data/index.html
+++ b/data/index.html
@@ -1,6 +1,7 @@
-
+
+
ESP8266 Treppenlicht
@@ -11,18 +12,23 @@
Treppenlicht
+
+ Active Brightness:
%
+
+
+
+
@@ -31,27 +37,27 @@
Time per stair [ms]: ms
-
+
-
+
diff --git a/data/input.js b/data/input.js
index f103844..f91afc8 100644
--- a/data/input.js
+++ b/data/input.js
@@ -1,13 +1,13 @@
let rangeValues = {};
let xhrUpd = new XMLHttpRequest();
-xhrUpd.onreadystatechange = function(){
- if(xhrUpd.readyState == 4) {
- if (xhrUpd.status == 200){
- console.log(xhrUpd.responseText);
+xhrUpd.onreadystatechange = function () {
+ if (xhrUpd.readyState == 4) {
+ if (xhrUpd.status == 200) {
+ console.log("xhrUpd: ", xhrUpd.responseText);
}
else {
- console.log("status:", xhrUpd.status);
+ console.log("xhrUpd: status=", xhrUpd.status);
}
}
}
@@ -15,9 +15,9 @@ xhrUpd.onreadystatechange = function(){
function reloadRangeValues() {
let url = "/update";
// if there are scheduled updates, send them
- if(Object.keys(rangeValues).length > 0) {
+ if (Object.keys(rangeValues).length > 0) {
let params = [];
- for(let p in rangeValues)
+ for (let p in rangeValues)
params.push(encodeURIComponent(p) + "=" + encodeURIComponent(rangeValues[p]));
params = params.join("&");
@@ -28,52 +28,61 @@ function reloadRangeValues() {
rangeValues = {};
}
- setTimeout(reloadRangeValues, 1000);
-};
-reloadRangeValues();
-
-function sendRangeValue(range, val) {
- rangeValues[range] = val;
- console.log(rangeValues);
};
-// connect actions to range inputs
-function rangeToOutput(range, output) {
- document.getElementById(range).oninput = function() {
- document.getElementById(output).innerHTML = this.value;
- sendRangeValue(this.id, this.value);
- }
-}
-
-rangeToOutput("range_act_pwm", "out_act_pwm");
-rangeToOutput("range_idl_pwm", "out_idl_pwm");
-rangeToOutput("range_tim_sta", "out_tim_sta");
-rangeToOutput("range_tim_ldr", "out_tim_ldr");
-rangeToOutput("range_ldr_shw", "out_ldr_shw");
-
-let xhr = new XMLHttpRequest();
-
-xhr.onreadystatechange = function(){
- if(xhr.readyState == 4) {
- if (xhr.status == 200){
- console.log(xhr.responseText);
- terminal = document.getElementById("term");
- autoscroll = document.getElementById("scroll");
- terminal.innerHTML += xhr.responseText;
- if(autoscroll.checked)
- terminal.scrollTop = terminal.scrollHeight;
- }
- else {
- console.log("status:", xhr.status);
- }
- }
-}
function reloadTerminal() {
- xhr.open("POST", "/terminal", true);
- xhr.send();
- setTimeout(reloadTerminal, 1000);
+ const terminal = document.querySelector("#term");
+ const autoscroll = document.querySelector("#scroll");
+
+ fetch(`/terminal`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: ''
+ })
+ .then(response => response.text())
+ .then(data => {
+ if(data.length > 0) {
+ terminal.innerHTML += data;
+ if (autoscroll.checked)
+ terminal.scrollTop = terminal.scrollHeight;
+ }
+ })
+ .catch(error => console.log('Error:', error));
};
-reloadTerminal();
-function clearTerminal() {
- document.getElementById("term").innerHTML = '';
-}
+
+document.addEventListener('DOMContentLoaded', () => {
+ setInterval(reloadTerminal, 1000);
+ setInterval(reloadRangeValues, 1000);
+
+
+ // use data- attributes for action
+ document.querySelectorAll('.control').forEach((button) => {
+ button.onclick = () => {
+ fetch(`/action`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: `control=${button.dataset.action}`
+ })
+ .then(response => console.log(response))
+ .catch(error => console.log('Error:', error));
+ }
+ });
+
+ document.querySelectorAll('.regler').forEach((regler) => {
+ regler.oninput = () => {
+ document.querySelector(`#${regler.dataset.output}`).innerHTML = regler.value;
+ rangeValues[regler.id] = regler.value;
+ }
+ });
+
+ document.querySelector('#clear_term').onclick = () => {
+ document.querySelector("#term").innerHTML = '';
+ };
+
+});
+
+
diff --git a/doku.md b/doku.md
index 10aba26..1ff813d 100644
--- a/doku.md
+++ b/doku.md
@@ -113,8 +113,10 @@ linker puts them together ?!?
- testing if dimming crashes when two animations
-> ldr does not interrupt animation, animation get's finished and stairs fade out -> FSM works without collisions
- interrupt to pending from sensors
+ -> rising edge trigger implemented, via pending input
- settings struct
-> implemented with EEPROM
+ -> adapted to only change on ruhezustand
- script for gdb on windows
-> [implemented](start_xtensa_gdb_stub.cmd)
- welcome animation ?
@@ -130,4 +132,10 @@ linker puts them together ?!?
- behavior when someone enters stairway from opposite direction after animation finished but person 1 is still on stairway?
-> currently stairs fade off from direction 1
- -> additional wait-state between "warten hoch/runter" and "abdimmen hoch/runter" after sensor detected person?
\ No newline at end of file
+ -> additional wait-state between "warten hoch/runter" and "abdimmen hoch/runter" after sensor detected person?
+
+
+- active brightness can be lower than idle in the moment
+- change idle to precentage of active !!
+
+- Webpage needs to load settings from eeprom !!
\ No newline at end of file
diff --git a/lib/httpserver/httpserver.cpp b/lib/httpserver/httpserver.cpp
index 568fc19..925f061 100644
--- a/lib/httpserver/httpserver.cpp
+++ b/lib/httpserver/httpserver.cpp
@@ -31,17 +31,33 @@ auto HTTPServer::start() -> bool {
// add static root file handler for http
this->serveStatic("/", LittleFS, "/");
this->begin();
- Serial.printf("Server active on Port 80 !\n\r");
+ logf("Server active on Port 80 !\n\r");
return true;
}
void HTTPServer::start_apps() {
- // application handler
+ this->on("/action", HTTP_POST, [this]() {
+ if (args()) {
+ logf("%s=%s\n", argName(0).c_str(), arg(0).c_str());
+
+ if (argName(0).equals("control")) {
+ if (arg(0).equals("s_oben")) {
+ treppe->overwrite_sensors(true, false);
+ logt("control => s_oben !\n");
+ }
+ else if (arg(0).equals("s_unten")) {
+ treppe->overwrite_sensors(false, true);
+ logt("control => s_unten !\n");
+ }
+ }
+ }
+ send(200, "text/plain", "accepted");
+ });
this->on("/update", HTTP_POST, [this]() {
if (args()) {
for (int i = 0; i < args() - 1; i++) {
- Serial.printf("%s=%s\n", argName(i).c_str(), arg(i).c_str());
+ logf("%s=%s\n", argName(i).c_str(), arg(i).c_str());
if (argName(i).equals("range_act_pwm")) {
treppe->set_active_pwm(arg(i).toInt(), VORGABE_PROZENT);
@@ -70,7 +86,7 @@ void HTTPServer::start_apps() {
});
this->on("/terminal", HTTP_POST, [this]() {
- // Serial.printf("got /terminal\n");
+ // logf("got /terminal\n");
if (tbuf_head) {
send(200, "text/plain", tbuf);
tbuf_head = 0;
diff --git a/lib/treppe/treppe.cpp b/lib/treppe/treppe.cpp
index 00bc5e1..0328be8 100644
--- a/lib/treppe/treppe.cpp
+++ b/lib/treppe/treppe.cpp
@@ -27,8 +27,7 @@ bool Treppe::dimmer_tick(dimmer_t *dimmer, bool dim_type) {
Serial.printf("DIM_LDR: start: %d, ziel: %d\n", dimmer->start_pwm,
dimmer->ziel_pwm);
return true;
- } else // DIM_STUFEN
- {
+ } else { // DIM_STUFEN
Serial.printf("DIM_STUFEN: stufe: %d, start: %d, ziel: %d\n",
dimmer->stufe, dimmer->start_pwm, dimmer->ziel_pwm);
@@ -36,8 +35,7 @@ bool Treppe::dimmer_tick(dimmer_t *dimmer, bool dim_type) {
if (dimmer->stufe >= stufen - 1)
return true;
dimmer->stufe++;
- } else // LR_RUNTER
- {
+ } else { // LR_RUNTER
if (dimmer->stufe <= 0)
return true;
dimmer->stufe--;
@@ -59,9 +57,9 @@ void Treppe::start_animation(dimmer_t *dimmer, bool dim_type, uint16_t on_pwm,
else
dimmer->stufe = stufen - 1;
- dimmer->ticks = parameters.time_per_stair / INT_TIME; // [ms]
+ dimmer->ticks = param.time_per_stair / INT_TIME; // [ms]
} else { // DIM_LDR
- dimmer->ticks = parameters.time_ldr / INT_TIME; // [ms]
+ dimmer->ticks = param.time_ldr / INT_TIME; // [ms]
}
if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN) {
@@ -108,33 +106,38 @@ void Treppe::print_state_on_change() {
}
}
-bool Treppe::read_sensor(int sensor) {
+void Treppe::overwrite_sensors(bool s_oben, bool s_unten) {
+ fsm_pend.web_ctrl_s_oben = s_oben;
+ fsm_pend.web_ctrl_s_unten = s_unten;
+}
- /*
- reads sensors with edge detection
+void Treppe::read_sensors() {
+ const bool s_oben = digitalRead(SENSOR_OBEN);
+ const bool s_unten = digitalRead(SENSOR_UNTEN);
- returns true if motion was detected
- returns false if no motion was detected
- returns false if motion was detected, but state did not change back to not
- detected
- */
- uint8_t pegel = digitalRead(sensor);
- static uint8_t pegel_alt[2] = {0, 0};
+ fsm_pend.sensor_oben = false;
+ fsm_pend.sensor_unten = false;
- uint8_t index = 0;
- if (sensor == SENSOR_OBEN)
- index = 0;
- else
- index = 1;
-
- if (pegel == 1 && pegel_alt[index] == 0) {
- pegel_alt[index] = pegel;
- return true;
- } else {
- pegel_alt[index] = pegel;
- return false;
+ // rising trigger => 1 cycle true !
+ if (s_oben && !fsm_pend.last_s_oben) {
+ fsm_pend.sensor_oben = true;
+ }
+ if (s_unten && !fsm_pend.last_s_unten) {
+ fsm_pend.sensor_unten = true;
+ }
+
+ fsm_pend.last_s_oben = s_oben;
+ fsm_pend.last_s_unten = s_unten;
+
+ // check for manipulation over webserver
+ if (fsm_pend.web_ctrl_s_oben) {
+ fsm_pend.sensor_oben = true;
+ fsm_pend.web_ctrl_s_oben = false;
+ }
+ if (fsm_pend.web_ctrl_s_unten) {
+ fsm_pend.sensor_unten = true;
+ fsm_pend.web_ctrl_s_unten = false;
}
- // return static_cast(pegel);
}
float Treppe::read_ldr() {
@@ -190,10 +193,10 @@ bool Treppe::check_ldr() {
// follow up: averaging over many samples?
float ldr = read_ldr();
- if (ldr < parameters.ldr_schwelle) {
+ if (ldr < param.ldr_schwelle) {
active = 1;
}
- if (ldr > parameters.ldr_schwelle + LDR_HYS) {
+ if (ldr > param.ldr_schwelle + LDR_HYS) {
active = 0;
}
return active;
@@ -206,7 +209,6 @@ void Treppe::task() {
// TODO wenn LDR geändert => idle_pwm_soll anpassen
// fsm_pend.ldr_changed = true;
-
fsm_inputs.ldr_schwelle = check_ldr();
#ifdef DEBUG_TIMING
@@ -215,8 +217,10 @@ void Treppe::task() {
m = micros();
#endif
- fsm_inputs.sensor_oben = read_sensor(SENSOR_OBEN);
- fsm_inputs.sensor_unten = read_sensor(SENSOR_UNTEN);
+ read_sensors();
+ fsm_inputs.sensor_oben = fsm_pend.sensor_oben;
+ fsm_inputs.sensor_unten = fsm_pend.sensor_unten;
+
fsm_inputs.anim_beendet = fsm_pend.anim_beendet;
#ifdef DEBUG_TIMING
@@ -248,7 +252,7 @@ void Treppe::task() {
fsm_outputs.status == ST_AUFDIMMEN_RUNTER ||
fsm_outputs.status == ST_ABDIMMEN_RUNTER) {
if (fsm_pend.anim_beendet)
- start_animation(&dimmer_stufen, DIM_STUFEN, parameters.active_pwm,
+ start_animation(&dimmer_stufen, DIM_STUFEN, param.active_pwm,
idle_pwm_ist);
else
fsm_pend.anim_beendet = dimmer_tick(&dimmer_stufen, DIM_STUFEN);
@@ -268,6 +272,12 @@ void Treppe::task() {
if (!fsm_pend.anim_beendet) {
fsm_pend.anim_beendet = dimmer_tick(&dimmer_ldr, DIM_LDR);
}
+
+ if (param_changed) {
+ param_changed = false;
+ param = param_pend;
+ save_param_to_eeprom();
+ }
}
#ifdef DEBUG_TIMING
@@ -288,7 +298,7 @@ void Treppe::setup() {
// WARNING: before getting Parameters of Flash, make sure plausible parameters
// are written in flash!
- EEPROM.get(EEP_START_ADDR, parameters); // get Parameters of flash
+ EEPROM.get(EEP_START_ADDR, param); // get Parameters of flash
pinMode(13, OUTPUT);
pinMode(0, OUTPUT);
@@ -304,73 +314,73 @@ void Treppe::setup() {
Serial.printf("Treppe: stufen=%d\n", stufen);
}
-void Treppe::saveParam() {
+void Treppe::save_param_to_eeprom() {
EEPROM.put(EEP_START_ADDR,
- parameters); // copy Parameters so "EEPROM"-section in RAM
+ param); // copy Parameters so "EEPROM"-section in RAM
EEPROM.commit(); // write "EEPROM"-section to flash
}
void Treppe::set_idle_pwm_max(const uint16_t value,
const vorgabe_typ_t vorgabe_typ) {
if (vorgabe_typ == VORGABE_PROZENT) {
- parameters.idle_pwm_max = parameters.active_pwm * value / 100;
+ param_pend.idle_pwm_max = param_pend.active_pwm * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
- parameters.idle_pwm_max = value;
+ param_pend.idle_pwm_max = value;
}
- if (parameters.idle_pwm_max > parameters.active_pwm) {
- parameters.idle_pwm_max = parameters.active_pwm;
+ if (param_pend.idle_pwm_max > param_pend.active_pwm) {
+ param_pend.idle_pwm_max = param_pend.active_pwm;
}
- saveParam();
+ param_changed = true;
- Serial.printf("Treppe: parameters.idle_pwm_max=%d\n",
- parameters.idle_pwm_max);
+ Serial.printf("Treppe: param_pend.idle_pwm_max=%d\n",
+ param_pend.idle_pwm_max);
}
void Treppe::set_active_pwm(const uint16_t value,
const vorgabe_typ_t vorgabe_typ) {
if (vorgabe_typ == VORGABE_PROZENT) {
- parameters.active_pwm = 4095 * value / 100;
+ param_pend.active_pwm = 4095 * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
- parameters.active_pwm = value;
+ param_pend.active_pwm = value;
}
- if (parameters.active_pwm > 4095) {
- parameters.idle_pwm_max = 4095;
+ if (param_pend.active_pwm > 4095) {
+ param_pend.idle_pwm_max = 4095;
}
- saveParam();
+ param_changed = true;
- Serial.printf("Treppe: parameters.active_pwm=%d\n", parameters.active_pwm);
+ Serial.printf("Treppe: param_pend.active_pwm=%d\n", param_pend.active_pwm);
}
void Treppe::set_time_ldr(const uint16_t value) {
- parameters.time_ldr = value;
- if (parameters.time_ldr > TIME_MS_MAX)
- parameters.time_ldr = TIME_MS_MAX;
- saveParam();
+ param_pend.time_ldr = value;
+ if (param_pend.time_ldr > TIME_MS_MAX)
+ param_pend.time_ldr = TIME_MS_MAX;
+ param_changed = true;
- Serial.printf("Treppe: time_ldr=%d\n", parameters.time_ldr);
+ Serial.printf("Treppe: time_ldr=%d\n", param_pend.time_ldr);
}
void Treppe::set_time_per_stair(const uint16_t value) {
- parameters.time_per_stair = value;
- if (parameters.time_per_stair > TIME_MS_MAX)
- parameters.time_per_stair = TIME_MS_MAX;
- saveParam();
+ param_pend.time_per_stair = value;
+ if (param_pend.time_per_stair > TIME_MS_MAX)
+ param_pend.time_per_stair = TIME_MS_MAX;
+ param_changed = true;
- Serial.printf("Treppe: time_per_stair=%d\n", parameters.time_per_stair);
+ Serial.printf("Treppe: time_per_stair=%d\n", param_pend.time_per_stair);
}
void Treppe::set_ldr_schwelle(const uint16_t value,
const vorgabe_typ_t vorgabe_typ) {
if (vorgabe_typ == VORGABE_PROZENT) {
// ?!
- parameters.ldr_schwelle = 10 * value / 100;
+ param_pend.ldr_schwelle = 10 * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
- // parameters.ldr_schwelle = value;
+ // param_pend.ldr_schwelle = value;
}
- saveParam();
+ param_changed = true;
- Serial.printf("Treppe: ldr_schwelle=%d\n", parameters.ldr_schwelle);
+ Serial.printf("Treppe: ldr_schwelle=%d\n", param_pend.ldr_schwelle);
}
\ No newline at end of file
diff --git a/lib/treppe/treppe.h b/lib/treppe/treppe.h
index 32bd14a..70389cc 100644
--- a/lib/treppe/treppe.h
+++ b/lib/treppe/treppe.h
@@ -30,15 +30,21 @@ private:
uint16_t active_pwm = 2000;
uint16_t ldr_schwelle = 2; // activation value for FSM [lx]
};
- stairway_param_t parameters;
+ stairway_param_t param;
+ stairway_param_t param_pend; // zwischenspeicher änderungen
+ bool param_changed = false;
- uint16_t idle_pwm_ist = parameters.idle_pwm_max;
+ uint16_t idle_pwm_ist = param.idle_pwm_max;
uint16_t idle_pwm_soll = 0;
struct fsm_pending_inputs_t {
bool anim_beendet = true;
bool sensor_unten = false;
+ bool last_s_unten = false;
+ bool web_ctrl_s_unten = false;
bool sensor_oben = false;
+ bool last_s_oben = false;
+ bool web_ctrl_s_oben = false;
bool ldr_changed = false;
};
fsm_pending_inputs_t fsm_pend;
@@ -77,13 +83,13 @@ private:
enum fsm_laufrichtung_t { LR_RUNTER = 0, LR_HOCH = 1 };
enum fsm_dimmrichtung_t { DR_ABDIMMEN = 0, DR_AUFDIMMEN = 1 };
+ void read_sensors();
+ void print_state_on_change();
+
/* DIMM */
- // bool dimmer(dimmer_t* dimmer, bool dim_type);
bool dimmer_tick(dimmer_t *dimmer, bool dim_type);
void start_animation(dimmer_t *dimmer, bool dim_type, uint16_t on_pwm,
uint16_t off_pwm);
- // void berechne_dimmer(dimmer_t* dimmer, bool dim_type);
- void print_state_on_change();
/* LDR */
bool read_sensor(int sensor);
@@ -98,13 +104,15 @@ public:
void task(); // call periodically
// Parameter section
- void saveParam();
+ void save_param_to_eeprom();
void set_idle_pwm_max(const uint16_t value, const vorgabe_typ_t vorgabe_typ);
void set_active_pwm(const uint16_t value, const vorgabe_typ_t vorgabe_typ);
void set_time_ldr(const uint16_t value);
void set_time_per_stair(const uint16_t value);
void set_ldr_schwelle(const uint16_t value, const vorgabe_typ_t vorgabe_typ);
+
+ void overwrite_sensors(bool s_oben, bool s_unten);
};
#endif // __TREPPE_H
\ No newline at end of file