<!DOCTYPE html> | <!DOCTYPE html> | ||||
<html> | <html> | ||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||||
<head> | <head> | ||||
<title>ESP8266 Treppenlicht</title> | <title>ESP8266 Treppenlicht</title> | ||||
<link href="/favicon.png" rel="icon" type="image/png" sizes="10x10"> | <link href="/favicon.png" rel="icon" type="image/png" sizes="10x10"> | ||||
<body> | <body> | ||||
<div class="topbar">Treppenlicht</div> | <div class="topbar">Treppenlicht</div> | ||||
<div class="param_block"> | |||||
<input type="button" class="control" data-action="s_oben" value="sensor_oben"> | |||||
<input type="button" class="control" data-action="s_unten" value="sensor_unten"> | |||||
<input type="button" class="control" data-action="on_off" value="on_off"> | |||||
</div> | |||||
<div class="param_block"> | <div class="param_block"> | ||||
Active Brightness: <output id="out_act_pwm" class="val_range">50</output> % | Active Brightness: <output id="out_act_pwm" class="val_range">50</output> % | ||||
<div class="slider"> | <div class="slider"> | ||||
<input type="range" class="regler" id="range_act_pwm" min="0" max="100" value="50"> | |||||
<input type="range" class="regler" id="range_act_pwm" data-output="out_act_pwm" min="0" max="100" value="50"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="param_block"> | <div class="param_block"> | ||||
Idle Brightness Maximum: <output id="out_idl_pwm" class="val_range">50</output> % | Idle Brightness Maximum: <output id="out_idl_pwm" class="val_range">50</output> % | ||||
<label id="note">[100% == Active Brightness]</label> | <label id="note">[100% == Active Brightness]</label> | ||||
<div class="slider"> | <div class="slider"> | ||||
<input type="range" class="regler" id="range_idl_pwm" min="0" max="100" value="50"> | |||||
<input type="range" class="regler" id="range_idl_pwm" data-output="out_idl_pwm" min="0" max="100" value="50"> | |||||
</div> | </div> | ||||
<label id="note">idle brightness gets controlled via LDR measurments</label> | <label id="note">idle brightness gets controlled via LDR measurments</label> | ||||
</div> | </div> | ||||
Time per stair [ms]: <output id="out_tim_sta" class="val_range">300</output> ms | Time per stair [ms]: <output id="out_tim_sta" class="val_range">300</output> ms | ||||
<div class="slider"> | <div class="slider"> | ||||
<input type="range" class="regler" id="range_tim_sta" min="0" max="5000" value="300"> | |||||
<input type="range" class="regler" id="range_tim_sta" data-output="out_tim_sta" min="0" max="5000" value="300"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="param_block"> | <div class="param_block"> | ||||
Time LDR [ms]: <output id="out_tim_ldr" class="val_range">500</output> ms | Time LDR [ms]: <output id="out_tim_ldr" class="val_range">500</output> ms | ||||
<div class="slider"> | <div class="slider"> | ||||
<input type="range" class="regler" id="range_tim_ldr" min="0" max="5000" value="500"> | |||||
<input type="range" class="regler" id="range_tim_ldr" data-output="out_tim_ldr" min="0" max="5000" value="500"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="param_block"> | <div class="param_block"> | ||||
LDR Schwelle [%]: <output id="out_ldr_shw" class="val_range">50</output> % | LDR Schwelle [%]: <output id="out_ldr_shw" class="val_range">50</output> % | ||||
<div class="slider"> | <div class="slider"> | ||||
<input type="range" class="regler" id="range_ldr_shw" min="0" max="100" value="50"> | |||||
<input type="range" class="regler" id="range_ldr_shw" data-output="out_ldr_shw" min="0" max="100" value="50"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="terminal"> | <div class="terminal"> | ||||
<input type="button" id="clear_term" value="clear" onclick="clearTerminal();"> | |||||
<input type="button" id="clear_term" value="clear"> | |||||
<input type="checkbox" id="scroll" name="scroll" value="scroll" checked> | <input type="checkbox" id="scroll" name="scroll" value="scroll" checked> | ||||
<label for="scroll"> autoscroll </label> | <label for="scroll"> autoscroll </label> | ||||
<textarea id="term">waiting for log messages ... </textarea> | <textarea id="term">waiting for log messages ... </textarea> |
let rangeValues = {}; | let rangeValues = {}; | ||||
let xhrUpd = new XMLHttpRequest(); | 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 { | else { | ||||
console.log("status:", xhrUpd.status); | |||||
console.log("xhrUpd: status=", xhrUpd.status); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
function reloadRangeValues() { | function reloadRangeValues() { | ||||
let url = "/update"; | let url = "/update"; | ||||
// if there are scheduled updates, send them | // if there are scheduled updates, send them | ||||
if(Object.keys(rangeValues).length > 0) { | |||||
if (Object.keys(rangeValues).length > 0) { | |||||
let params = []; | let params = []; | ||||
for(let p in rangeValues) | |||||
for (let p in rangeValues) | |||||
params.push(encodeURIComponent(p) + "=" + encodeURIComponent(rangeValues[p])); | params.push(encodeURIComponent(p) + "=" + encodeURIComponent(rangeValues[p])); | ||||
params = params.join("&"); | params = params.join("&"); | ||||
rangeValues = {}; | rangeValues = {}; | ||||
} | } | ||||
setTimeout(reloadRangeValues, 1000); | |||||
}; | }; | ||||
reloadRangeValues(); | |||||
function sendRangeValue(range, val) { | |||||
rangeValues[range] = val; | |||||
console.log(rangeValues); | |||||
function reloadTerminal() { | |||||
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)); | |||||
}; | }; | ||||
// 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); | |||||
} | |||||
} | |||||
document.addEventListener('DOMContentLoaded', () => { | |||||
setInterval(reloadTerminal, 1000); | |||||
setInterval(reloadRangeValues, 1000); | |||||
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; | |||||
// 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)); | |||||
} | } | ||||
else { | |||||
console.log("status:", xhr.status); | |||||
}); | |||||
document.querySelectorAll('.regler').forEach((regler) => { | |||||
regler.oninput = () => { | |||||
document.querySelector(`#${regler.dataset.output}`).innerHTML = regler.value; | |||||
rangeValues[regler.id] = regler.value; | |||||
} | } | ||||
} | |||||
} | |||||
function reloadTerminal() { | |||||
xhr.open("POST", "/terminal", true); | |||||
xhr.send(); | |||||
setTimeout(reloadTerminal, 1000); | |||||
}; | |||||
reloadTerminal(); | |||||
function clearTerminal() { | |||||
document.getElementById("term").innerHTML = ''; | |||||
} | |||||
}); | |||||
document.querySelector('#clear_term').onclick = () => { | |||||
document.querySelector("#term").innerHTML = ''; | |||||
}; | |||||
}); | |||||
- testing if dimming crashes when two animations | - testing if dimming crashes when two animations | ||||
-> ldr does not interrupt animation, animation get's finished and stairs fade out -> FSM works without collisions | -> ldr does not interrupt animation, animation get's finished and stairs fade out -> FSM works without collisions | ||||
- interrupt to pending from sensors | - interrupt to pending from sensors | ||||
-> rising edge trigger implemented, via pending input | |||||
- settings struct | - settings struct | ||||
-> implemented with EEPROM | -> implemented with EEPROM | ||||
-> adapted to only change on ruhezustand | |||||
- script for gdb on windows | - script for gdb on windows | ||||
-> [implemented](start_xtensa_gdb_stub.cmd) | -> [implemented](start_xtensa_gdb_stub.cmd) | ||||
- welcome animation ? | - welcome animation ? | ||||
- behavior when someone enters stairway from opposite direction after animation finished but person 1 is still on stairway? | - 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 | -> currently stairs fade off from direction 1 | ||||
-> additional wait-state between "warten hoch/runter" and "abdimmen hoch/runter" after sensor detected person? | |||||
-> 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 !! |
// add static root file handler for http | // add static root file handler for http | ||||
this->serveStatic("/", LittleFS, "/"); | this->serveStatic("/", LittleFS, "/"); | ||||
this->begin(); | this->begin(); | ||||
Serial.printf("Server active on Port 80 !\n\r"); | |||||
logf("Server active on Port 80 !\n\r"); | |||||
return true; | return true; | ||||
} | } | ||||
void HTTPServer::start_apps() { | 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]() { | this->on("/update", HTTP_POST, [this]() { | ||||
if (args()) { | if (args()) { | ||||
for (int i = 0; i < args() - 1; i++) { | 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")) { | if (argName(i).equals("range_act_pwm")) { | ||||
treppe->set_active_pwm(arg(i).toInt(), VORGABE_PROZENT); | treppe->set_active_pwm(arg(i).toInt(), VORGABE_PROZENT); | ||||
}); | }); | ||||
this->on("/terminal", HTTP_POST, [this]() { | this->on("/terminal", HTTP_POST, [this]() { | ||||
// Serial.printf("got /terminal\n"); | |||||
// logf("got /terminal\n"); | |||||
if (tbuf_head) { | if (tbuf_head) { | ||||
send(200, "text/plain", tbuf); | send(200, "text/plain", tbuf); | ||||
tbuf_head = 0; | tbuf_head = 0; |
Serial.printf("DIM_LDR: start: %d, ziel: %d\n", dimmer->start_pwm, | Serial.printf("DIM_LDR: start: %d, ziel: %d\n", dimmer->start_pwm, | ||||
dimmer->ziel_pwm); | dimmer->ziel_pwm); | ||||
return true; | return true; | ||||
} else // DIM_STUFEN | |||||
{ | |||||
} else { // DIM_STUFEN | |||||
Serial.printf("DIM_STUFEN: stufe: %d, start: %d, ziel: %d\n", | Serial.printf("DIM_STUFEN: stufe: %d, start: %d, ziel: %d\n", | ||||
dimmer->stufe, dimmer->start_pwm, dimmer->ziel_pwm); | dimmer->stufe, dimmer->start_pwm, dimmer->ziel_pwm); | ||||
if (dimmer->stufe >= stufen - 1) | if (dimmer->stufe >= stufen - 1) | ||||
return true; | return true; | ||||
dimmer->stufe++; | dimmer->stufe++; | ||||
} else // LR_RUNTER | |||||
{ | |||||
} else { // LR_RUNTER | |||||
if (dimmer->stufe <= 0) | if (dimmer->stufe <= 0) | ||||
return true; | return true; | ||||
dimmer->stufe--; | dimmer->stufe--; | ||||
else | else | ||||
dimmer->stufe = stufen - 1; | 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 | } 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) { | if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN) { | ||||
} | } | ||||
} | } | ||||
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; | |||||
// 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; | |||||
} | |||||
if (pegel == 1 && pegel_alt[index] == 0) { | |||||
pegel_alt[index] = pegel; | |||||
return true; | |||||
} else { | |||||
pegel_alt[index] = pegel; | |||||
return false; | |||||
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<bool>(pegel); | |||||
} | } | ||||
float Treppe::read_ldr() { | float Treppe::read_ldr() { | ||||
// follow up: averaging over many samples? | // follow up: averaging over many samples? | ||||
float ldr = read_ldr(); | float ldr = read_ldr(); | ||||
if (ldr < parameters.ldr_schwelle) { | |||||
if (ldr < param.ldr_schwelle) { | |||||
active = 1; | active = 1; | ||||
} | } | ||||
if (ldr > parameters.ldr_schwelle + LDR_HYS) { | |||||
if (ldr > param.ldr_schwelle + LDR_HYS) { | |||||
active = 0; | active = 0; | ||||
} | } | ||||
return active; | return active; | ||||
// TODO wenn LDR geändert => idle_pwm_soll anpassen | // TODO wenn LDR geändert => idle_pwm_soll anpassen | ||||
// fsm_pend.ldr_changed = true; | // fsm_pend.ldr_changed = true; | ||||
fsm_inputs.ldr_schwelle = check_ldr(); | fsm_inputs.ldr_schwelle = check_ldr(); | ||||
#ifdef DEBUG_TIMING | #ifdef DEBUG_TIMING | ||||
m = micros(); | m = micros(); | ||||
#endif | #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; | fsm_inputs.anim_beendet = fsm_pend.anim_beendet; | ||||
#ifdef DEBUG_TIMING | #ifdef DEBUG_TIMING | ||||
fsm_outputs.status == ST_AUFDIMMEN_RUNTER || | fsm_outputs.status == ST_AUFDIMMEN_RUNTER || | ||||
fsm_outputs.status == ST_ABDIMMEN_RUNTER) { | fsm_outputs.status == ST_ABDIMMEN_RUNTER) { | ||||
if (fsm_pend.anim_beendet) | 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); | idle_pwm_ist); | ||||
else | else | ||||
fsm_pend.anim_beendet = dimmer_tick(&dimmer_stufen, DIM_STUFEN); | fsm_pend.anim_beendet = dimmer_tick(&dimmer_stufen, DIM_STUFEN); | ||||
if (!fsm_pend.anim_beendet) { | if (!fsm_pend.anim_beendet) { | ||||
fsm_pend.anim_beendet = dimmer_tick(&dimmer_ldr, DIM_LDR); | 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 | #ifdef DEBUG_TIMING | ||||
// WARNING: before getting Parameters of Flash, make sure plausible parameters | // WARNING: before getting Parameters of Flash, make sure plausible parameters | ||||
// are written in flash! | // 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(13, OUTPUT); | ||||
pinMode(0, OUTPUT); | pinMode(0, OUTPUT); | ||||
Serial.printf("Treppe: stufen=%d\n", stufen); | Serial.printf("Treppe: stufen=%d\n", stufen); | ||||
} | } | ||||
void Treppe::saveParam() { | |||||
void Treppe::save_param_to_eeprom() { | |||||
EEPROM.put(EEP_START_ADDR, | 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 | EEPROM.commit(); // write "EEPROM"-section to flash | ||||
} | } | ||||
void Treppe::set_idle_pwm_max(const uint16_t value, | void Treppe::set_idle_pwm_max(const uint16_t value, | ||||
const vorgabe_typ_t vorgabe_typ) { | const vorgabe_typ_t vorgabe_typ) { | ||||
if (vorgabe_typ == VORGABE_PROZENT) { | 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) { | } 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, | void Treppe::set_active_pwm(const uint16_t value, | ||||
const vorgabe_typ_t vorgabe_typ) { | const vorgabe_typ_t vorgabe_typ) { | ||||
if (vorgabe_typ == VORGABE_PROZENT) { | if (vorgabe_typ == VORGABE_PROZENT) { | ||||
parameters.active_pwm = 4095 * value / 100; | |||||
param_pend.active_pwm = 4095 * value / 100; | |||||
} else if (vorgabe_typ == VORGABE_12BIT) { | } 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) { | 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) { | 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, | void Treppe::set_ldr_schwelle(const uint16_t value, | ||||
const vorgabe_typ_t vorgabe_typ) { | const vorgabe_typ_t vorgabe_typ) { | ||||
if (vorgabe_typ == VORGABE_PROZENT) { | if (vorgabe_typ == VORGABE_PROZENT) { | ||||
// ?! | // ?! | ||||
parameters.ldr_schwelle = 10 * value / 100; | |||||
param_pend.ldr_schwelle = 10 * value / 100; | |||||
} else if (vorgabe_typ == VORGABE_12BIT) { | } 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); | |||||
} | } |
uint16_t active_pwm = 2000; | uint16_t active_pwm = 2000; | ||||
uint16_t ldr_schwelle = 2; // activation value for FSM [lx] | 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; | uint16_t idle_pwm_soll = 0; | ||||
struct fsm_pending_inputs_t { | struct fsm_pending_inputs_t { | ||||
bool anim_beendet = true; | bool anim_beendet = true; | ||||
bool sensor_unten = false; | bool sensor_unten = false; | ||||
bool last_s_unten = false; | |||||
bool web_ctrl_s_unten = false; | |||||
bool sensor_oben = false; | bool sensor_oben = false; | ||||
bool last_s_oben = false; | |||||
bool web_ctrl_s_oben = false; | |||||
bool ldr_changed = false; | bool ldr_changed = false; | ||||
}; | }; | ||||
fsm_pending_inputs_t fsm_pend; | fsm_pending_inputs_t fsm_pend; | ||||
enum fsm_laufrichtung_t { LR_RUNTER = 0, LR_HOCH = 1 }; | enum fsm_laufrichtung_t { LR_RUNTER = 0, LR_HOCH = 1 }; | ||||
enum fsm_dimmrichtung_t { DR_ABDIMMEN = 0, DR_AUFDIMMEN = 1 }; | enum fsm_dimmrichtung_t { DR_ABDIMMEN = 0, DR_AUFDIMMEN = 1 }; | ||||
void read_sensors(); | |||||
void print_state_on_change(); | |||||
/* DIMM */ | /* DIMM */ | ||||
// bool dimmer(dimmer_t* dimmer, bool dim_type); | |||||
bool dimmer_tick(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, | void start_animation(dimmer_t *dimmer, bool dim_type, uint16_t on_pwm, | ||||
uint16_t off_pwm); | uint16_t off_pwm); | ||||
// void berechne_dimmer(dimmer_t* dimmer, bool dim_type); | |||||
void print_state_on_change(); | |||||
/* LDR */ | /* LDR */ | ||||
bool read_sensor(int sensor); | bool read_sensor(int sensor); | ||||
void task(); // call periodically | void task(); // call periodically | ||||
// Parameter section | // 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_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_active_pwm(const uint16_t value, const vorgabe_typ_t vorgabe_typ); | ||||
void set_time_ldr(const uint16_t value); | void set_time_ldr(const uint16_t value); | ||||
void set_time_per_stair(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 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 | #endif // __TREPPE_H |