21 Commits
Author SHA1 Message Date
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
10 changed files with 596 additions and 472 deletions

No files matched your search

+15 -2
View File
@@ -54,14 +54,27 @@ else
server.streamFile(f, mime::getContentType(SRH::_path), requestMethod);
```
LED_sequence_v1:
### 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
### 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
### Webserver on v0.3.0 now working with LittleFS
TODO:
- check dir for files automatic
- move handleNotFound to httpserver.h
+2 -2
View File
@@ -1,8 +1,8 @@
#pragma once
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
void ota_setup() {
ArduinoOTA.setPort(8266);
@@ -45,4 +45,4 @@ void ota_setup() {
});
ArduinoOTA.begin();
}
}
-170
View File
@@ -1,170 +0,0 @@
//
// 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]
//
+237
View File
@@ -0,0 +1,237 @@
//
// 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.29
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Sat Jul 3 17:39:25 2021
//
// Target selection: ert.tlc
// Embedded hardware selection: ARM Compatible->ARM Cortex-M
// Code generation objectives: Unspecified
// Validation result: Not run
//
#include "FSMTreppe2.h"
#include <stdint.h>
// Named constants for Chart: '<Root>/FSMTreppe'
const uint8_t FSMTreppe_IN_abdimmen_hoch = 1U;
const uint8_t FSMTreppe_IN_abdimmen_runter = 2U;
const uint8_t FSMTreppe_IN_aufdimmen_hoch = 3U;
const uint8_t FSMTreppe_IN_aufdimmen_runter = 4U;
const uint8_t FSMTreppe_IN_inaktiv = 5U;
const uint8_t FSMTreppe_IN_ruhezustand = 6U;
const uint8_t FSMTreppe_IN_warten_hoch = 7U;
const uint8_t FSMTreppe_IN_warten_runter = 8U;
// 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 = 4U;
if (FSMTreppe_U.anim_beendet || (FSMTreppe_DW.temporalCounter_i1 >= 500U))
{
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
}
break;
case FSMTreppe_IN_abdimmen_runter:
// Outport: '<Root>/dimmrichtung'
FSMTreppe_Y.dimmrichtung = 0U;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 7U;
if (FSMTreppe_U.anim_beendet || (FSMTreppe_DW.temporalCounter_i1 >= 500U))
{
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
}
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 = 2U;
if (FSMTreppe_U.anim_beendet || (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 = 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 = 5U;
if (FSMTreppe_U.anim_beendet || (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 = 6U;
}
break;
case FSMTreppe_IN_inaktiv:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 0U;
if (FSMTreppe_U.ldr_schwelle == 1.0) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_ruhezustand;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
}
break;
case FSMTreppe_IN_ruhezustand:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 1U;
if (FSMTreppe_U.sensor_unten) {
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 = 2U;
} else if (FSMTreppe_U.sensor_oben) {
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 = 5U;
} else if (FSMTreppe_U.ldr_schwelle == 0.0) {
FSMTreppe_DW.is_c3_FSMTreppe = FSMTreppe_IN_inaktiv;
// Outport: '<Root>/status'
FSMTreppe_Y.status = 0U;
}
break;
case FSMTreppe_IN_warten_hoch:
// Outport: '<Root>/status'
FSMTreppe_Y.status = 3U;
if (FSMTreppe_U.sensor_oben || (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 = 4U;
}
break;
default:
// Outport: '<Root>/status'
// case IN_warten_runter:
FSMTreppe_Y.status = 6U;
if (FSMTreppe_U.sensor_unten || (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 = 7U;
}
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]
//
@@ -7,9 +7,9 @@
//
// Code generated for Simulink model 'FSMTreppe'.
//
// Model version : 1.22
// Model version : 1.28
// Simulink Coder version : 9.5 (R2021a) 14-Nov-2020
// C/C++ source code generated on : Fri Jul 2 17:45:36 2021
// C/C++ source code generated on : Sat Jul 3 13:50:17 2021
//
// Target selection: ert.tlc
// Embedded hardware selection: ARM Compatible->ARM Cortex-M
@@ -30,22 +30,21 @@ class FSMTreppeModelClass {
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'
bool anim_beendet; // '<Root>/anim_beendet'
double ldr_schwelle; // '<Root>/ldr_schwelle'
};
// External outputs (root outports fed by signals with default storage)
struct ExtY_FSMTreppe_T {
uint8_t anim_active; // '<Root>/anim_active'
uint8_t laufrichtung; // '<Root>/laufrichtung'
uint8_t status; // '<Root>/status'
uint8_t dimmrichtung; // '<Root>/dimmrichtung'
};
// model initialize function
+261 -217
View File
@@ -1,238 +1,282 @@
#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()
/*
dimm_stufe
- dimmt stufe (0 - 15, PCA9685 outputs) mit linearen ticks
von idle bis active brightness
- return false solange gedimmt wird
- return true bei nächster stufe
*/
bool Treppe::dimm_stufe(uint8_t stufe)
{
if(state) {
finish = 0;
state = 0;// set parameter memory
}
if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN)
current_pwm += differenz_pwm_pro_tick;
else
current_pwm -= differenz_pwm_pro_tick;
pwmController.setChannelPWM(stufe, static_cast<uint16_t>(current_pwm));
if(!finish) {
if(direction) { // aufwärts
if(tick >= ticks_treppe-1) { // ziel erreicht
Serial.println("[Treppe] oberster tick !");
finish = 1;
current_tick++;
if (current_tick >= ticks_pro_stufe)
return false;
return true;
}
/*
animation tick
- nach dem dimmen einer stufe wird die stufe weitergezählt
- abbruch am ende => anim_beendet = true;
*/
void Treppe::anim_tick()
{
if (!dimm_stufe(stufe))
{
Serial.printf("anim_tick(): stufe: %d, start: %d, ziel: %d, current %f\n",
stufe, start_pwm, ziel_pwm, current_pwm);
if (fsm_outputs.laufrichtung == LR_HOCH)
{
if (stufe >= stufen - 1)
{
anim_beendet = true;
return;
}
tick++; // eins hoch
stufe++;
}
else { // abwärts
if(tick <= 0) { // ziel erreicht
Serial.println("[Treppe] unterster tick !");
finish = 1;
else
{
if (stufe <= 0)
{
anim_beendet = true;
return;
}
tick--; // eins runter
stufe--;
}
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
);
current_tick = 0;
current_pwm = start_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);
// startbedingunen für animation
void Treppe::start_animation()
{
anim_beendet = false;
if (fsm_outputs.laufrichtung == LR_HOCH)
stufe = 0;
else
stufe = stufen - 1;
if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN)
{
start_pwm = idle_bright_internal;
ziel_pwm = active_brightness;
}
else
{
start_pwm = active_brightness;
ziel_pwm = idle_bright_internal;
}
current_tick = 0;
current_pwm = start_pwm;
}
void Treppe::task(){
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_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_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, beendet: %d =>",
fsm_inputs.sensor_oben, fsm_inputs.sensor_unten, fsm_inputs.anim_beendet);
Serial.print(" step => ");
Serial.printf("OUT: LR: %d DR: %d ST: %d\n",
fsm_outputs.laufrichtung, fsm_outputs.dimmrichtung, fsm_outputs.status);
}
}
bool Treppe::read_sensor(int sensor)
{
/*
reads sensors with edge detection
returns true if motion was detected
returns false if no motion was detected
returns false if motion was detected, but state did not change back to not detected
*/
uint8_t pegel = digitalRead(sensor);
static uint8_t pegel_alt[2] = {0, 0};
uint8_t index = 0;
if (sensor == SENSOR_OBEN)
index = 0;
else
index = 1;
if (pegel == 1 && pegel_alt[index] == 0)
{
pegel_alt[index] = pegel;
return true;
}
else
{
pegel_alt[index] = pegel;
return false;
}
//return static_cast<bool>(pegel);
}
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) = 79.735 * R(LDR)^-0.498 (see Excel Regression)
ldr_value = E(LDR)
*/
float ldr_ohm = 37280.00 / analogRead(A0);
float ldr_value = 79.735 * pow(ldr_ohm, -0.498);
return ldr_value;
}
bool Treppe::check_ldr()
{
static uint8_t active = 0;
#ifdef LDRDEBUG
Serial.printf("R(LDR) = %f kOhm %f lux\n", ldr_value, lux);
return true;
#endif
// follow up: averaging over many samples?
float ldr = read_ldr();
if (ldr < ldr_schwelle)
active = 1;
if (ldr > ldr_schwelle + LDR_HYS)
active = 0;
activate_idle_pwm(active);
return active;
}
void Treppe::task()
{
fsm_inputs.ldr_schwelle = check_ldr();
fsm_inputs.sensor_oben = read_sensor(SENSOR_OBEN);
fsm_inputs.sensor_unten = read_sensor(SENSOR_UNTEN);
fsm_inputs.anim_beendet = static_cast<bool>(anim_beendet);
FSMTreppe_Obj.setExternalInputs(&fsm_inputs);
FSMTreppe_Obj.step();
fsm_outputs = FSMTreppe_Obj.getExternalOutputs();
print_state_on_change();
if(finish){
direction = switch_direction;
state = switch_state;
if (fsm_outputs.status > ST_RUHEZUSTAND)
{
if (anim_beendet == true &&
(fsm_outputs.status == ST_AUFDIMMEN_HOCH || fsm_outputs.status == ST_ABDIMMEN_HOCH ||
fsm_outputs.status == ST_AUFDIMMEN_RUNTER || fsm_outputs.status == ST_ABDIMMEN_RUNTER))
{
start_animation();
}
if (!anim_beendet)
anim_tick();
}
}
void Treppe::berechne_dimmer()
{
ticks_pro_stufe = time_per_stair / INT_TIME; // [ms]
differenz_pwm_pro_tick = (float)(active_brightness - idle_brightness) / (float)ticks_pro_stufe;
}
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_brightness);
pinMode(A0, INPUT);
pinMode(SENSOR_OBEN, INPUT);
pinMode(SENSOR_UNTEN, INPUT);
pinMode(OE, OUTPUT);
digitalWrite(OE, 0);
Serial.printf("differenz_pwm_pro_tick %f\n", differenz_pwm_pro_tick);
Serial.printf("Treppe: initial parameters: stufen=%d\n", stufen);
}
// ###################################################################################################################
// GEBUFFERT => Erst im Ruhezustand übernehmen !!!!
void Treppe::set_idle_pwm(uint16_t _idle_brightness)
{
idle_brightness = _idle_brightness;
berechne_dimmer();
Serial.printf("Treppe: idle_brightness=%d\n", idle_brightness);
}
void Treppe::activate_idle_pwm(bool active){
static uint8_t former_active = 0;
if(active != former_active && fsm_outputs.status == ST_RUHEZUSTAND){
idle_bright_internal = idle_brightness * active;
// Dimming Function for all LEDS ?
pwmController.setAllChannelsPWM(idle_bright_internal);
former_active = active;
}
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;
void Treppe::set_active_pwm(uint16_t _active_brightness)
{
active_brightness = _active_brightness;
berechne_dimmer();
Serial.printf("Treppe: active_brightness=%d\n", active_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");
}
void Treppe::set_time_per_stair(uint16_t _time_per_stair)
{
time_per_stair = _time_per_stair;
berechne_dimmer();
Serial.printf("Treppe: time_per_stair=%d\n", time_per_stair);
}
+62 -57
View File
@@ -1,54 +1,77 @@
#pragma once
#include "FSMTreppe/FSMTreppe.h"
#include "FSMTreppe2/FSMTreppe2.h"
#include "PCA9685.h"
#define SENSOR1 2
#define SENSOR2 12
// #define LDRDEBUG // comment in to override LDR measurement
#define LDR_HYS 5.0 // Hysteresis for switching off FSM [lux]
#define SENSOR_OBEN 16
#define SENSOR_UNTEN 12
#define OE 14
#define INT_TIME 20 // interrupt intervall [ms]
class Treppe {
private:
const uint8_t stufen;
uint16_t time_per_stair = 300; // dimmtime per stair [ms]
uint16_t idle_brightness = 100;
uint16_t idle_bright_internal = 0;
uint16_t active_brightness = 500;
uint16_t ldr_schwelle = 7; // activation value for FSM [lx]
uint16_t start_pwm = 0;
uint16_t ziel_pwm = 0;
bool anim_beendet = true;
uint8_t stufe = 0;
uint16_t current_tick = 0;
float current_pwm = 0.0;
uint16_t ticks_pro_stufe = 0;
float differenz_pwm_pro_tick = 0.0;
// initialize with i2c-Address 0, use Wire Library
PCA9685 pwmController;
FSMTreppeModelClass FSMTreppe_Obj;// Instance of model class
FSMTreppeModelClass FSMTreppe_Obj;
FSMTreppeModelClass::ExtU_FSMTreppe_T fsm_inputs;
FSMTreppeModelClass::ExtY_FSMTreppe_T fsm_outputs;
enum fsm_status_t {
ST_INAKTIV_LDR =0,
ST_RUHEZUSTAND =1,
ST_AUFDIMMEN_HOCH =2,
ST_WARTEN_HOCH =3,
ST_ABDIMMEN_HOCH =4,
ST_AUFDIMMEN_RUNTER =5,
ST_WARTEN_RUNTER =6,
ST_ABDIMMEN_RUNTER =7
};
enum fsm_laufrichtung_t {
LR_RUNTER=0,
LR_HOCH=1
};
enum fsm_dimmrichtung_t {
DR_ABDIMMEN=0,
DR_AUFDIMMEN=1
};
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();
/* DIMM */
bool dimm_stufe(uint8_t stufe);
void anim_tick();
void start_animation();
void berechne_dimmer();
void print_state_on_change();
/* LDR */
bool read_sensor(int sensor);
float read_ldr();
bool check_ldr();
public:
Treppe(uint8_t _stairs) : stairs(_stairs){
Treppe(uint8_t _stufen) : stufen(_stufen){
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;
berechne_dimmer();
}
~Treppe() {
FSMTreppe_Obj.terminate();
@@ -58,26 +81,8 @@ public:
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;};
void set_idle_pwm(uint16_t _idle_brightness);
void activate_idle_pwm(bool active);
void set_active_pwm(uint16_t _active_brightness);
void set_time_per_stair(uint16_t _time_per_stair);
};
Binary file not shown.
-14
View File
@@ -94,23 +94,9 @@ void setup() {
os_timer_arm(&timer1, 20, true);
}
#include <random>
uint32_t c = 0;
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);
// stairs.setDirection(!stairs.getDirection());
// stairs.setState(1);
// }
if(inter){
Serial.printf("interrupt\n");
inter = 0;
+12 -2
View File
@@ -16,13 +16,23 @@ data_dir = data_gz
[env:hardware]
platform = espressif8266
board = nodemcuv2
; board = nodemcuv2
board = huzzah
framework = arduino
; for pio check
; check_tool = cppcheck
check_tool = clangtidy
check_flags =
; clangtidy: --fix-errors
clangtidy: lib/httpserver/* lib/treppe/* lib/PCA9685-Arduino/*
check_skip_packages = yes
board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m1m.ld
extra_scripts = pre:create_gz_files.py
monitor_speed = 115200
monitor_speed = 76800
[env:serial]
extends = env:hardware