93 Commits
Author SHA1 Message Date
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
schmidtsi76327 1b34714d27 Fehler in PCA Library mit LED flicker 2021-06-24 16:40:19 +02:00
Pupsmuckel 90a9213a3c HTML Änderung 2021-06-24 13:51:12 +02:00
Pupsmuckel 7976f5258f html Änderung 2021-06-24 13:41:20 +02:00
Pupsmuckel bb3a735d37 Html Änderung 2021-06-24 13:08:28 +02:00
Pupsmuckel 3c186771fe Html Änderung 2021-06-24 11:42:12 +02:00
Pupsmuckel c40e7f80e5 Html Änderung 2021-06-24 11:34:05 +02:00
bartschdo76253 9d1105cb80 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 21:25:24 +02:00
bartschdo76253 4130b64370 object oriented stairlight control 2021-06-23 21:23:31 +02:00
schmidtsi76327 bff8cdbeb7 compress errors :) 2021-06-23 17:30:15 +02:00
schmidtsi76327 d8343ea91f Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 17:26:28 +02:00
schmidtsi76327 78f09b3a3b compress 2021-06-23 17:26:22 +02:00
schmidtsi76327 bd0e364d22 delete compress files 2021-06-23 17:24:54 +02:00
bartschdo76253 32266b5f37 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 17:20:22 +02:00
schmidtsi76327 b62f4f9f95 changed gitignore 2021-06-23 17:16:16 +02:00
bartschdo76253 a8af7543ba deleted headers 2021-06-23 17:15:22 +02:00
schmidtsi76327 85f8da3476 reorganize 2021-06-23 17:12:44 +02:00
schmidtsi76327 f323bd4cf9 reorganize 2021-06-23 17:12:40 +02:00
Pupsmuckel 708bb2cda4 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 17:01:53 +02:00
Pupsmuckel a4196bb579 Änderung 2021-06-23 17:01:47 +02:00
schmidtsi76327 908c4298be Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 17:01:34 +02:00
schmidtsi76327 6e885673b8 e 2021-06-23 17:01:08 +02:00
bartschdo76253 93cc958800 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 16:57:11 +02:00
bartschdo76253 9d30423ca3 variable PWM step calculation 2021-06-23 16:51:15 +02:00
schmidtsi76327 b3b11d0818 reorder main, add ota.h 2021-06-23 16:49:53 +02:00
schmidtsi76327 51bdd6210e changed from include/http to data/ because of littlefs 2021-06-23 16:30:27 +02:00
Pupsmuckel d51bb4c95c Änderung html 2021-06-23 16:29:30 +02:00
schmidtsi76327 2659e366ec Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 16:20:45 +02:00
schmidtsi76327 4951ca46c1 delete unnecessary files 2021-06-23 16:19:31 +02:00
schmidtsi76327 97a6076864 delete unnecessary files 2021-06-23 16:18:54 +02:00
schmidtsi76327 ff6b82867c added httpserver with inheritance 2021-06-23 16:12:19 +02:00
Pupsmuckel a3dc7a5fba Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 16:09:58 +02:00
Pupsmuckel c13b0adc82 2te Änderung 2021-06-23 16:07:19 +02:00
schmidtsi76327 da20f74db8 „include/http/index.html“ ändern 2021-06-23 14:06:55 +00:00
Pupsmuckel d5b9827543 wichtige Änderung 2021-06-23 16:03:49 +02:00
Pupsmuckel 3c6889854e Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht 2021-06-23 15:58:48 +02:00
Pupsmuckel 8d8ffe4173 änderung an der website 2021-06-23 15:56:27 +02:00
schmidtsi76327 006404fccf ugly hack 2021-06-23 15:22:38 +02:00
schmidtsi76327 d17091651f Merge branch 'littlefs' of https://git.efi.th-nuernberg.de/gitea/schmidtsi76327/ESP8266_Treppenlicht into littlefs 2021-06-23 13:37:59 +02:00
schmidtsi76327 4b608c42ca tryin on win 2021-06-23 13:37:13 +02:00
Simon Schmidt 278f746b33 templ ini 2021-06-23 13:34:54 +02:00
Simon Schmidt 642ee7d0a6 gzip works from FS 2021-06-23 02:13:48 +02:00
Simon Schmidt 6596346d3d ls -l implement and ota fw fix 2021-06-23 01:30:28 +02:00
Simon Schmidt b696703d45 littefs working 2021-06-22 23:38:39 +02:00
Simon Schmidt baecaf02da cleanup 2021-06-22 20:36:53 +02:00
Simon Schmidt 1d7f2f368b debugging support :) over gdbstub 2021-06-22 20:25:27 +02:00
Simon Schmidt c8938f4b36 added webtest.sh for linux 2021-06-22 17:26:58 +02:00
Simon Schmidt cd80b9b7ba add lib PCA9685 locally, because of warnings 2021-06-22 17:22:00 +02:00
Simon Schmidt 657f77e73d test example 2021-06-22 16:12:04 +02:00
37 changed files with 1515 additions and 532 deletions
+4
View File
@@ -1,5 +1,9 @@
.pio .pio
.vscode .vscode
.vscode/*
.vscode/**
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"
]
}
-15
View File
@@ -1,15 +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"
}
}
-3
View File
@@ -35,8 +35,5 @@ upload_port = <IPADRESS>
upload_flags = upload_flags =
--port=8266 --port=8266
--auth=admin --auth=admin
lib_deps =
ottowinter/PCA9685 16-Channel PWM Driver Module Library @ 1.2.9
``` ```
+6 -2
View File
@@ -1,3 +1,4 @@
#!/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://www.mischianti.org/2020/10/26/web-server-with-esp8266-and-esp32-byte-array-gzipped-pages-and-spiffs-2/
@@ -27,8 +28,11 @@ def convert_to_gzip(src, out, f):
f_out.write(top.encode(encoding='utf-8')) f_out.write(top.encode(encoding='utf-8'))
src='include/http/' src='data/'
out='include/' out='compress/'
if not 'compress' in os.listdir():
os.mkdir('compress')
for f in os.listdir(src): for f in os.listdir(src):
convert_to_gzip(src, out, f) convert_to_gzip(src, out, f)
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/python3
import os, gzip
# https://stackoverflow.com/questions/8156707/gzip-a-file-in-python
src_dir='data'
out_dir='data_gz'
if not 'data_gz' in os.listdir():
os.mkdir('data_gz')
for f in os.listdir(src_dir):
with open(f'{src_dir}/{f}', 'rb') as f_in:
with gzip.open(f'{out_dir}/{f}.gz', 'wb') as f_out:
f_out.writelines(f_in)
Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 531 B

+74
View File
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP8266 Treppenlicht</title>
<!-- main style sheet -->
<link href="/favicon.png" rel="icon" type="image/png" sizes="10x10">
<link href="/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="kopfzeile" style="text-align: center;">
<b>Treppenlicht</b>
</div>
<div class="ueberschrift">
Helligkeit
<!--<label id="label_pwm">
</label>-->
<div class="slider">
<input type="range" class="regler" id="helligkeit" name="rangeInput" 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 class="ueberschrift">
Laufgeschwindigkeit
<!--<label id="label_geschwindigkeit">
</label>-->
<div class="slider">
<input type="range" class="regler" id="geschwindigkeit" name="rangeInput" min="0" max="100" value="50"
oninput="amount3.value=geschwindigkeit.value">
<br>
<output name="amount3" id="amount3" for="geschwindigkeit">50</output>
</div>
</div>
<div class="ueberschrift">
Licht-An-Zeit
<!-- <label id="label_time">
</label>-->
<div class="slider">
<input type="range" class="regler" id="time" name="rangeInput" min="0" max="100" value="50"
oninput="amount4.value=time.value">
<br>
<output name="amount4" id="amount4" for="time">50</output>
</div>
</div>
<div class="terminal">
<input type="button" id="clear_term" value="clear" onclick="clearTerminal();">
<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>
<script src="/input.js"></script>
</html>
+40
View File
@@ -0,0 +1,40 @@
// var slider = document.getElementById("helligkeit");
// var output = document.getElementById("l_pwm");
// output.innerHTML = slider.value; // Display the default slider value
// // Update the current slider value (each time you drag the slider handle)
// slider.oninput = function() {
// output.innerHTML = this.value;
// }
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4) {
if (xhr.status == 200){
console.log(xhr.responseText);
terminal = document.getElementById("term");
autoscroll = document.getElementById("scroll");
terminal.innerHTML += xhr.responseText;
if(autoscroll.checked)
terminal.scrollTop = terminal.scrollHeight;
}
else {
console.log("status:", xhr.status);
}
}
}
function reloadTerminal() {
xhr.open("POST", "/app=terminal", true);
xhr.send();
setTimeout(reloadTerminal, 1000);
};
reloadTerminal();
function clearTerminal() {
document.getElementById("term").innerHTML = '';
}
+122
View File
@@ -0,0 +1,122 @@
html {
font-size: 16px;
font-family: sans-serif, Arial, Helvetica;
background-color: #d4d4d4;
height: 100%;
/* background-image: url('Background.png'); */
background-repeat: repeat;
background-size: 150% 150%;
}
body {
height: 100%;
margin: 0 auto;
border: none;
border-radius: 3;
}
.topbar {
padding: 1em;
background-color: #1f1f1f;
color: white;
font-size: x-large;
text-align: center;
}
.ueberschrift{
color: #ffffff;
font-size: 50px;
width: 100%;
text-align: center;
}
.regler{
-webkit-appearance: none;
height: 30px;
width: 100%;
border-radius: 20px;
outline: black;
background-color: rgb(176, 188, 228);
}
.regler::-webkit-slider-thumb{
-webkit-appearance: none;
appearance: none;
width: 5%;
height: 20px;
border-radius: 10px;
background-color: rgb(107, 122, 192);
cursor:pointer;
}
input[type=range]::-webkit-slider-thumb{
-webkit-appearance: none;
border:none;
height: 30px;
width: 4%;
border-radius: 30px;
}
.slider {
width: 100%;
}
.kopfzeile{
color: #1f1f1f;
font-size: 50px;
width: 100%;
background-color: #8d8a8a;
}
/*-------------------------------------------------------*/
/*Switch:
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
Hide default HTML checkbox
.switch input {
opacity: 0;
width: 0;
height: 0;
}
*/
/* The slider */
/*input:checked + .slider {
background-color: #04AA6D;
}
input:focus + .slider {
box-shadow: 0 0 1px #04AA6D;
}*/
/*
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-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;
}
+86
View File
@@ -0,0 +1,86 @@
Hardware Timer didnt work https://github.com/khoih-prog/ESP8266TimerInterrupt#why-using-isr-based-hardware-timer-interrupt-is-better
=> Software Timer https://ullisroboterseite.de/esp8266-timing.html#timer
### __Zum aktivieren von GDBStub:__
```c
#include <GDBStub.h>
...
void setup() {
Serial.begin(460800);
gdbstub_init();
```
### __Achtung !__
GDB muss dafür compiled werden
GDB-Version aus Arduino Toolchain hat Support
```sh
$ ./start_xtensa_gdb_stub.sh
```
### __Achtung !__
Don`t forget __\r__
ESP-OTA wird von ufw oder Defender geblockt.
- Windows -> Python needs to be granted with rights
- Linux -> open udp port in ufw ->
```sh
platform.ini
upload_flags =
--host-port <PORT>
...
$ sudo ufw allow tcp/<PORT>
```
```c++
server.streamFile(f, mime::getContentType(SRH::_path), requestMethod);
=====>
const String& p = SRH::_path;
if(p.endsWith(".gzip")) {
server.sendHeader("Content-Encoding", "gzip");
server.streamFile(f, mime::getContentType(p.substring(0, p.length()-5)), requestMethod);
}
else
server.streamFile(f, mime::getContentType(SRH::_path), requestMethod);
```
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:
- check dir for files automatic
- move handleNotFound to httpserver.h
- maybe compress files ?
### LED Flickering issue
https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15
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 !__
-3
View File
@@ -1,3 +0,0 @@
Hardware Timer didnt work https://github.com/khoih-prog/ESP8266TimerInterrupt#why-using-isr-based-hardware-timer-interrupt-is-better
=> Software Timer https://ullisroboterseite.de/esp8266-timing.html#timer
Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

-40
View File
@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>ESP8266 Treppenlicht</title>
<!-- main style sheet -->
<link href="/favicon.png" rel="icon" type="image/png" sizes="16x16">
<link href="/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="topbar">
ESP8266 Treppenlicht Controller
</div>
<div class="control">
<div class="brightness">
</div>
<div class="onoff">
toggle all
<label id="l_onoff"></label>
<label class="switch">
<input type="checkbox">
<span class="slider round"></span>
</label>
</div>
<div class="pwm">
<label id="label_pwm"></label>
<input type="range" min="1" max="100" value="50" class="rangeslider" id="range1">
</div>
<div class="timer">
<label id="label_timer"></label>
<input type="range" min="1" max="100" value="50" class="rangeslider" id="timer_range">
</div>
</div>
</body>
<script src="/input.js"></script>
</html>
-8
View File
@@ -1,8 +0,0 @@
var slider = document.getElementById("range1");
var output = document.getElementById("l_pwm");
output.innerHTML = slider.value; // Display the default slider value
// Update the current slider value (each time you drag the slider handle)
slider.oninput = function() {
output.innerHTML = this.value;
}
-132
View File
@@ -1,132 +0,0 @@
html {
font-size: 10px;
font-family: sans-serif, Arial, Helvetica;
background-color: #b3b3b3;
}
.topbar {
padding: 1em;
background-color: #1f1f1f;
color: white;
font-size: x-large;
text-align: center;
}
.control {
padding: 1em;
}
p, li {
font-size: 16px;
line-height: 2;
letter-spacing: 1px;
}
body {
margin: 0 auto;
border: 1px solid black;
border-radius: 3;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #04AA6D;
}
input:focus + .slider {
box-shadow: 0 0 1px #04AA6D;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
/* The slider itself */
.rangeslider {
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
width: 50%; /* Full-width */
height: 34px; /* Specified height */
border-radius: 34px; /* range round corners */
background: #d3d3d3; /* Grey background */
outline: none; /* Remove outline */
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
transition: opacity .2s;
}
/* Mouse-over effects */
.rangeslider:hover {
opacity: 1; /* Fully shown on mouse-over */
}
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
.rangeslider::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 26px; /* Set a specific slider handle width */
height: 26px; /* Slider handle height */
border-radius: 50%; /* Round Element */
background: #04AA6D; /* Green background */
cursor: pointer; /* Cursor on hover */
}
.rangeslider::-moz-range-thumb {
width: 26px; /* Set a specific slider handle width */
height: 26px; /* Slider handle height */
background: #04AA6D; /* Green background */
cursor: pointer; /* Cursor on hover */
}
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
void ota_setup() {
ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname("ESP_Treppenlicht");
ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
}
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
+128
View File
@@ -0,0 +1,128 @@
#include "filesys.h"
FSInfo fsinfo;
bool mount_fs() {
if(!LittleFS.begin()) {
Serial.println("[ERROR] LittleFS.info(), reset ...");
return false;
}
if(!LittleFS.info(fsinfo)) {
Serial.println("[ERROR] LittleFS.info(), reset ...");
return false;
}
printf("Filesystem opened:\n\r");
printf("\ttotalBytes:\t%d\n\r", fsinfo.totalBytes);
printf("\tusedBytes:\t%d\n\r", fsinfo.usedBytes);
printf("\tblockSize:\t%d\n\r", fsinfo.blockSize);
printf("\tpageSize:\t%d\n\r", fsinfo.pageSize);
printf("\tmaxOpenFiles:\t%d\n\r", fsinfo.maxOpenFiles);
printf("\tmaxPathLength:\t%d\n\r", fsinfo.maxPathLength);
printf("\n\r");
return true;
}
bool format_fs() {
printf("Formatting FS ! \n\r");
return LittleFS.format();
}
void ls(const char * dirname) {
Serial.printf("ls -l %s\n\r", dirname);
Dir root = LittleFS.openDir(dirname);
while (root.next()) {
File file = root.openFile("r");
time_t lw = file.getLastWrite();
struct tm * tmstruct = localtime(&lw);
Serial.printf("%8d %02d %02d %02d:%02d %s\n\r",
file.size(),
tmstruct->tm_mon + 1,
tmstruct->tm_mday,
tmstruct->tm_hour,
tmstruct->tm_min,
root.fileName().c_str());
file.close();
}
Serial.println();
}
File open(const char * path) {
return LittleFS.open(path, "r");
}
void printFile(const char * path) {
Serial.printf("Reading file: %s\n\r", path);
File file = LittleFS.open(path, "r");
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available()) {
Serial.write(file.read());
}
file.close();
}
void writeFile(const char * path, const char * message) {
Serial.printf("Writing file: %s\n\r", path);
File file = LittleFS.open(path, "w");
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
delay(2000); // Make sure the CREATE and LASTWRITE times are different
file.close();
}
void appendFile(const char * path, const char * message) {
Serial.printf("Appending to file: %s\n\r", path);
File file = LittleFS.open(path, "a");
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
void renameFile(const char * path1, const char * path2) {
Serial.printf("Renaming file %s to %s\n\r", path1, path2);
if (LittleFS.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(const char * path) {
Serial.printf("Deleting file: %s\n\r", path);
if (LittleFS.remove(path)) {
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <LittleFS.h>
// some usefull wrappers for Filesystem
bool mount_fs();
bool format_fs();
File open(const char * path);
void ls(const char * dirname);
void printFile(const char * path);
void writeFile(const char * path, const char * message);
void appendFile(const char * path, const char * message);
void renameFile(const char * path1, const char * path2);
void deleteFile(const char * path);
+68
View File
@@ -0,0 +1,68 @@
#include "httpserver.h"
bool HTTPServer::start() {
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();
Serial.printf("Server active on Port 80 !\n\r");
return true;
}
void HTTPServer::logf(const char *format, ...) {
va_list args;
va_start(args, format);
char temp[64];
size_t len = vsnprintf(temp, sizeof(temp), format, args);
Serial.print(log_prefix);
Serial.write(temp, len);
va_end(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) {
size_t len = vsnprintf(tbuf+tbuf_head, TBUF_LEN-tbuf_head, format, args);
tbuf_head += len;
}
va_end(args);
}
void HTTPServer::start_apps() {
// application handler
this->on("/app=terminal", HTTP_POST, [this]() {
if(tbuf_head) {
send(200, "text/plain", tbuf);
tbuf_head = 0;
}
});
}
+42
View File
@@ -0,0 +1,42 @@
// Wrapper for ESP8266WebServer with Filesystem as HTTP source
#pragma once
#include <ESP8266WebServer.h>
#include <stdarg.h>
#include "filesys.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);
}
public:
HTTPServer(const int _port, const char* _rootDir) :
ESP8266WebServer(_port), rootDir(_rootDir)
{ }
~HTTPServer()
{
Serial.printf("[HTTPServer] shut down ...\n\r");
}
bool start();
void start_apps();
void logf(const char *format, ...);
void logt(const char *format, ...);
};
+170
View File
@@ -0,0 +1,170 @@
//
// 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.22
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Fri Jul 2 17:45:36 2021
//
// Target selection: ert.tlc
// Embedded hardware selection: ARM Compatible->ARM Cortex-M
// Code generation objectives: Unspecified
// Validation result: Not run
//
#include "FSMTreppe.h"
// Named constants for Chart: '<Root>/FSMTreppe'
const uint8_t FSMTreppe_IN_animation_down = 1U;
const uint8_t FSMTreppe_IN_animation_up = 2U;
const uint8_t FSMTreppe_IN_idle = 3U;
// Model step function
void FSMTreppeModelClass::step()
{
// Chart: '<Root>/FSMTreppe' incorporates:
// Inport: '<Root>/anim_finished'
// 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_idle;
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 0U;
FSMTreppe_DW.got_sensor = 0U;
FSMTreppe_DW.got_anim_finished = 0U;
FSMTreppe_DW.finished_up = 0U;
FSMTreppe_DW.finished_dn = 0U;
} else {
switch (FSMTreppe_DW.is_c3_FSMTreppe) {
case FSMTreppe_IN_animation_down:
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 2U;
if ((FSMTreppe_DW.finished_dn == 1) || (FSMTreppe_DW.temporalCounter_i1 >=
300U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_idle;
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 0U;
FSMTreppe_DW.got_sensor = 0U;
FSMTreppe_DW.got_anim_finished = 0U;
FSMTreppe_DW.finished_up = 0U;
FSMTreppe_DW.finished_dn = 0U;
} else {
if (FSMTreppe_U.sensor_unten) {
FSMTreppe_DW.got_sensor = 1U;
}
if (FSMTreppe_U.anim_finished) {
FSMTreppe_DW.got_anim_finished = 1U;
}
if ((FSMTreppe_DW.got_anim_finished == 1) && (FSMTreppe_DW.got_sensor ==
1)) {
FSMTreppe_DW.finished_dn = 1U;
}
}
break;
case FSMTreppe_IN_animation_up:
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 1U;
if ((FSMTreppe_DW.finished_up == 1) || (FSMTreppe_DW.temporalCounter_i1 >=
300U)) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_idle;
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 0U;
FSMTreppe_DW.got_sensor = 0U;
FSMTreppe_DW.got_anim_finished = 0U;
FSMTreppe_DW.finished_up = 0U;
FSMTreppe_DW.finished_dn = 0U;
} else {
if (FSMTreppe_U.sensor_oben) {
FSMTreppe_DW.got_sensor = 1U;
}
if (FSMTreppe_U.anim_finished) {
FSMTreppe_DW.got_anim_finished = 1U;
}
if ((FSMTreppe_DW.got_anim_finished == 1) && (FSMTreppe_DW.got_sensor ==
1)) {
FSMTreppe_DW.finished_up = 1U;
}
}
break;
default:
// Outport: '<Root>/anim_active'
// case IN_idle:
FSMTreppe_Y.anim_active = 0U;
if (FSMTreppe_U.sensor_oben) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_animation_down;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 2U;
FSMTreppe_DW.got_sensor = 0U;
FSMTreppe_DW.got_anim_finished = 0U;
FSMTreppe_DW.finished_dn = 0U;
} else if (FSMTreppe_U.sensor_unten) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_animation_up;
FSMTreppe_DW.temporalCounter_i1 = 0U;
// Outport: '<Root>/anim_active'
FSMTreppe_Y.anim_active = 1U;
FSMTreppe_DW.got_sensor = 0U;
FSMTreppe_DW.got_anim_finished = 0U;
FSMTreppe_DW.finished_up = 0U;
}
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]
//
+120
View File
@@ -0,0 +1,120 @@
//
// 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.22
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Fri Jul 2 17:45:36 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; // '<Root>/FSMTreppe'
uint8_t is_active_c3_FSMTreppe; // '<Root>/FSMTreppe'
uint8_t is_c3_FSMTreppe; // '<Root>/FSMTreppe'
uint8_t got_anim_finished; // '<Root>/FSMTreppe'
uint8_t finished_up; // '<Root>/FSMTreppe'
uint8_t finished_dn; // '<Root>/FSMTreppe'
uint8_t got_sensor; // '<Root>/FSMTreppe'
};
// External inputs (root inport signals with default storage)
struct ExtU_FSMTreppe_T {
bool sensor_unten; // '<Root>/sensor_unten'
bool sensor_oben; // '<Root>/sensor_oben'
bool anim_finished; // '<Root>/anim_finished'
};
// External outputs (root outports fed by signals with default storage)
struct ExtY_FSMTreppe_T {
uint8_t anim_active; // '<Root>/anim_active'
};
// 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 = *pExtU_FSMTreppe_T;
}
// 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]
//
+238
View File
@@ -0,0 +1,238 @@
#include "treppe.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 = INT_TIME*abs(stopval - startval)/(float)time_per_stair; // only valid at 1ms function call interval
return 1;
}
if(startval > stopval){
current_pwm -= stepsize;
}
else {
current_pwm += stepsize;
}
// Serial.println((uint16_t)current_pwm);
pwmController.setChannelPWM(led, (uint16_t)current_pwm);
if(current_pwm > stopval - stepsize && current_pwm < stopval + stepsize){
if(stopval == 0) pwmController.setChannelPWM(led, 0);
return 0;
}
return 1;
}
void Treppe::ledsequence(){
static int8_t led = 0;
static uint16_t brightness = 0;
static uint16_t lastbrightness = 0;
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.printf("----Status Changed! onoff: %d, dir: %d\n", state, direction);
}
if(!finish){ // finish == 0 -> action pending
if(!softstart_led(led,lastbrightness, brightness)){
Serial.printf("one LED finished: led: %d, last: %d, curr %d\n",
led, lastbrightness, brightness);
if(direction){
led++;
if(led >= stairs)
finish = 1;
}
else{
led--;
if(led < 0)
finish = 1;
}
}
}
}
void Treppe::rampe()
{
if(state) {
finish = 0;
state = 0;// set parameter memory
}
if(!finish) {
if(direction) { // aufwärts
if(tick >= ticks_treppe-1) { // ziel erreicht
Serial.println("[Treppe] oberster tick !");
finish = 1;
return;
}
tick++; // eins hoch
}
else { // abwärts
if(tick <= 0) { // ziel erreicht
Serial.println("[Treppe] unterster tick !");
finish = 1;
return;
}
tick--; // eins runter
}
stufe = tick / ticks_pro_stufe;
float new_pwm = 0.0;
if(an_aus) {
new_pwm = differenz_pwm_pro_tick * (tick - ticks_pro_stufe*stufe);
new_pwm += idle_brightness;
if(direction) new_pwm += differenz_pwm_pro_tick;
}
else {
new_pwm = active_brightness - differenz_pwm_pro_tick * (tick - ticks_pro_stufe*stufe);
new_pwm += idle_brightness;
if(direction) new_pwm -= differenz_pwm_pro_tick;
}
pwmController.setChannelPWM(stufe, (uint16_t) new_pwm);
Serial.printf("tick %04u, led %02d:%02u, pwm %4.1f\n",
tick,
stufe,
(tick - ticks_pro_stufe*stufe),
new_pwm
);
}
}
void Treppe::setup(){
Serial.printf("differenz_pwm_pro_tick %f\n", differenz_pwm_pro_tick);
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_brightness);
pinMode(A0, INPUT);
pinMode(SENSOR1, INPUT);
pinMode(SENSOR2, INPUT);
pinMode(OE, OUTPUT);
digitalWrite(OE, 0);
Serial.println("Hello from Treppe");
Serial.print("Treppe: initial parameters: stairs=");
Serial.println(stairs);
}
void Treppe::task(){
FSMTreppe_Obj.step();
if(finish){
direction = switch_direction;
state = switch_state;
}
static uint8_t last_sensor_state[2] = {0,0};
uint8_t current_sensor_state[2] = {0,0};
current_sensor_state[0] = digitalRead(SENSOR1);
current_sensor_state[1] = digitalRead(SENSOR2);
if(current_sensor_state[0] && !last_sensor_state[0] && state == 0){
setTick(0);
setAnAus(1);
setDirection(1);
setState(1);
}
if(current_sensor_state[1] && !last_sensor_state[1] && state == 0){
setTick(0);
setAnAus(0);
setDirection(0);
setState(1);
}
// first switch - off approach, use timer later
if(!current_sensor_state[0] && last_sensor_state[0] && state == 1){
setTick(ticks_treppe);
setAnAus(1);
setDirection(1);
setState(0);
}
if(!current_sensor_state[1] && last_sensor_state[1] && state == 1){
setTick(ticks_treppe);
setAnAus(1);
setDirection(0);
setState(0);
}
last_sensor_state[0] = current_sensor_state[0];
last_sensor_state[1] = current_sensor_state[1];
ledsequence();
//Serial.printf("LDR: %f\n", ((float)analogRead(A0))/1023.*3.68);
}
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;
}
void Treppe::setDirection(uint8_t _direction){
switch_direction = _direction;
Serial.printf("Treppe: switch_direction=%d!\n", switch_direction);
if(finish) Serial.println("apply direction request immediately");
else Serial.println("currently active, dir change afterwards");
// to do: implement state command variable to determine dimm-state
}
void Treppe::setState(uint8_t _state){
if(state == _state) return;
else {
switch_state = _state;
Serial.printf("Treppe: switch_state=%d!\n", switch_state);
if(finish) Serial.println("apply state request immediately");
else Serial.println("currently active, state changes after activity");
}
}
+83
View File
@@ -0,0 +1,83 @@
#pragma once
#include "FSMTreppe/FSMTreppe.h"
#include "PCA9685.h"
#define SENSOR1 2
#define SENSOR2 12
#define OE 14
#define INT_TIME 20 // interrupt intervall [ms]
class Treppe {
private:
// initialize with i2c-Address 0, use Wire Library
PCA9685 pwmController;
FSMTreppeModelClass FSMTreppe_Obj;// Instance of model class
uint8_t stairs;
uint16_t time_per_stair = 300; // dimmtime per stair [ms]
uint16_t idle_brightness = 100;
uint16_t active_brightness = 2048;
uint8_t direction = 0;
uint8_t switch_direction = 0;
uint8_t state = 0;
uint8_t switch_state = 0;
uint8_t finish = 1;
// alternative
uint32_t tick = 0;
uint32_t stufe = 0;
uint8_t an_aus = 0;
uint32_t ticks_treppe = 0;
uint32_t ticks_pro_stufe = 0;
float differenz_pwm_pro_tick = 0.0;
// alternative
uint8_t softstart_led(uint8_t led, uint16_t startval, uint16_t stopval);
void ledsequence();
void rampe();
public:
Treppe(uint8_t _stairs) : stairs(_stairs){
FSMTreppe_Obj.initialize();
ticks_pro_stufe = time_per_stair / 20; // [ms]
ticks_treppe = ticks_pro_stufe * stairs;
differenz_pwm_pro_tick = (float) (active_brightness - idle_brightness)
/ (float) ticks_pro_stufe;
}
~Treppe() {
FSMTreppe_Obj.terminate();
}
void setup();
void task(); // call periodically
// Parameter section
uint16_t setIdle(uint16_t _idle_brightness);
uint16_t setActive(uint16_t _active_brightness);
uint16_t setTime(uint16_t _time_per_stair);
void setTick(uint32_t _tick) {
tick = _tick;
Serial.printf("Treppe: Tick: %u!\n", tick);
}
uint32_t getTicks() {
return ticks_treppe;
}
// Runtime Parameter section
void setDirection(uint8_t _direction);
void setState(uint8_t _state);
void setAnAus(uint8_t _an_aus) {
an_aus = _an_aus;
}
uint8_t getState() { return state;};
uint8_t getFinished() { return finish;};
uint8_t getDirection() {return direction;};
};
+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 /dev/ttyUSB0
thb loop
+72 -266
View File
@@ -1,194 +1,67 @@
#include <Arduino.h> #include <Arduino.h>
#include <Wire.h>
#ifdef WITH_DEBUGGING_ON
#include <GDBStub.h> // debugging support via GDBStub over UART
#endif
#include "PCA9685.h" #include "PCA9685.h"
#include <GDBStub.h> extern "C" {
#include "user_interface.h"
}
// OTA & WEB
#include "wifi_credentials.h"
#include "ota.h"
#include "httpserver.h"
// BOARD
#define ESP12_LED 2 #define ESP12_LED 2
#define NODEMCU_LED 16 #define NODEMCU_LED 16
extern "C" { // PWM
#include "user_interface.h" #include "treppe.h"
} os_timer_t timer1;
os_timer_t Timer1; // Verwaltungsstruktur des Timers uint8_t timer_flag = 0;
Treppe stairs(16);
int c; // WIFI
bool toggle = false; const char* ssid = STASSID;
uint32_t m=0; const char* password = STAPSK;
uint32_t dimmtimer = 0; // port 80, root directory of server '/'
uint8_t direction = 1; HTTPServer httpServer(80, "/");
uint8_t onoff = 1;
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); }
void ledsequence(uint8_t direction, uint8_t onoff, uint8_t factor);
uint8_t softstart_led(uint8_t led, uint16_t startval, uint16_t stopval, uint8_t factor);
void timerCallback(void *pArg) void timerCallback(void *pArg)
{ {
*((int *) pArg) += 1; *((int *) pArg) += 1;
stairs.task();
ledsequence(direction, onoff, 4);
// Serial.print("[");
// Serial.print(micros()-m);
// Serial.print("] timerCallback\n");
// m = micros();
} }
// OTA & WEB // ===============================================
#include "wifi_credentials.h" uint8_t inter = 0;
#include <ESP8266WiFi.h> ICACHE_RAM_ATTR void int_test(){
#include <WiFiUdp.h> inter = 1;
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#include "index.html.gz.h"
#include "style.css.gz.h"
#include "favicon.png.gz.h"
// images are possible
// maybe check out FS <- SPIFFS
const char* ssid = STASSID;
const char* password = STAPSK;
void setup_webserver();
void setup_ota();
void setup_pwm_pca9685();
void handleRootGz();
void handleCssGz();
void handleNotFound();
const int led = 13;
ESP8266WebServer server(80);
PCA9685 pwmController;
void handleRootGz() {
const char* dataType = "text/html";
server.sendHeader(F("Content-Encoding"), F("gzip"));
server.send(200, dataType, (const char*)index_html_gz, index_html_gz_len);
}
void handleCssGz() {
const char* dataType = "text/css";
server.sendHeader(F("Content-Encoding"), F("gzip"));
server.send(200, dataType, (const char*)style_css_gz, style_css_gz_len);
}
void handleFaviconGz() {
const char* dataType = "image/png";
server.sendHeader(F("Content-Encoding"), F("gzip"));
server.send(200, dataType, (const char*)favicon_png_gz, favicon_png_gz_len);
}
void handleNotFound() {
digitalWrite(led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(led, 0);
}
void setup_webserver() {
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handleRootGz);
server.on("/style.css", handleCssGz);
server.on("/favicon.png", handleFaviconGz);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void setup_ota() {
ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname("ESP_Treppenlicht");
ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
}
void setup_pwm_pca9685() {
pwmController.resetDevices(); // Software resets all PCA9685 devices on Wire line
pwmController.init(B000000); // Address pins A5-A0 set to B000000
pwmController.setPWMFrequency(200); // Default is 200Hz, supports 24Hz to 1526Hz
Serial.println(pwmController.getChannelPWM(0)); // Should output 2048, which is 128 << 4
} }
void setup() { void setup() {
#ifdef WITH_DEBUGGING_ON
Serial.begin(460800); Serial.begin(460800);
gdbstub_init(); gdbstub_init();
#else
Serial.begin(76800);
#endif
Serial.println(F("Booting ....")); Serial.println(F("Booting ...."));
pinMode(NODEMCU_LED, OUTPUT); //pinMode(NODEMCU_LED, OUTPUT);
pinMode(ESP12_LED, OUTPUT); pinMode(ESP12_LED, OUTPUT);
Wire.begin(); // Wire must be started first Wire.begin(); // Wire must be started first
Wire.setClock(400000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz Wire.setClock(1000000); // Supported baud rates are 100kHz, 400kHz, and 1000kHz
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
@@ -199,119 +72,52 @@ void setup() {
ESP.restart(); ESP.restart();
} }
os_timer_setfn(&Timer1, timerCallback, &c); Serial.println("");
os_timer_arm(&Timer1, 1, true); Serial.print("Connected to ");
Serial.println(ssid);
Serial.println("Ready");
Serial.print("IP address: "); Serial.print("IP address: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
setup_ota(); ota_setup();
setup_webserver();
setup_pwm_pca9685(); httpServer.start();
httpServer.start_apps();
Serial.println("HTTP server started !");
stairs.setup();
Serial.println("PCA9685 connected !");
//attachInterrupt(digitalPinToInterrupt(2), int_test, RISING);
//attachInterrupt(digitalPinToInterrupt(12), int_test, RISING);
os_timer_setfn(&timer1, timerCallback, &timer_flag);
os_timer_arm(&timer1, 20, true);
} }
uint32_t t; #include <random>
#define SP_US(_str,_a) Serial.print(_str); Serial.print(" took: "); Serial.print(_a); Serial.println("µs")
#define TIMEIF_US(_str,_f, _l) t=micros(); _f; t=micros()-t; if(t > _l) { SP_US(_str, t); }
uint8_t softstart_led(uint8_t led, uint16_t startval, uint16_t stopval, uint8_t factor){
static uint8_t lastled = 255;
static uint8_t current_pwm = 0;
if(led != lastled){
pwmController.setChannelPWM(led, startval);
lastled = led;
current_pwm = startval;
return 1;
}
if(current_pwm == stopval){
return 0;
}
else if(startval > stopval){
current_pwm -= 1;
}
else {
current_pwm += 1;
}
pwmController.setChannelPWM(led, current_pwm*factor);
return 1;
}
#define LEDCOUNT 16
void ledsequence(uint8_t direction, uint8_t onoff, uint8_t factor){
static int8_t led = 0;
static uint8_t brightness = 0;
static uint8_t lastbrightness = 0;
static uint8_t finish = 1;
static uint32_t status = 0;
uint32_t status_build = 0;
status_build |= direction << 16;
status_build |= onoff << 8;
status_build |= factor;
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 = LEDCOUNT-1;
if(onoff){
brightness = 127; // set brightness value depending of on/off
lastbrightness = 0;
}
else{
brightness = 0;
lastbrightness = 127;
}
status = status_build; // set parameter memory
Serial.print("----Status Changed! onoff: ");
Serial.print(onoff);
Serial.print(" dir: ");
Serial.println(direction);
}
if(!finish){ // finish == 0 -> action pending
if(!softstart_led(led,lastbrightness, brightness, factor)){
Serial.print("one LED finished, new set led: ");
Serial.print(led);
Serial.print(" last: ");
Serial.print(lastbrightness);
Serial.print(" curr: ");
Serial.println(brightness);
if(direction){
led++;
if(led >= LEDCOUNT) {
finish = 1;
//lastbrightness = brightness;
}
}
else{
led--;
if(led < 0){
//lastbrightness = brightness;
finish = 1;
}
}
}
}
}
uint32_t c = 0;
void loop() { void loop() {
// if(stairs.getState() == 0) {
// delay(1000);
// // uint32_t t = rand() % stairs.getTicks();
// // uint32_t d = rand() % 2;
// // stairs.setTick(t);
// // stairs.setDirection(d);
if(millis() - dimmtimer > 2){ // stairs.setDirection(!stairs.getDirection());
//ledsequence(direction, onoff, 4); // stairs.setState(1);
dimmtimer = millis(); // }
if(inter){
Serial.printf("interrupt\n");
inter = 0;
} }
if(millis() > 25000 && onoff == 1 && direction == 1) onoff = 0; if(c++%1000000 == 0)
if(millis() > 35000 && direction == 1){ httpServer.logt("[%d] starting :)\n", c);
onoff = 1;
direction = 0; TIMEIF_US(ArduinoOTA.handle(), 10000, "OTA");
} TIMEIF_US(httpServer.handleClient(), 10000, "HTTP");
TIMEIF_US("OTA", ArduinoOTA.handle(), 1000);
TIMEIF_US("HTTP", server.handleClient(), 1000);
} }
+6
View File
@@ -0,0 +1,6 @@
#!/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
cd ..
echo "Starting gdb"
$GDB_PATH -x scripts/gdboptions
+63 -7
View File
@@ -8,21 +8,77 @@
; 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:esp01_1m] [platformio]
description = ESP8266 Treppenlicht Steuerung
default_envs = ota
; test_dir = test
data_dir = data_gz
[env:hardware]
platform = espressif8266 platform = espressif8266
board = esp01_1m board = nodemcuv2
framework = arduino framework = arduino
board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m1m.ld
extra_scripts = pre:create_gz_files.py
monitor_speed = 115200 monitor_speed = 115200
extra_scripts = pre:extra_script.py [env:serial]
extends = env:hardware
upload_protocol = esptool
upload_speed = 921600
; stuff for OTA [env:ota]
; https://docs.platformio.org/en/latest/platforms/espressif8266.html#over-the-air-ota-update extends = env:hardware
; 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 !!>
upload_flags = upload_flags =
--port=8266 --port=8266
--host_port=<!! PORT !!>
--auth=admin --auth=admin
lib_deps =
ottowinter/PCA9685 16-Channel PWM Driver Module Library @ 1.2.9 [env:debug]
extends = env:hardware
; look at doku.md
build_flags = -DWITH_DEBUGGING_ON -Os -g3 -ggdb3
upload_protocol = esptool
upload_speed = 921600
# 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
+40
View File
@@ -0,0 +1,40 @@
// #include <Arduino.h>
// #include <unity.h>
// String STR_TO_TEST;
// // void setUp(void) {
// // // set stuff up here
// // STR_TO_TEST = "Hello, world!";
// // }
// // void tearDown(void) {
// // // clean stuff up here
// // STR_TO_TEST = "";
// // }
// void test_led_builtin_pin_number(void) {
// TEST_ASSERT_EQUAL(2, LED_BUILTIN);
// }
// void test_string_concat(void) {
// String hello = "Hello, ";
// String world = "world!";
// TEST_ASSERT_EQUAL_STRING(STR_TO_TEST.c_str(), (hello + world).c_str());
// }
// void setup()
// {
// delay(2000); // service delay
// UNITY_BEGIN();
// RUN_TEST(test_led_builtin_pin_number);
// RUN_TEST(test_string_concat);
// UNITY_END(); // stop unit testing
// }
// 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()
{
}
+1 -1
View File
@@ -1,2 +1,2 @@
CD .\include\http CD .\data
py.exe -m http.server py.exe -m http.server
Executable
+2
View File
@@ -0,0 +1,2 @@
cd data
python3 -m http.server