116 Commits
Author SHA1 Message Date
Simon Schmidt 1686b9ea2a v1.0.1 ldr corrected 2021-09-06 13:42:55 +02:00
schmidtsi76327 8c45c65d00 templ ini update 2021-09-06 00:46:07 +02:00
schmidtsi76327 6bd0844927 got parameter fetch working beta only 2021-09-06 00:41:11 +02:00
schmidtsi76327 b309c0b207 formatting 2021-09-04 10:29:09 +02:00
bartschdo76253 767df957cc ldr schwelle [lx], parameter change when inactive 2021-07-25 17:38:12 +02:00
bartschdo76253 0d6f0b28e2 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-25 17:05:20 +02:00
bartschdo76253 937f7f09e7 new ldr algo 2021-07-25 17:05:14 +02:00
schmidtsi76327 6ae3f5690f add to TODO 2021-07-22 21:50:01 +02:00
schmidtsi76327 7c770a7802 change terminal reload to fetch API, use promises, DOMContentLoaded etc. 2021-07-22 21:49:22 +02:00
schmidtsi76327 6807d0f0af add pending settings buffer, gets written in RUHEZUSTAND, add TODO point ! 2021-07-22 21:25:24 +02:00
schmidtsi76327 770c2436fd change read sensors, trigger via web possible, modify js to fetch with HTTP_POST 2021-07-22 21:08:23 +02:00
schmidtsi76327 3145949020 use fetch and update js and add some buttons for webpage 2021-07-22 03:42:51 +02:00
schmidtsi76327 ca938ef3dd TODO update 2021-07-19 12:36:24 +02:00
schmidtsi76327 f8fac7acfb added win debug script 2021-07-19 12:34:06 +02:00
bartschdo76253 9ed1b24316 variable viewport -> besser usability on phones 2021-07-19 12:22:45 +02:00
schmidtsi76327 125b39a418 added log messages 2021-07-19 12:01:20 +02:00
schmidtsi76327 e47cae30a8 merge conflicts 2021-07-19 11:57:12 +02:00
schmidtsi76327 b2ff66d44c updates to change other parameters from http 2021-07-19 11:54:37 +02:00
bartschdo76253 c23b9f2bc6 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-19 11:44:05 +02:00
bartschdo76253 31c268487c EEP implementation 2021-07-19 11:31:32 +02:00
schmidtsi76327 ad21d73fbb changed pwm setters and httpserver call 2021-07-19 11:29:51 +02:00
bartschdo76253 42a927e383 struct for treppe parameters ->eeprom 2021-07-19 11:08:13 +02:00
bartschdo76253 13db3da082 checked virtual "EEPROM" -> works 2021-07-16 21:40:51 +02:00
schmidtsi76327 9518c06fd9 format change 2021-07-11 01:45:00 +02:00
schmidtsi76327 2820869e14 some formating, add variadic templ for logf() 2021-07-10 04:12:50 +02:00
schmidtsi76327 6e810fad59 added matlab slx model 2021-07-09 13:39:07 +02:00
bartschdo76253 79a9eecaad doku details 2021-07-08 10:43:04 +02:00
schmidtsi76327 1189b7c3a4 doku.md create TODO-List 2021-07-08 03:01:10 +02:00
schmidtsi76327 7643961ed2 got dimming working, dimming from ldr, can be testet via webbrowser; dynamic dimmer_t used for both dimmers, can be selected via dimmer_type_t (DIM_STUFEN, DIM_LDR) 2021-07-08 02:54:08 +02:00
schmidtsi76327 6cc52dc460 add ifdef DEBUG_TIMING for fiming measurments 2021-07-07 21:27:07 +02:00
schmidtsi76327 d3ed19e639 add structs to treppe to clear understanding 2021-07-07 21:13:58 +02:00
schmidtsi76327 d55da4e6d7 der linker dieser sack, double declatartion of FSM, FSM3.0 implemented ! 2021-07-07 20:52:20 +02:00
schmidtsi76327 f677f18681 corrected double in FSM2, debug in treppe.cpp ! 2021-07-07 19:33:20 +02:00
schmidtsi76327 f027478e2e FSM 3.0 2021-07-07 18:28:38 +02:00
schmidtsi76327 5986beb10c add FSM3.0 src code not impl yet, add header guards and format main 2021-07-07 18:28:05 +02:00
Pupsmuckel f57e875a17 HTML Änderung 2021-07-07 17:13:40 +02:00
Pupsmuckel d16f3823b8 HTML Änderung 2021-07-07 17:08:26 +02:00
Pupsmuckel a5ac7d358b puu 2021-07-07 16:58:27 +02:00
bartschdo76253 0cd46a3c9f wrong ldr lux-calc (see Excel sheet, mixed x y ) 2021-07-06 14:19:35 +02:00
schmidtsi76327 3a93b8a002 changed static var in activate 2021-07-06 01:06:46 +02:00
schmidtsi76327 0e5085c008 small updates to treppe 2021-07-05 21:33:08 +02:00
schmidtsi76327 7177472ea6 small updates to treppe 2021-07-05 21:32:37 +02:00
schmidtsi76327 03d0cfedd1 small updates to treppe 2021-07-05 21:20:00 +02:00
schmidtsi76327 66d220cdb0 can set idle_pwm from webserver, but not working properly 2021-07-05 19:51:55 +02:00
schmidtsi76327 2754bd5247 update webserver html,js,css 2021-07-05 18:15:57 +02:00
bartschdo76253 f62a18fe66 re-addded idle_bright_internal 2021-07-05 16:59:22 +02:00
bartschdo76253 2139ff5943 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-05 16:57:11 +02:00
bartschdo76253 6a04a4d1c9 improved activate_idle 2021-07-05 16:57:09 +02:00
schmidtsi76327 630250da78 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-05 16:16:43 +02:00
schmidtsi76327 35ba3e7573 updates format style 2021-07-05 16:15:47 +02:00
bartschdo76253 53efb0c309 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-05 15:56:19 +02:00
bartschdo76253 c1e24d633b activate / inactivate idle brightess w LDR 2021-07-05 15:54:35 +02:00
schmidtsi76327 5e36ef55df format 2021-07-05 15:16:43 +02:00
schmidtsi76327 6b5cabb1f4 repo PCA9685 lib 2021-07-05 14:54:23 +02:00
bartschdo76253 37380cbebc xlsx for ldr regression doku 2021-07-05 11:51:25 +02:00
bartschdo76253 8c507083a7 bugfixes 2021-07-05 11:48:31 +02:00
bartschdo76253 2f6502ce20 added LDR evaluation + sensor edge detection 2021-07-05 11:40:45 +02:00
bartschdo76253 278179fa6e doku issues 2021-07-05 10:00:21 +02:00
bartschdo76253 f38ef0ed0e Testing, Doku, Issues 2021-07-05 09:57:56 +02:00
schmidtsi76327 f2a9ed2888 clangtidy cleanups and added checks to platformio.ini 2021-07-04 14:45:14 +02:00
schmidtsi76327 1662079547 INT_TIME define added 2021-07-03 21:11:32 +02:00
schmidtsi76327 1e8d24dc40 FSM mostly working, need to implement bufferd param changes 2021-07-03 21:04:24 +02:00
schmidtsi76327 af40298378 somehow working, starting to refactor 2021-07-03 18:10:30 +02:00
schmidtsi76327 8351a6430c forgot smtn in print, spaces to 4 2021-07-03 17:51:14 +02:00
schmidtsi76327 b2ddc978b6 copy pasta :| 2021-07-03 17:46:31 +02:00
schmidtsi76327 22f141e2cd version model 1.29 added state for inaktiv = LDR ... 2021-07-03 17:44:46 +02:00
schmidtsi76327 f5d6e376c6 FSM2: rm rtm code, change print, add ldr_schwelle 2021-07-03 17:36:10 +02:00
bartschdo76253 eeac10c66f new FSM 2021-07-03 17:09:35 +02:00
schmidtsi76327 e9d16a80d4 FSM 2.0 einfacher xD lol: ) 2021-07-03 13:52:52 +02:00
schmidtsi76327 dcae074b55 pushpull sensor logik 2021-07-03 12:56:58 +02:00
schmidtsi76327 472eba7977 updates to state machine with print function 2021-07-03 12:48:17 +02:00
schmidtsi76327 6a398d9ba0 simulink stateflow compiling 2021-07-03 11:33:20 +02:00
schmidtsi76327 f28aa2df8b stripped out RTM Model interface and custom types from matlab 2021-07-03 11:31:46 +02:00
schmidtsi76327 754da9f931 added simulink stateflow c++ fsm 2021-07-03 11:21:18 +02:00
schmidtsi76327 df2a8fa1e3 delete remove .vscode folder 2021-07-02 18:23:51 +02:00
schmidtsi76327 dc159a35d0 readded submodule 2021-07-02 18:21:32 +02:00
schmidtsi76327 2378ca80b9 gitignore 2021-07-02 17:53:31 +02:00
schmidtsi76327 79ff1f0d33 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-07-02 17:51:31 +02:00
schmidtsi76327 6a36971406 small corrections 2021-07-02 17:51:16 +02:00
bartschdo76253 714fcb4b18 tested interrupts on GPIOs 2, 12 2021-07-02 16:25:54 +02:00
schmidtsi76327 712acf3541 all right 2021-06-30 20:33:51 +02:00
schmidtsi76327 df89c9716c Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-30 20:33:26 +02:00
schmidtsi76327 66e8ddb2d9 updates to http terminal 2021-06-30 20:33:16 +02:00
bartschdo76253 5b197288bc back to normal 2021-06-30 16:50:00 +02:00
bartschdo76253 a9f098097c switched to linear phase balance 2021-06-30 16:09:46 +02:00
bartschdo76253 a0f6a5aec3 pin optimizations 2021-06-30 11:23:56 +02:00
schmidtsi76327 633b99f818 missing ret val 2021-06-30 09:34:11 +02:00
bartschdo76253 5d32392844 merged treppe.cpp 2021-06-28 15:49:07 +02:00
bartschdo76253 50e714e5f8 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-28 15:48:29 +02:00
bartschdo76253 e0bc75826f added OE Pin for PCB 2021-06-28 15:47:10 +02:00
schmidtsi76327 3d13e761f4 update templ.ini and doku 2021-06-27 02:01:25 +02:00
schmidtsi76327 3c824bfc92 much simpler callback approach due to serveStatic with directories !!! 2021-06-27 01:56:30 +02:00
schmidtsi76327 9ea541a1b4 lambda error 2021-06-26 21:11:19 +02:00
schmidtsi76327 b89604edc3 simple serial monitor in httpserver 2021-06-26 10:49:29 +02:00
schmidtsi76327 4e6445fea8 modify script for new way of serving gz files 2021-06-26 09:33:37 +02:00
schmidtsi76327 10b57ca516 further improvments, [this] in lambda fcn callback, compressed gz webfiles via streamFile() 2021-06-26 09:21:34 +02:00
schmidtsi76327 e8329f2587 moved files, this in on callback for httpserver class 2021-06-26 09:02:55 +02:00
schmidtsi76327 014aa028d7 move http and ota to lib/ for testing, add #pragma once include guards 2021-06-26 07:33:12 +02:00
schmidtsi76327 b47f778fc1 weitere anpassungen an pwm 2021-06-25 21:10:07 +02:00
schmidtsi76327 c7eaffda00 moved to treppe.h instead of pwm.h :) 2021-06-25 19:23:02 +02:00
schmidtsi76327 69e1e869a5 old pwm 2021-06-25 19:14:30 +02:00
schmidtsi76327 1a284080e8 typo 2021-06-25 19:13:04 +02:00
schmidtsi76327 3490e7ba44 Merge branch 'master' into test 2021-06-25 19:11:58 +02:00
schmidtsi76327 d059c3d72d working, but need to write test 2021-06-25 18:35:16 +02:00
bartschdo76253 33499beb32 zero duty cycle fix 2021-06-25 15:41:34 +02:00
bartschdo76253 38c81ae182 main cleanup 2021-06-25 15:25:09 +02:00
bartschdo76253 a8ceb258b8 leds light up at boot 2021-06-25 15:17:38 +02:00
bartschdo76253 7e5a6fac9f doku 2021-06-25 11:03:17 +02:00
bartschdo76253 b7ba521c59 first approach with sensor controlled led sequence 2021-06-25 10:55:27 +02:00
schmidtsi76327 55ebd21975 test 2021-06-25 04:53:06 +02:00
schmidtsi76327 2b2a135bd5 reorganzie main 2021-06-24 19:46:24 +02:00
bartschdo76253 a400b0464d deleted Wire setClock 2021-06-24 19:34:26 +02:00
schmidtsi76327 2d9be85b09 added lib submodule 2021-06-24 18:38:30 +02:00
schmidtsi76327 33b9f0150e nicht so :) 2021-06-24 18:32:38 +02:00
schmidtsi76327 48d0dc50f7 added library 2021-06-24 18:28:00 +02:00
schmidtsi76327 cdb34a3cbf make it clear what happens with new pca lib 2021-06-24 16:51:38 +02:00
35 changed files with 1677 additions and 587 deletions
+3
View File
@@ -1,6 +1,9 @@
.pio .pio
.vscode .vscode
.vscode/*
.vscode/**
compress compress
data_gz
platformio.ini platformio.ini
include/wifi_credentials.h include/wifi_credentials.h
include/*.gz.h include/*.gz.h
+3
View File
@@ -0,0 +1,3 @@
[submodule "lib/PCA9685-Arduino"]
path = lib/PCA9685-Arduino
url = https://github.com/NachtRaveVL/PCA9685-Arduino
-7
View File
@@ -1,7 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}
-52
View File
@@ -1,52 +0,0 @@
{
"files.associations": {
"random": "cpp",
"array": "cpp",
"*.tcc": "cpp",
"deque": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"string_view": "cpp",
"memory": "cpp",
"ranges": "cpp",
"initializer_list": "cpp",
"utility": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"map": "cpp",
"set": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"iosfwd": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
}
}
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/python3
import os, gzip
# https://www.mischianti.org/2020/10/26/web-server-with-esp8266-and-esp32-byte-array-gzipped-pages-and-spiffs-2/
def convert_to_gzip(src, out, f):
input_file = f'{src}{f}'
output_file = f'{out}{f}.gz.h'
output_charp = f'{f.replace(".", "_")}_gz'
top = ''
with open(input_file, 'rb') as f_in:
gz = gzip.compress(f_in.read())
gzlen = len(gz)
top += f'// filename: {f}.gz.h\n'
top += f'#define {output_charp}_len {gzlen}\n'
top += f'const char {output_charp}[] = '
top += '{'
with open(output_file, 'wb') as f_out:
for i, b in enumerate(gz):
if not i%10:
top += '\n '
top += f'0x{b:02X}, '
top = top[:-2]
top += '};'
f_out.write(top.encode(encoding='utf-8'))
src='data/'
out='compress/'
if not 'compress' in os.listdir():
os.mkdir('compress')
for f in os.listdir(src):
convert_to_gzip(src, out, f)
+9 -32
View File
@@ -1,38 +1,15 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, gzip import os, gzip
# https://www.mischianti.org/2020/10/26/web-server-with-esp8266-and-esp32-byte-array-gzipped-pages-and-spiffs-2/ # https://stackoverflow.com/questions/8156707/gzip-a-file-in-python
def convert_to_gzip(src, out, f): src_dir='data'
input_file = f'{src}{f}' out_dir='data_gz'
output_file = f'{out}{f}.gz.h'
output_charp = f'{f.replace(".", "_")}_gz'
top = '' if not 'data_gz' in os.listdir():
with open(input_file, 'rb') as f_in: os.mkdir('data_gz')
gz = gzip.compress(f_in.read())
gzlen = len(gz)
top += f'// filename: {f}.gz.h\n' for f in os.listdir(src_dir):
top += f'#define {output_charp}_len {gzlen}\n' with open(f'{src_dir}/{f}', 'rb') as f_in:
top += f'const char {output_charp}[] = ' with gzip.open(f'{out_dir}/{f}.gz', 'wb') as f_out:
top += '{' f_out.writelines(f_in)
with open(output_file, 'wb') as f_out:
for i, b in enumerate(gz):
if not i%10:
top += '\n '
top += f'0x{b:02X}, '
top = top[:-2]
top += '};'
f_out.write(top.encode(encoding='utf-8'))
src='data/'
out='compress/'
if not 'compress' in os.listdir():
os.mkdir('compress')
for f in os.listdir(src):
convert_to_gzip(src, out, f)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

+41 -38
View File
@@ -1,65 +1,68 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head> <head>
<title>ESP8266 Treppenlicht</title> <title>ESP8266 Treppenlicht</title>
<!-- main style sheet -->
<link href="/favicon.png" rel="icon" type="image/png" sizes="10x10"> <link href="/favicon.png" rel="icon" type="image/png" sizes="10x10">
<link href="/style.css" rel="stylesheet" type="text/css"> <link href="/style.css" rel="stylesheet" type="text/css">
</head> </head>
<body> <body>
<div class="kopfzeile" style="text-align: center;"> <div class="topbar">Treppenlicht</div>
<b>Treppenlicht</b>
<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>
<div class="ueberschrift"> <div class="param_block">
Helligkeit Active Brightness: <output id="out_act_pwm" class="val_range">50</output> %
<!--<label id="label_pwm">
</label>-->
<div class="slider"> <div class="slider">
<input type="range" class="regler" id="helligkeit" name="rangeInput" 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">
oninput="amount1.value=helligkeit.value">
<br>
<output name="amount1" id="amount1" for="helligkeit">50</output>
</div>
</div>
<div class="ueberschrift">
Helligkeit bei Dunkelheit
<!--<label id="label_pwm_dark">
</label>-->
<div class="slider">
<input type="range" class="regler" id="helligkeit_dunkel" name="rangeInput" min="0" max="100" value="50"
oninput="amount2.value=helligkeit_dunkel.value">
<br>
<output name="amount2" id="amount2" for="helligkeit_dunkel">50</output>
</div> </div>
</div> </div>
<div class="ueberschrift"> <div class="param_block">
Laufgeschwindigkeit Idle Brightness Maximum: <output id="out_idl_pwm" class="val_range">50</output> %
<!--<label id="label_geschwindigkeit"> <label id="note">[100% == Active Brightness]</label>
</label>-->
<div class="slider"> <div class="slider">
<input type="range" class="regler" id="geschwindigkeit" name="rangeInput" 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">
oninput="amount3.value=geschwindigkeit.value"> </div>
<br> <label id="note">idle brightness gets controlled via LDR measurments</label>
<output name="amount3" id="amount3" for="geschwindigkeit">50</output> </div>
<div class="param_block">
Time per stair [ms]: <output id="out_tim_sta" class="val_range">300</output> ms
<div class="slider">
<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="ueberschrift"> <div class="param_block">
Licht-An-Zeit Time LDR [ms]: <output id="out_tim_ldr" class="val_range">500</output> ms
<!-- <label id="label_time">
</label>-->
<div class="slider"> <div class="slider">
<input type="range" class="regler" id="time" name="rangeInput" min="0" max="100" value="50" <input type="range" class="regler" id="range_tim_ldr" data-output="out_tim_ldr" min="0" max="5000" value="500">
oninput="amount4.value=time.value">
<br>
<output name="amount4" id="amount4" for="time">50</output>
</div> </div>
</div> </div>
<div class="param_block">
LDR Schwelle [lx]: <output id="out_ldr_shw" class="val_range">50</output> lx
<div class="slider">
<input type="range" class="regler" id="range_ldr_shw" data-output="out_ldr_shw" min="0" max="1000" value="50">
</div>
</div>
<div class="terminal">
<input type="button" id="clear_term" value="clear">
<input type="checkbox" id="scroll" name="scroll" value="scroll" checked>
<label for="scroll"> autoscroll </label>
<textarea id="term">waiting for log messages ...&#10;</textarea>
</div>
</body> </body>
<script src="/input.js"></script> <script src="/input.js"></script>
+118 -6
View File
@@ -1,8 +1,120 @@
var slider = document.getElementById("range1"); let rangeValues = {};
var output = document.getElementById("l_pwm"); let xhrUpd = new XMLHttpRequest();
output.innerHTML = slider.value; // Display the default slider value
// Update the current slider value (each time you drag the slider handle) xhrUpd.onreadystatechange = function () {
slider.oninput = function() { if (xhrUpd.readyState == 4) {
output.innerHTML = this.value; if (xhrUpd.status == 200) {
console.log("xhrUpd: ", xhrUpd.responseText);
} }
else {
console.log("xhrUpd: status=", xhrUpd.status);
}
}
}
function reloadRangeValues() {
let url = "/update";
// if there are scheduled updates, send them
if (Object.keys(rangeValues).length > 0) {
let params = [];
for (let p in rangeValues)
params.push(encodeURIComponent(p) + "=" + encodeURIComponent(rangeValues[p]));
params = params.join("&");
xhrUpd.open("POST", url, true);
xhrUpd.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhrUpd.send(params);
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));
};
function updateParameters() {
fetch('/parameters', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: ''
})
.then(response => response.json())
.then(json_str => {
const active_pwm = Math.round(json_str.active_pwm / 4095 * 100);
document.querySelector('#range_act_pwm').value = active_pwm;
document.querySelector('#out_act_pwm').value = active_pwm;
const idle_pwm_max = Math.round(json_str.idle_pwm_max / json_str.active_pwm * 100);
document.querySelector('#range_idl_pwm').value = idle_pwm_max;
document.querySelector('#out_idl_pwm').value = idle_pwm_max;
document.querySelector('#range_tim_sta').value = json_str.time_per_stair;
document.querySelector('#out_tim_sta').value = json_str.time_per_stair;
document.querySelector('#range_tim_ldr').value = json_str.time_ldr;
document.querySelector('#out_tim_ldr').value = json_str.time_ldr;
document.querySelector('#range_ldr_shw').value = json_str.ldr_schwelle;
document.querySelector('#out_ldr_shw').value = json_str.ldr_schwelle;
})
.catch(error => console.log('Error:', error));
};
document.addEventListener('DOMContentLoaded', () => {
setInterval(reloadTerminal, 1000);
setInterval(reloadRangeValues, 1000);
updateParameters();
// 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 = '';
};
});
+61 -33
View File
@@ -1,45 +1,50 @@
html { html {
font-size: 16px; font-size: 16px;
font-family: sans-serif, Arial, Helvetica; font-family: sans-serif, Arial, Helvetica;
background-color: #d4d4d4; background-color: #ffffff;
height: 100%; height: 100%;
background-image: url('Background.png');
background-repeat: repeat;
background-size: 150% 150%;
} }
body { body {
height: 100%; height: 100%;
margin: 0 auto;
border: none;
border-radius: 3; border-radius: 3;
} }
.topbar { .topbar {
padding: 1em; padding: 10px;
background-color: #1f1f1f; background-color: #585858;
color: white; color: white;
font-size: x-large; font-size: xx-large;
text-align: center; text-align: center;
} }
.ueberschrift{ .param_block{
color: #ffffff; padding: 1em;
font-size: 50px; color: #000000;
width: 100%; border: 1px solid darkred;
text-align: center; font-size: x-large;
width: 80%;
}
.val_range {
font-weight: bold;
} }
.regler { .regler {
/* -webkit-appearance: none; */
-webkit-appearance: none; height: 50px;
height: 30px;
width: 100%; width: 100%;
border-radius: 20px; border-radius: 20px;
outline: black; outline: black;
background-color: rgb(176, 188, 228); background-color: rgb(176, 188, 228);
} }
.regler::-webkit-slider-thumb{
#note {
font-size: medium;
font-style: italic;
}
/* .regler::-webkit-slider-thumb{
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
width: 5%; width: 5%;
@@ -47,31 +52,21 @@ body {
border-radius: 10px; border-radius: 10px;
background-color: rgb(107, 122, 192); background-color: rgb(107, 122, 192);
cursor:pointer; cursor:pointer;
} } */
input[type=range]::-webkit-slider-thumb{ /* input[type=range]::-webkit-slider-thumb{
-webkit-appearance: none; -webkit-appearance: none;
border:none; border:none;
height: 30px; height: 30px;
width: 4%; width: 4%;
border-radius: 30px; border-radius: 30px;
} } */
.slider { .slider {
width: 100%; margin: 1%;
} }
.kopfzeile{
color: #1f1f1f;
font-size: 50px;
width: 100%;
background-color: #8d8a8a;
}
/*-------------------------------------------------------*/ /*-------------------------------------------------------*/
/*Switch: /*Switch:
.switch { .switch {
position: relative; position: relative;
@@ -103,4 +98,37 @@ input:checked + .slider:before {
-ms-transform: translateX(26px); -ms-transform: translateX(26px);
transform: translateX(26px); transform: translateX(26px);
} }
*/
.terminal {
margin:5%;
padding: 1%;
width: 80%;
border: 1px solid black;
border-radius: 5px;
}
#term {
font-size: large;
width: 100%;
height: 20em;
}
#clear_term {
margin: 2px;
}
input[type="number"] {
width: 100px;
}
input:invalid+span:after {
content: '✖';
padding-left: 5px;
}
input:valid+span:after {
content: '✓';
padding-left: 5px;
}
+76 -3
View File
@@ -54,15 +54,88 @@ else
server.streamFile(f, mime::getContentType(SRH::_path), requestMethod); server.streamFile(f, mime::getContentType(SRH::_path), requestMethod);
``` ```
### HW issues
- GPIO2 used as input -> must be high during startup
- PCB Solution: cut trace to GPIO2, solder bridge to GPIO16
- -> disadvantage: GPIO16 is not interrupt capable
Webserver on v0.3.0 now working with LittleFS
### FSM 2 - to do
- stairway light switches off after timeout
- switches concurrently on again if sensor is still high
- desired behavior? Defective Sensor would cause continuos animation
- edge detection / interrupts as solution ?
### LED_sequence_v1:
TODO:
- disable led stripes after defined time (webserver paramter?)
- define what to do if people enter stairs from different directions
- CAUTION: Sensor-Deadtime at LEAST 8 seconds
- --> switch off with person leaving stairs might not be possible
### Webserver on v0.3.0 now working with LittleFS
TODO: TODO:
- check dir for files automatic - check dir for files automatic
- move handleNotFound to httpserver.h - move handleNotFound to httpserver.h
- maybe compress files ? - maybe compress files ?
LED Flickering issue ### LED Flickering issue
https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15 https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15
PlatformIO Library veraltet !!
PlatformIO Library veraltet
### TIMER in OTA unterbrechen !!!!!
### further improvments
with streamFile gzip encoded Files can be sent
this reduces space on fs !
new easier script needed to just convert to .gz
maybe measure timings on ESP
__=> use serveStatic because way simpler !__
__=> serverStatic("/") works wonders__
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARHRRHRGH
Two implementations of FSM are not that good,
linker puts them together ?!?
:):):):):):):)
=> maybe investigate for doc
### TODO Treppe
- dynamic lighting with ldr
- http control over active pwm ... => set_active_pwm()
-> is implemntiert, kann mit % oder abs eingestellt werden
- 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 ?
-> wird hochgedimmt beim einschalten von 0
- on/off switch http
- use logging to serial http monitor with httpserver.logt()
-> is used for some status updates
- behavior when someone enters stairway from opposite direction while animation is running?
-> currently ignored, second persons walks in darkness
-> animation from both sides?
-> problem: person 1 leaving stairway might pass the sensor right after person 2 -> person 1 leaving not detected
- 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?
- active brightness can be lower than idle in the moment
- change idle to precentage of active !!
- Webpage needs to load settings from eeprom !!
-48
View File
@@ -1,48 +0,0 @@
#ifndef __HTTPSERVER_H
#define __HTTPSERVER_H
#include "filesys.h"
#include <ESP8266WebServer.h>
class HTTPServer : public ESP8266WebServer {
private:
const char* rootDir;
bool addRootFileHandler();
bool formatFS() {
return format_fs();
}
void listRoot() {
ls(rootDir);
}
public:
HTTPServer(const int _port, const char* _rootDir) :
ESP8266WebServer(_port), rootDir(_rootDir)
{ }
~HTTPServer()
{
Serial.printf("[HTTPServer] shut down ...\n\r");
}
bool start() {
if(!mount_fs())
return false;
Serial.printf("[HTTPServer] LittleFS mounted !\n\r");
Serial.printf("[HTTPServer] root:\n\r");
this->listRoot();
Serial.printf("\n\r");
if( this->addRootFileHandler() ){
this->begin();
Serial.printf("[HTTPServer] Server active on Port 80 !\n\r");
return true;
}
Serial.printf("[HTTPServer] Not starting Server, something went wrong !\n\r");
return false;
}
};
#endif // __HTTPSERVER_H
+4 -1
View File
@@ -1,6 +1,10 @@
#ifndef __OTA_H #ifndef __OTA_H
#define __OTA_H #define __OTA_H
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
void ota_setup() { void ota_setup() {
ArduinoOTA.setPort(8266); ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname("ESP_Treppenlicht"); ArduinoOTA.setHostname("ESP_Treppenlicht");
@@ -44,5 +48,4 @@ void ota_setup() {
} }
#endif // __OTA_H #endif // __OTA_H
-38
View File
@@ -1,38 +0,0 @@
#pragma once
#include "PCA9685.h"
class Treppe {
private:
uint8_t stairs;
uint16_t time_per_stair = 300; // dimmtime per stair [ms]
uint16_t idle_brightness = 200;
uint16_t active_brightness = 2048;
uint8_t direction = 0;
uint8_t state = 0;
uint8_t switch_state = 0;
PCA9685 pwmController;
uint8_t softstart_led(uint8_t led, uint16_t startval, uint16_t stopval);
void ledsequence();
public:
Treppe(uint8_t _stairs) : stairs(_stairs){}
void task(); // call periodically
void setup();
// Parameter section
uint16_t setIdle(uint16_t _idle_brightness);
uint16_t setActive(uint16_t _active_brightness);
uint16_t setTime(uint16_t _time_per_stair);
// Runtime Parameter section
uint8_t setDirection(uint8_t _direction);
uint8_t setState(uint8_t _state);
uint8_t getState() { return state;};
uint8_t getDirection() {return direction;};
};
Submodule lib/PCA9685-Arduino added at a70be39257
-46
View File
@@ -1,46 +0,0 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
+8 -14
View File
@@ -1,15 +1,8 @@
#include "filesys.h" #include "filesys.h"
// listDir("/");
// deleteFile("/hello.txt");
// writeFile("/hello.txt", "Hello ");
// appendFile("/hello.txt", "World!\n\r");
// readFile("/hello.txt");
// listDir("/");
FSInfo fsinfo; FSInfo fsinfo;
bool mount_fs() { auto mount_fs() -> bool {
if(!LittleFS.begin()) { if(!LittleFS.begin()) {
Serial.println("[ERROR] LittleFS.info(), reset ..."); Serial.println("[ERROR] LittleFS.info(), reset ...");
return false; return false;
@@ -32,7 +25,7 @@ bool mount_fs() {
return true; return true;
} }
bool format_fs() { auto format_fs() -> bool {
printf("Formatting FS ! \n\r"); printf("Formatting FS ! \n\r");
return LittleFS.format(); return LittleFS.format();
} }
@@ -58,7 +51,12 @@ void ls(const char * dirname) {
Serial.println(); Serial.println();
} }
void readFile(const char * path) { File open(const char * path) {
return LittleFS.open(path, "r");
}
void printFile(const char * path) {
Serial.printf("Reading file: %s\n\r", path); Serial.printf("Reading file: %s\n\r", path);
File file = LittleFS.open(path, "r"); File file = LittleFS.open(path, "r");
@@ -124,7 +122,3 @@ void deleteFile(const char * path) {
Serial.println("Delete failed"); Serial.println("Delete failed");
} }
} }
@@ -1,16 +1,16 @@
#ifndef __FILESYS_H #pragma once
#define __FILESYS_H
#include <LittleFS.h> #include <LittleFS.h>
// some usefull wrappers for Filesystem
bool mount_fs(); bool mount_fs();
bool format_fs(); bool format_fs();
File open(const char * path);
void ls(const char * dirname); void ls(const char * dirname);
void readFile(const char * path); void printFile(const char * path);
void writeFile(const char * path, const char * message); void writeFile(const char * path, const char * message);
void appendFile(const char * path, const char * message); void appendFile(const char * path, const char * message);
void renameFile(const char * path1, const char * path2); void renameFile(const char * path1, const char * path2);
void deleteFile(const char * path); void deleteFile(const char * path);
#endif // __FILESYS_H
+122
View File
@@ -0,0 +1,122 @@
#include "httpserver.h"
auto HTTPServer::start() -> bool {
if (!mount_fs()) {
logf("cant mount filesystem, EXIT !\n\r");
return false;
}
logf("LittleFS mounted !\n\r");
logf("root:\n\r");
this->listRoot();
logf("\n\r");
// default handler
this->onNotFound([this]() {
String message = "File Not Found\n\n";
message += "URI: ";
message += uri();
message += "\nMethod: ";
message += (method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += args();
message += "\n";
for (uint8_t i = 0; i < args(); i++) {
message += " " + argName(i) + ": " + arg(i) + "\n";
}
send(404, "text/plain", message);
});
// add static root file handler for http
this->serveStatic("/", LittleFS, "/");
this->begin();
logf("Server active on Port 80 !\n\r");
return true;
}
void HTTPServer::start_apps() {
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++) {
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);
logt("set_active_pwm = %d %\n", arg(i).toInt());
}
else if (argName(i).equals("range_idl_pwm")) {
treppe->set_idle_pwm_max(arg(i).toInt(), VORGABE_PROZENT);
logt("set_idle_pwm_max = %d %\n", arg(i).toInt());
}
else if (argName(i).equals("range_tim_sta")) {
treppe->set_time_per_stair(arg(i).toInt());
logt("set_time_per_stair = %d\n", arg(i).toInt());
}
else if (argName(i).equals("range_tim_ldr")) {
treppe->set_time_ldr(arg(i).toInt());
logt("set_time_ldr = %d\n", arg(i).toInt());
}
else if (argName(i).equals("range_ldr_shw")) {
treppe->set_ldr_schwelle(arg(i).toInt(), VORGABE_12BIT);
logt("set_ldr_schwelle = %d %\n", arg(i).toInt());
}
}
}
send(200, "text/plain", "accepted");
});
this->on("/terminal", HTTP_POST, [this]() {
// logf("got /terminal\n");
if (tbuf_head) {
send(200, "text/plain", tbuf);
tbuf_head = 0;
} else {
send(202, "text/plain", "");
}
});
this->on("/parameters", HTTP_POST, [this]() {
logt("got /parameters\n");
char json_str[255];
treppe->param_to_json(json_str, 255);
logt("%s\n", json_str);
send(200, "application/json", json_str);
});
}
template <class... Args>
void HTTPServer::logf(const char *format, Args... args) const {
Serial.print(log_prefix);
Serial.printf(format, args...);
}
void HTTPServer::logt(const char *format, ...) {
va_list args;
va_start(args, format);
// append logging string to local buffer
if (tbuf_head < TBUF_LEN) {
tbuf_head +=
vsnprintf(tbuf + tbuf_head, TBUF_LEN - tbuf_head, format, args);
}
va_end(args);
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef __HTTPSERVER_H
#define __HTTPSERVER_H
// Wrapper for ESP8266WebServer with Filesystem as HTTP source
#include "filesys.h"
#include "treppe.h"
#include <ESP8266WebServer.h>
#include <stdarg.h>
// debug log <ESP8266WebServer.h>
// #define DEBUGV(f,...) do { Serial.printf(PSTR(f), ##__VA_ARGS__); } while (0)
#define TBUF_LEN 256
class HTTPServer : public ESP8266WebServer {
private:
const char *rootDir = "/";
const char *log_prefix = "[HTTPServer] ";
size_t tbuf_head = 0;
char tbuf[TBUF_LEN];
void listRoot() { ls(rootDir); }
Treppe *treppe;
public:
HTTPServer(const int _port, const char *_rootDir, Treppe *_treppe)
: ESP8266WebServer(_port), rootDir(_rootDir), treppe(_treppe) {}
~HTTPServer() { Serial.printf("[HTTPServer] shut down ...\n\r"); }
bool start();
void start_apps();
template <class... Args>
void logf(const char *format, Args... args) const;
void logt(const char *format, ...);
};
#endif // __HTTPSERVER_H
+276
View File
@@ -0,0 +1,276 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
//
// File: FSMTreppe.cpp
//
// Code generated for Simulink model 'FSMTreppe'.
//
// Model version : 1.51
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Wed Jul 7 18:54:01 2021
//
// Target selection: ert.tlc
// Embedded hardware selection: ARM Compatible->ARM Cortex-M
// Code generation objectives: Unspecified
// Validation result: Not run
//
#include "FSMTreppe3.h"
// Named constants for Chart: '<Root>/FSMTreppe'
const uint32_t FSMTreppe_IN_abdimmen_hoch = 1U;
const uint32_t FSMTreppe_IN_abdimmen_ldr = 2U;
const uint32_t FSMTreppe_IN_abdimmen_runter = 3U;
const uint32_t FSMTreppe_IN_aufdimmen_hoch = 4U;
const uint32_t FSMTreppe_IN_aufdimmen_ldr = 5U;
const uint32_t FSMTreppe_IN_aufdimmen_runter = 6U;
const uint32_t FSMTreppe_IN_inaktiv = 7U;
const uint32_t FSMTreppe_IN_ruhezustand = 8U;
const uint32_t FSMTreppe_IN_warten_hoch = 9U;
const uint32_t FSMTreppe_IN_warten_runter = 10U;
// Model step function
void FSMTreppeModelClass::step()
{
// Chart: '<Root>/FSMTreppe' incorporates:
// Inport: '<Root>/anim_beendet'
// Inport: '<Root>/ldr_schwelle'
// Inport: '<Root>/sensor_oben'
// Inport: '<Root>/sensor_unten'
if (FSMTreppe_DW.temporalCounter_i1 < 511U) {
FSMTreppe_DW.temporalCounter_i1 = static_cast<uint16_t>
(FSMTreppe_DW.temporalCounter_i1 + 1U);
}
if (FSMTreppe_DW.is_active_c3_FSMTreppe == 0U) {
FSMTreppe_DW.is_active_c3_FSMTreppe = 1U;
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_inaktiv;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 0U;
} else {
switch (FSMTreppe_DW.is_c3_FSMTreppe) {
case FSMTreppe_IN_abdimmen_hoch:
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 6U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 3U;
}
break;
case FSMTreppe_IN_abdimmen_ldr:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 2U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_inaktiv;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 0U;
}
break;
case FSMTreppe_IN_abdimmen_runter:
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 9U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 3U;
}
break;
case FSMTreppe_IN_aufdimmen_hoch:
// Outport: '<Root>/laufrichtung'
FSMTreppe_Y.laufrichtung = 1U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 4U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_warten_hoch;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 5U;
}
break;
case FSMTreppe_IN_aufdimmen_ldr:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 3U;
}
break;
case FSMTreppe_IN_aufdimmen_runter:
// Outport: '<Root>/laufrichtung'
FSMTreppe_Y.laufrichtung = 0U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 7U;
if ((FSMTreppe_U.anim_beendet == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_warten_runter;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 8U;
}
break;
case FSMTreppe_IN_inaktiv:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 0U;
if (FSMTreppe_U.ldr_schwelle == 1U) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_aufdimmen_ldr;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
}
break;
case FSMTreppe_IN_ruhezustand:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 3U;
if (FSMTreppe_U.sensor_unten == 1U) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_aufdimmen_hoch;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/laufrichtung'
FSMTreppe_Y.laufrichtung = 1U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 4U;
} else if (FSMTreppe_U.sensor_oben == 1U) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_aufdimmen_runter;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/laufrichtung'
FSMTreppe_Y.laufrichtung = 0U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 1U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 7U;
} else if (FSMTreppe_U.ldr_schwelle == 0U) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_abdimmen_ldr;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 2U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
}
break;
case FSMTreppe_IN_warten_hoch:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 5U;
if ((FSMTreppe_U.sensor_oben == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_abdimmen_hoch;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 6U;
}
break;
default:
// Outport: '<Root>/status'
// case IN_warten_runter:
FSMTreppe_Y.status = 8U;
if ((FSMTreppe_U.sensor_unten == 1U) || (FSMTreppe_DW.temporalCounter_i1 >=
500U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_abdimmen_runter;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 9U;
}
break;
}
}
// End of Chart: '<Root>/FSMTreppe'
}
// Model initialize function
void FSMTreppeModelClass::initialize()
{
// (no initialization code required)
}
// Model terminate function
void FSMTreppeModelClass::terminate()
{
// (no terminate code required)
}
// Constructor
FSMTreppeModelClass::FSMTreppeModelClass() :
FSMTreppe_DW(),
FSMTreppe_U(),
FSMTreppe_Y()
{
// Currently there is no constructor body generated.
}
// Destructor
FSMTreppeModelClass::~FSMTreppeModelClass()
{
// Currently there is no destructor body generated.
}
//
// File trailer for generated code.
//
// [EOF]
//
+122
View File
@@ -0,0 +1,122 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
//
// File: FSMTreppe.h
//
// Code generated for Simulink model 'FSMTreppe'.
//
// Model version : 1.51
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Wed Jul 7 18:54:01 2021
//
// Target selection: ert.tlc
// Embedded hardware selection: ARM Compatible->ARM Cortex-M
// Code generation objectives: Unspecified
// Validation result: Not run
//
#ifndef RTW_HEADER_FSMTreppe_h_
#define RTW_HEADER_FSMTreppe_h_
#include <stdint.h>
// Class declaration for model FSMTreppe
class FSMTreppeModelClass {
// public data and function members
public:
// Block states (default storage) for system '<Root>'
struct DW_FSMTreppe_T {
uint16_t temporalCounter_i1=0; // '<Root>/FSMTreppe'
uint8_t is_active_c3_FSMTreppe=0; // '<Root>/FSMTreppe'
uint8_t is_c3_FSMTreppe=0; // '<Root>/FSMTreppe'
};
// External inputs (root inport signals with default storage)
struct ExtU_FSMTreppe_T {
uint32_t sensor_unten=0; // '<Root>/sensor_unten'
uint32_t sensor_oben=0; // '<Root>/sensor_oben'
uint32_t anim_beendet=0; // '<Root>/anim_beendet'
uint32_t ldr_schwelle=0; // '<Root>/ldr_schwelle'
};
// External outputs (root outports fed by signals with default storage)
struct ExtY_FSMTreppe_T {
uint32_t laufrichtung=0; // '<Root>/laufrichtung'
uint32_t status=0; // '<Root>/status'
uint32_t dimmrichtung=0; // '<Root>/dimmrichtung'
};
// model initialize function
void initialize();
// model step function
void step();
// model terminate function
void terminate();
// Constructor
FSMTreppeModelClass();
// Destructor
~FSMTreppeModelClass();
// Root-level structure-based inputs set method
// Root inports set method
void setExternalInputs(const ExtU_FSMTreppe_T* pExtU_FSMTreppe_T)
{
FSMTreppe_U.anim_beendet = pExtU_FSMTreppe_T->anim_beendet;
FSMTreppe_U.ldr_schwelle = pExtU_FSMTreppe_T->ldr_schwelle;
FSMTreppe_U.sensor_oben = pExtU_FSMTreppe_T->sensor_oben;
FSMTreppe_U.sensor_unten = pExtU_FSMTreppe_T->sensor_unten;
}
// Root-level structure-based outputs get method
// Root outports get method
const FSMTreppeModelClass::ExtY_FSMTreppe_T getExternalOutputs() const
{
return FSMTreppe_Y;
}
// private data and function members
private:
// Block states
DW_FSMTreppe_T FSMTreppe_DW;
// External inputs
ExtU_FSMTreppe_T FSMTreppe_U;
// External outputs
ExtY_FSMTreppe_T FSMTreppe_Y;
};
//-
// The generated code includes comments that allow you to trace directly
// back to the appropriate location in the model. The basic format
// is <system>/block_name, where system is the system number (uniquely
// assigned by Simulink) and block_name is the name of the block.
//
// Note that this particular code originates from a subsystem build,
// and has its own system numbers different from the parent model.
// Refer to the system hierarchy for this subsystem below, and use the
// MATLAB hilite_system command to trace the generated code back
// to the parent model. For example,
//
// hilite_system('FSM_Treppenlicht/FSMTreppe') - opens subsystem FSM_Treppenlicht/FSMTreppe
// hilite_system('FSM_Treppenlicht/FSMTreppe/Kp') - opens and selects block Kp
//
// Here is the system hierarchy for this model
//
// '<Root>' : 'FSM_Treppenlicht'
// '<S1>' : 'FSM_Treppenlicht/FSMTreppe'
#endif // RTW_HEADER_FSMTreppe_h_
//
// File trailer for generated code.
//
// [EOF]
//
Binary file not shown.
+401
View File
@@ -0,0 +1,401 @@
#include "treppe.h"
// #define DEBUG_TIMING
/*
- dimmer_tick: increment pwm jeden tick, bis anim beendet
- return: fsm_pend.anim_beendet
*/
bool Treppe::dimmer_tick(dimmer_t *dimmer, bool dim_type) {
dimmer->pwm += dimmer->delta_pwm;
Serial.printf("%.0f", dimmer->pwm);
if (dim_type == DIM_STUFEN) {
pwmController.setChannelPWM(dimmer->stufe,
static_cast<uint16_t>(dimmer->pwm));
} else { // DIM_LDR
pwmController.setAllChannelsPWM(static_cast<uint16_t>(dimmer->pwm));
}
dimmer->tick++;
if (dimmer->tick < dimmer->ticks) {
Serial.print("-");
return false;
}
Serial.println("");
if (dim_type == DIM_LDR) {
Serial.printf("DIM_LDR: start: %d, ziel: %d\n", dimmer->start_pwm,
dimmer->ziel_pwm);
return true;
} else { // DIM_STUFEN
Serial.printf("DIM_STUFEN: stufe: %d, start: %d, ziel: %d\n",
dimmer->stufe, dimmer->start_pwm, dimmer->ziel_pwm);
if (fsm_outputs.laufrichtung == LR_HOCH) {
if (dimmer->stufe >= stufen - 1)
return true;
dimmer->stufe++;
} else { // LR_RUNTER
if (dimmer->stufe <= 0)
return true;
dimmer->stufe--;
}
dimmer->tick = 0;
dimmer->pwm = dimmer->start_pwm;
}
return false;
}
// startbedingunen für animation
void Treppe::start_animation(dimmer_t *dimmer, bool dim_type, uint16_t on_pwm,
uint16_t off_pwm) {
fsm_pend.anim_beendet = false;
if (dim_type == DIM_STUFEN) {
if (fsm_outputs.laufrichtung == LR_HOCH)
dimmer->stufe = 0;
else
dimmer->stufe = stufen - 1;
dimmer->ticks = param.time_per_stair / INT_TIME; // [ms]
} else { // DIM_LDR
dimmer->ticks = param.time_ldr / INT_TIME; // [ms]
}
if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN) {
dimmer->start_pwm = off_pwm;
dimmer->ziel_pwm = on_pwm;
dimmer->delta_pwm = (float)(on_pwm - off_pwm) / (float)dimmer->ticks;
} else {
dimmer->start_pwm = on_pwm;
dimmer->ziel_pwm = off_pwm;
dimmer->delta_pwm = (float)(off_pwm - on_pwm) / (float)dimmer->ticks;
}
dimmer->tick = 0;
dimmer->pwm = dimmer->start_pwm;
Serial.printf("stufe %d, ticks %d, delta %f, start %d, ziel %d\n",
dimmer->stufe, dimmer->ticks, dimmer->delta_pwm,
dimmer->start_pwm, dimmer->ziel_pwm);
}
void Treppe::print_state_on_change() {
static FSMTreppeModelClass::ExtU_FSMTreppe_T last_in;
static FSMTreppeModelClass::ExtY_FSMTreppe_T last_out;
if (fsm_inputs.anim_beendet != last_in.anim_beendet ||
fsm_inputs.sensor_oben != last_in.sensor_oben ||
fsm_inputs.sensor_unten != last_in.sensor_unten ||
fsm_inputs.ldr_schwelle != last_in.ldr_schwelle ||
fsm_outputs.dimmrichtung != last_out.dimmrichtung ||
fsm_outputs.laufrichtung != last_out.laufrichtung ||
fsm_outputs.status != last_out.status) {
last_in.anim_beendet = fsm_inputs.anim_beendet;
last_in.sensor_oben = fsm_inputs.sensor_oben;
last_in.sensor_unten = fsm_inputs.sensor_unten;
last_in.ldr_schwelle = fsm_inputs.ldr_schwelle;
last_out.dimmrichtung = fsm_outputs.dimmrichtung;
last_out.laufrichtung = fsm_outputs.laufrichtung;
last_out.status = fsm_outputs.status;
Serial.printf("FSM IN: s_u: %d, s_o: %d, a_b: %d, l_s: %d => ",
fsm_inputs.sensor_oben, fsm_inputs.sensor_unten,
fsm_inputs.anim_beendet, fsm_inputs.ldr_schwelle);
Serial.printf("OUT: LR: %d DR: %d ST: %d\n", fsm_outputs.laufrichtung,
fsm_outputs.dimmrichtung, fsm_outputs.status);
}
}
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;
}
void Treppe::read_sensors() {
const bool s_oben = digitalRead(SENSOR_OBEN);
const bool s_unten = digitalRead(SENSOR_UNTEN);
fsm_pend.sensor_oben = false;
fsm_pend.sensor_unten = 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;
}
}
float Treppe::read_ldr() {
/*
Reads Illuminance in Lux
FUTURE USE : show current Illuminance on Webserver in order to calibrate
Voltage Divider 1 (R13, R14):
R13 = 220k, R14 = 82k
V(ADC) = V(in1) * R14/(R13+R14)
-> V(in1) = V(ADC) * (R13+R14)/R14
V(ADC) = analogRead(A0)/1023.00
-> V(in1) = analogRead(A0)/1023.00 * (R13+R14)/R14
= analogRead(A0) * (R13+R14)/(R14*1023.00)
= analogRead(A0) * (220k+82k)/(82k*1023.00)
= analogRead(A0) * 0.0036
Voltage Divider 2 (LDR, R1 || (R13+R14))
R1 = 47k, R13+R14 = 302k -> R1||(R13+R14) = 40,67k
Vcc/V(in1) = R(LDR) / (R1||(R13+R14))
-> R(LDR) = Vcc/V(in1) * (R1||(R13+R14))
R(LDR) = 3.3V * 40.67k / V(in1)
Join formulas:
R(LDR) = 3.3V * 40.67k / (0.0036 * analogRead(A0))
= 37280.00/analogRead(A0)
ldr_ohm = R(LDR)
E(LDR) = 6526.5 * R(LDR)^-2 (see Excel Regression)
E(LDR) = 6526.5 / (R(LDR)^2)
ldr_value = E(LDR)
*/
// float ldr_ohm = 37280.00 / analogRead(A0);
float vol_adc = analogRead(A0) * 0.0036;
if(vol_adc > 3.29)
vol_adc = 3.29;
float ldr_ohm = 40.67 * (3.3 - vol_adc) / vol_adc;
float ldr_value = 6526.6 / (ldr_ohm * ldr_ohm);
#ifdef LDRDEBUG
Serial.printf("vol_adc: %f Ohm: %f lux: %f Comp: %d\n", vol_adc, ldr_ohm, ldr_value,
param.ldr_schwelle);
#endif
return ldr_value;
}
bool Treppe::check_ldr() {
static uint8_t active = 0;
// follow up: averaging over many samples?
float ldr = read_ldr();
if (ldr < param.ldr_schwelle) {
active = 1;
}
if (ldr > param.ldr_schwelle + LDR_HYS) {
active = 0;
}
return active;
}
void Treppe::task() {
#ifdef DEBUG_TIMING
uint32_t m = micros();
#endif
// TODO wenn LDR geändert => idle_pwm_soll anpassen
// fsm_pend.ldr_changed = true;
fsm_inputs.ldr_schwelle = check_ldr();
#ifdef DEBUG_TIMING
Serial.print("1:");
Serial.println(micros() - m);
m = micros();
#endif
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
Serial.print("2:");
Serial.println(micros() - m);
m = micros();
#endif
FSMTreppe_Obj.setExternalInputs(&fsm_inputs);
FSMTreppe_Obj.step();
fsm_outputs = FSMTreppe_Obj.getExternalOutputs();
#ifdef DEBUG_TIMING
Serial.print("3:");
Serial.println(micros() - m);
m = micros();
#endif
print_state_on_change();
#ifdef DEBUG_TIMING
Serial.print("4:");
Serial.println(micros() - m);
m = micros();
#endif
if (fsm_outputs.status == ST_AUFDIMMEN_HOCH ||
fsm_outputs.status == ST_ABDIMMEN_HOCH ||
fsm_outputs.status == ST_AUFDIMMEN_RUNTER ||
fsm_outputs.status == ST_ABDIMMEN_RUNTER) {
if (fsm_pend.anim_beendet)
start_animation(&dimmer_stufen, DIM_STUFEN, param.active_pwm,
idle_pwm_ist);
else
fsm_pend.anim_beendet = dimmer_tick(&dimmer_stufen, DIM_STUFEN);
} else if (fsm_outputs.status == ST_AUFDIMMEN_LDR ||
fsm_outputs.status == ST_ABDIMMEN_LDR) {
if (fsm_pend.anim_beendet)
start_animation(&dimmer_ldr, DIM_LDR, idle_pwm_ist, 0);
else
fsm_pend.anim_beendet = dimmer_tick(&dimmer_ldr, DIM_LDR);
} else if (fsm_outputs.status == ST_RUHEZUSTAND) {
if (fsm_pend.ldr_changed) {
fsm_pend.ldr_changed = false;
fsm_outputs.dimmrichtung = DR_AUFDIMMEN;
start_animation(&dimmer_ldr, DIM_LDR, idle_pwm_soll, idle_pwm_ist);
idle_pwm_ist = idle_pwm_soll;
}
if (!fsm_pend.anim_beendet) {
fsm_pend.anim_beendet = dimmer_tick(&dimmer_ldr, DIM_LDR);
}
}
if (fsm_outputs.status == ST_RUHEZUSTAND ||
fsm_outputs.status == ST_INAKTIV_LDR) {
if (param_changed) {
param_changed = false;
param = param_pend;
save_param_to_eeprom();
Serial.printf("Parameter Change applied!\n");
}
}
#ifdef DEBUG_TIMING
Serial.print("5:");
Serial.println(micros() - m);
#endif
}
void Treppe::setup() {
pwmController.resetDevices();
// Deactive PCA9685 Phase Balancer due to LED Flickering
// https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15
// see also lib/PCA9685-Arduin/PCA9685.h:204
pwmController.init(PCA9685_PhaseBalancer_None);
// pwmController.init(PCA9685_PhaseBalancer_Linear);
pwmController.setPWMFrequency(100);
// pwmController.setAllChannelsPWM(idle_pwm);
// WARNING: before getting Parameters of Flash, make sure plausible parameters
// are written in flash!
EEPROM.get(EEP_START_ADDR, param); // get Parameters of flash
pinMode(13, OUTPUT);
pinMode(0, OUTPUT);
digitalWrite(13, HIGH);
digitalWrite(0, HIGH);
pinMode(A0, INPUT);
pinMode(SENSOR_OBEN, INPUT);
pinMode(SENSOR_UNTEN, INPUT);
pinMode(OE, OUTPUT);
digitalWrite(OE, 0);
Serial.printf("Treppe: stufen=%d\n", stufen);
}
void Treppe::save_param_to_eeprom() {
EEPROM.put(EEP_START_ADDR,
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) {
param_pend.idle_pwm_max = param_pend.active_pwm * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
param_pend.idle_pwm_max = value;
}
if (param_pend.idle_pwm_max > param_pend.active_pwm) {
param_pend.idle_pwm_max = param_pend.active_pwm;
}
param_changed = true;
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) {
param_pend.active_pwm = 4095 * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
param_pend.active_pwm = value;
}
if (param_pend.active_pwm > 4095) {
param_pend.idle_pwm_max = 4095;
}
param_changed = true;
Serial.printf("Treppe: param_pend.active_pwm=%d\n", param_pend.active_pwm);
}
void Treppe::set_time_ldr(const uint16_t value) {
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", param_pend.time_ldr);
}
void Treppe::set_time_per_stair(const uint16_t value) {
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", 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) {
// ?!
param_pend.ldr_schwelle = 10 * value / 100;
} else if (vorgabe_typ == VORGABE_12BIT) {
param_pend.ldr_schwelle = value;
}
param_changed = true;
Serial.printf("Treppe: ldr_schwelle=%d\n", param_pend.ldr_schwelle);
}
void Treppe::param_to_json(char *json_str, size_t sz) {
snprintf(json_str, sz, "{\n\
\"time_ldr\": %d,\n\
\"time_per_stair\": %d,\n\
\"idle_pwm_max\": %d,\n\
\"active_pwm\": %d,\n\
\"ldr_schwelle\": %d\n}\n",
param.time_ldr, param.time_per_stair, param.idle_pwm_max,
param.active_pwm, param.ldr_schwelle);
}
+120
View File
@@ -0,0 +1,120 @@
#ifndef __TREPPE_H
#define __TREPPE_H
#include "FSMTreppe3/FSMTreppe3.h"
#include "PCA9685.h"
#include <EEPROM.h>
#define LDRDEBUG // comment in to override LDR measurement
#define LDR_HYS 100 // Hysteresis for switching off FSM [lux]
#define SENSOR_OBEN 16
#define SENSOR_UNTEN 12
#define OE 14
#define INT_TIME 20 // interrupt intervall [ms]
#define TIME_MS_MAX 5000 // maximum time for animation [ms]
enum vorgabe_typ_t { VORGABE_PROZENT = 0, VORGABE_12BIT = 1 };
#define EEP_START_ADDR 100 // define Start Address for "EEPROM" storage -> depends on size of "wifi_data"!
class Treppe {
private:
const uint8_t stufen;
struct stairway_param_t {
uint16_t time_ldr = 500;
uint16_t time_per_stair = 300; // dimmtime per stair [ms]
uint16_t idle_pwm_max = 100;
uint16_t active_pwm = 2000;
uint16_t ldr_schwelle = 30; // activation value for FSM [lx]
};
stairway_param_t param;
stairway_param_t param_pend; // zwischenspeicher änderungen
bool param_changed = false;
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;
struct dimmer_t {
uint8_t stufe = 0;
uint16_t ticks = 0;
uint16_t tick = 0;
float delta_pwm = 0.0;
float pwm = 0.0;
uint16_t start_pwm = 0;
uint16_t ziel_pwm = 0;
};
enum dimmer_type_t { DIM_STUFEN = 0, DIM_LDR = 1 };
dimmer_t dimmer_stufen;
dimmer_t dimmer_ldr;
// initialize with i2c-Address 0, use Wire Library
PCA9685 pwmController;
FSMTreppeModelClass FSMTreppe_Obj;
FSMTreppeModelClass::ExtU_FSMTreppe_T fsm_inputs;
FSMTreppeModelClass::ExtY_FSMTreppe_T fsm_outputs;
enum fsm_status_t {
ST_INAKTIV_LDR = 0,
ST_AUFDIMMEN_LDR = 1,
ST_ABDIMMEN_LDR = 2,
ST_RUHEZUSTAND = 3,
ST_AUFDIMMEN_HOCH = 4,
ST_WARTEN_HOCH = 5,
ST_ABDIMMEN_HOCH = 6,
ST_AUFDIMMEN_RUNTER = 7,
ST_WARTEN_RUNTER = 8,
ST_ABDIMMEN_RUNTER = 9
};
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_tick(dimmer_t *dimmer, bool dim_type);
void start_animation(dimmer_t *dimmer, bool dim_type, uint16_t on_pwm,
uint16_t off_pwm);
/* LDR */
bool read_sensor(int sensor);
float read_ldr();
bool check_ldr();
public:
Treppe(uint8_t _stufen) : stufen(_stufen) { FSMTreppe_Obj.initialize(); }
~Treppe() { FSMTreppe_Obj.terminate(); }
void setup();
void task(); // call periodically
// Parameter section
void save_param_to_eeprom();
void param_to_json(char* json_str, size_t sz);
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
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
set remote hardware-breakpoint-limit 1
set remote hardware-watchpoint-limit 1
set remote interrupt-on-connect on
set remote kill-packet off
set remote symbol-lookup-packet off
set remote verbose-resume-packet off
mem 0x20000000 0x3fefffff ro cache
mem 0x3ff00000 0x3fffffff rw
mem 0x40000000 0x400fffff ro cache
mem 0x40100000 0x4013ffff rw cache
mem 0x40140000 0x5fffffff ro cache
mem 0x60000000 0x60001fff rw
set serial baud 460800
file .pio/build/debug/firmware.elf
target remote \\.\COM23
thb loop
-17
View File
@@ -1,17 +0,0 @@
#include "httpserver.h"
bool HTTPServer::addRootFileHandler() {
// //experimental, see doku.md
// server.serveStatic("/compressed", LittleFS, "/compressed.html.gzip");
this->serveStatic("", LittleFS, "/index.html");
this->serveStatic("/", LittleFS, "/index.html");
this->serveStatic("/#", LittleFS, "/index.html");
this->serveStatic("/style.css", LittleFS, "/style.css");
this->serveStatic("/input.js", LittleFS, "/input.js");
this->serveStatic("/favicon.png", LittleFS, "/favicon.png");
return true;
}
+56 -58
View File
@@ -9,80 +9,81 @@ extern "C" {
#include "user_interface.h" #include "user_interface.h"
} }
// OTA & WEB // OTA & WEB
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include "ota.h"
#include "wifi_credentials.h"
#include "httpserver.h" #include "httpserver.h"
#include "ota.h"
#include "wifi_credentials.h"
#include <EEPROM.h>
// BOARD // BOARD
#define ESP12_LED 2 #define ESP12_LED 2
#define NODEMCU_LED 16 // #define NODEMCU_LED 16
// PWM // PWM
#include "treppe.h"
#include "pwm.h"
os_timer_t timer1; os_timer_t timer1;
uint8_t timer_flag = 0; uint8_t timer_flag = 0;
Treppe stairs(16);
Treppe stairs(13);
// WIFI // WIFI
const char *ssid = STASSID; const char *ssid = STASSID;
const char *password = STAPSK; const char *password = STAPSK;
// port 80, root directory of server '/'
HTTPServer httpServer(80, "/", &stairs);
void timerCallback(void *pArg) uint32_t _t = 0;
{ #define SP_US(_str, _a) \
*((int *) pArg) += 1; Serial.print(_str); \
Serial.print(" took: "); \
Serial.print(_a); \
Serial.println("us")
#define TIMEIF_US(_f, _l, _str) \
_t = micros(); \
_f; \
_t = micros() - _t; \
if (_t > (_l)) { \
SP_US(_str, _t); \
}
struct { // Struct for wifi-data, 40 Bytes each SSID and PW
char SSID[40] = "";
char PW[40] = "";
} wifi_data;
void timerCallback(void *pArg) {
*(static_cast<int *>(pArg)) += 1;
stairs.task(); stairs.task();
} }
// HTTP
void handleNotFound();
HTTPServer httpServer(80, "/");
uint32_t _t=0;
#define SP_US(_str,_a) Serial.print(_str); Serial.print(" took: "); Serial.print(_a); Serial.println("us")
#define TIMEIF_US(_f, _l, _str) _t=micros(); _f; _t=micros()-_t; if(_t > _l) { SP_US(_str, _t); }
// =============================================== // ===============================================
uint8_t inter = 0;
ICACHE_RAM_ATTR void int_test() { inter = 1; }
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += httpServer.uri();
message += "\nMethod: ";
message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += httpServer.args();
message += "\n";
for (uint8_t i = 0; i < httpServer.args(); i++) {
message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
}
httpServer.send(404, "text/plain", message);
}
void setup() { void setup() {
#ifdef WITH_DEBUGGING_ON #ifdef WITH_DEBUGGING_ON
Serial.begin(460800); Serial.begin(460800);
gdbstub_init(); gdbstub_init();
#else #else
Serial.begin(115200); Serial.begin(76800);
#endif #endif
Serial.println("Booting ....");
Serial.println(F("Booting ...."));
pinMode(NODEMCU_LED, OUTPUT);
pinMode(ESP12_LED, OUTPUT); pinMode(ESP12_LED, OUTPUT);
EEPROM.begin(512); // init virtual "EEPROM" with size 512 Bytes
// strncpy(wifi_data.SSID, "donotconnect", 40);
// strncpy(wifi_data.PW, "unsafe lol", 40);
EEPROM.get(0, wifi_data);
// EEPROM.commit();
Wire.begin(); // Wire must be started first Wire.begin(); // Wire must be started first
Wire.setClock(1000000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz Wire.setClock(
1000000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz
stairs.setup();
Serial.println("PCA9685 connected !");
// attachInterrupt(digitalPinToInterrupt(2), int_test, RISING);
// attachInterrupt(digitalPinToInterrupt(12), int_test, RISING);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
@@ -102,25 +103,22 @@ void setup() {
ota_setup(); ota_setup();
httpServer.start(); httpServer.start();
httpServer.onNotFound(handleNotFound); httpServer.start_apps();
Serial.println("HTTP server started !"); Serial.println("HTTP server started !");
stairs.setup();
Serial.println("PCA9685 connected !");
os_timer_setfn(&timer1, timerCallback, &timer_flag); os_timer_setfn(&timer1, timerCallback, &timer_flag);
os_timer_arm(&timer1, 20, true); os_timer_arm(&timer1, 20, true);
stairs.setState(1); Serial.println("SSID: " + String(wifi_data.SSID) +
stairs.setDirection(1); " PW: " + String(wifi_data.PW));
} }
void loop() { void loop() {
if(millis() > 25000 && stairs.getState() == 1 && stairs.getDirection() == 1) stairs.setState(0); if (inter != 0u) {
if(millis() > 45000 && stairs.getDirection() == 1){ Serial.printf("interrupt\n");
stairs.setState(1); inter = 0;
stairs.setDirection(0);
} }
TIMEIF_US(ArduinoOTA.handle(), 1000, "OTA");
TIMEIF_US(httpServer.handleClient(), 1000, "HTTP"); TIMEIF_US(ArduinoOTA.handle(), 10000, "OTA");
TIMEIF_US(httpServer.handleClient(), 10000, "HTTP");
} }
-136
View File
@@ -1,136 +0,0 @@
#include "pwm.h"
uint8_t Treppe::softstart_led(uint8_t led, uint16_t startval, uint16_t stopval){
/*
softstart task
- get's called at regular intervals (1ms at the moment)
- dimms single led (0 - 15, PCA9685 outputs) with linear intervals vom startval to stopval
- calculates pwm steps depending on startval, stopval and timeinterval
- -> results in constanst speed
- returns 1 if led dimming is running
- returns 0 if led dimming is finished
*/
static uint8_t lastled = 255;
static float current_pwm = 0;
static float stepsize = 1.0;
if(led != lastled){
pwmController.setChannelPWM(led, (uint16_t)startval);
lastled = led;
current_pwm = startval;
stepsize = 20*abs(stopval - startval)/(float)time_per_stair; // only valid at 1ms function call interval
return 1;
}
if(current_pwm > stopval - stepsize && current_pwm < stopval + stepsize) return 0;
// todo: duty cycle zero!
if(startval > stopval){
current_pwm -= stepsize;
}
else {
current_pwm += stepsize;
}
Serial.println((uint16_t)current_pwm);
pwmController.setChannelPWM(led, (uint16_t)current_pwm);
return 1;
}
void Treppe::ledsequence(){
static int8_t led = 0;
static uint16_t brightness = 0;
static uint16_t lastbrightness = 0;
static uint8_t finish = 1;
static uint16_t status = 0;
uint16_t status_build = 0;
status_build |= direction << 8;
status_build |= state;
if(status_build != status){ // check if any parameter changed
finish = 0; // set state unfinished -> start action
if(direction) led = 0; // reset led counter depending of direction
else led = stairs-1;
if(state){
brightness = active_brightness; // set brightness value depending of on/off
lastbrightness = idle_brightness;
}
else{
brightness = idle_brightness;
lastbrightness = active_brightness;
}
status = status_build; // set parameter memory
Serial.print("----Status Changed! onoff: ");
Serial.print(state);
Serial.print(" dir: ");
Serial.println(direction);
}
if(!finish){ // finish == 0 -> action pending
if(!softstart_led(led,lastbrightness, brightness)){
Serial.print("one LED finished: ");
Serial.print(led);
Serial.print(" last: ");
Serial.print(lastbrightness);
Serial.print(" curr: ");
Serial.println(brightness);
if(direction){
led++;
if(led >= stairs) {
finish = 1;
//lastbrightness = brightness;
}
}
else{
led--;
if(led < 0){
//lastbrightness = brightness;
finish = 1;
}
}
}
}
}
void Treppe::setup(){
pwmController.resetDevices();
pwmController.init();
pwmController.setPWMFrequency(200);
Serial.println("Hello from Treppe");
Serial.print("Treppe: initial parameters: stairs=");
Serial.println(stairs);
}
void Treppe::task(){
ledsequence();
}
uint16_t Treppe::setIdle(uint16_t _idle_brightness){
idle_brightness = _idle_brightness;
Serial.println("Treppe: idle brightness changed!");
return idle_brightness;
}
uint16_t Treppe::setActive(uint16_t _active_brightness){
active_brightness = _active_brightness;
Serial.println("Treppe: active brightness changed!");
return active_brightness;
}
uint16_t Treppe::setTime(uint16_t _time_per_stair){
time_per_stair = _time_per_stair;
Serial.println("Treppe: time changed!");
return time_per_stair;
}
uint8_t Treppe::setDirection(uint8_t _direction){
direction = _direction;
Serial.println("Treppe: Direction changed!");
// to do: implement state command variable to determine dimm-state
return direction;
}
uint8_t Treppe::setState(uint8_t _state){
if(state == _state) return 1;
else{
state = _state;
Serial.println("Treppe: State changed!");
}
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
SET GDB_PATH=C:\Users\simon\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.0-newlib4.0.0-gnu23-48f7b08\bin\xtensa-lx106-elf-gdb.exe
echo "Starting gdb"
echo %GDB_PATH%
%GDB_PATH% -x ".\scripts\gdboptions_win"
-1
View File
@@ -1,6 +1,5 @@
#!/bin/bash #!/bin/bash
GDB_PATH=~/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/bin/xtensa-lx106-elf-gdb GDB_PATH=~/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.0-newlib4.0.0-gnu23-48f7b08/bin/xtensa-lx106-elf-gdb
cd ..
echo "Starting gdb" echo "Starting gdb"
$GDB_PATH -x scripts/gdboptions $GDB_PATH -x scripts/gdboptions
+57 -5
View File
@@ -8,23 +8,34 @@
; Please visit documentation for the other options and examples ; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[env] [platformio]
description = ESP8266 Treppenlicht Steuerung
default_envs = ota
; test_dir = test
data_dir = data_gz
[env:hardware]
platform = espressif8266 platform = espressif8266
board = nodemcuv2 ; board = nodemcuv2
board = huzzah
framework = arduino framework = arduino
; build_unflags = -Os
; build_flags = -O2
; for http files
board_build.filesystem = littlefs board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m1m.ld board_build.ldscript = eagle.flash.4m1m.ld
extra_scripts = pre:create_gz_files.py extra_scripts = pre:create_gz_files.py
monitor_speed = 115200
[env:serial] [env:serial]
extends = env:hardware
upload_protocol = esptool upload_protocol = esptool
upload_speed = 921600 upload_speed = 921600
upload_port = COM23
monitor_port = COM23
monitor_speed = 76800
[env:ota] [env:ota]
extends = env:hardware
; OTA => https://docs.platformio.org/en/latest/platforms/espressif8266.html#over-the-air-ota-update ; OTA => https://docs.platformio.org/en/latest/platforms/espressif8266.html#over-the-air-ota-update
upload_protocol = espota upload_protocol = espota
upload_port = <!! IP ADDRESS !!> upload_port = <!! IP ADDRESS !!>
@@ -33,13 +44,54 @@ upload_flags =
--host_port=<!! PORT !!> --host_port=<!! PORT !!>
--auth=admin --auth=admin
[env:debug] [env:debug]
extends = env:hardware
; look at doku.md ; look at doku.md
build_flags = -DWITH_DEBUGGING_ON -Os -g3 -ggdb3 build_flags = -DWITH_DEBUGGING_ON -Os -g3 -ggdb3
upload_protocol = esptool upload_protocol = esptool
upload_speed = 921600 upload_speed = 921600
upload_port = COM23
; for pio check
; check_tool = cppcheck
check_tool = clangtidy
check_flags =
clangtidy: --fix-errors lib/httpserver/*
; clangtidy: lib/httpserver/* lib/treppe/* lib/treppe/FSMTreppe3/* lib/PCA9685-Arduino/*
check_skip_packages = yes
# This file is used compile and run tests located in the `unit` directory.
# For more info, see:
# https://docs.platformio.org/en/latest/plus/unit-testing.html
# https://github.com/ThrowTheSwitch/Unity
# https://github.com/ThrowTheSwitch/Unity/blob/master/docs/UnityAssertionsReference.md
# To prepare coverage data for lcov, add ${coverage.build_flags} to env:test build flags
# To actually generate coverage report:
# $ `pio test` / run the test `program` manually
# $ lcov --include (readlink -f ../espurna)'/*' --capture --directory .pio/build/test/ --output-file test.info
# $ genhtml --ignore-errors source test.info --output-directory out
[coverage]
build_flags = -lgcov -fprofile-arcs -ftest-coverage
[env:test]
extends = env:hardware
[env:native]
platform = native
test_build_project_src = true
build_flags =
-DMANUFACTURER="PLATFORMIO"
-DDEVICE="TEST"
-std=gnu++11
-g
-Os
-I lib/treppe
-I lib/PCA9685-Arduino
+30 -30
View File
@@ -1,40 +1,40 @@
#include <Arduino.h> // #include <Arduino.h>
#include <unity.h> // #include <unity.h>
String STR_TO_TEST; // String STR_TO_TEST;
void setUp(void) { // // void setUp(void) {
// set stuff up here // // // set stuff up here
STR_TO_TEST = "Hello, world!"; // // STR_TO_TEST = "Hello, world!";
} // // }
void tearDown(void) { // // void tearDown(void) {
// clean stuff up here // // // clean stuff up here
STR_TO_TEST = ""; // // STR_TO_TEST = "";
} // // }
void test_led_builtin_pin_number(void) { // void test_led_builtin_pin_number(void) {
TEST_ASSERT_EQUAL(2, LED_BUILTIN); // TEST_ASSERT_EQUAL(2, LED_BUILTIN);
} // }
void test_string_concat(void) { // void test_string_concat(void) {
String hello = "Hello, "; // String hello = "Hello, ";
String world = "world!"; // String world = "world!";
TEST_ASSERT_EQUAL_STRING(STR_TO_TEST.c_str(), (hello + world).c_str()); // TEST_ASSERT_EQUAL_STRING(STR_TO_TEST.c_str(), (hello + world).c_str());
} // }
void setup() // void setup()
{ // {
delay(2000); // service delay // delay(2000); // service delay
UNITY_BEGIN(); // UNITY_BEGIN();
RUN_TEST(test_led_builtin_pin_number); // RUN_TEST(test_led_builtin_pin_number);
RUN_TEST(test_string_concat); // RUN_TEST(test_string_concat);
UNITY_END(); // stop unit testing // UNITY_END(); // stop unit testing
} // }
void loop() // void loop()
{ // {
} // }
+47
View File
@@ -0,0 +1,47 @@
// #include <Arduino.h>
#include "treppe.h"
#include <unity.h>
Treppe stairs(10);
void setUp(void) {
// run before each test
// set stuff up here
stairs.setup();
Serial.println("Treppe initialized !");
Serial.println("PCA9685 connected !");
}
void tearDown(void) {
// clean stuff up here
}
void test_set_state(void) {
stairs.setState(1);
TEST_ASSERT_EQUAL(1, stairs.getState());
stairs.setState(0);
TEST_ASSERT_EQUAL(0, stairs.getState());
}
void test_set_direction(void) {
stairs.setDirection(1);
TEST_ASSERT_EQUAL(1, stairs.getDirection());
stairs.setDirection(0);
TEST_ASSERT_EQUAL(0, stairs.getDirection());
}
void setup()
{
delay(2000); // service delay
UNITY_BEGIN();
RUN_TEST(test_set_state);
RUN_TEST(test_set_direction);
UNITY_END(); // stop unit testing
}
void loop()
{
}