added LDR evaluation + sensor edge detection

This commit is contained in:
Dominik Bartsch 2021-07-05 11:40:45 +02:00
parent 278179fa6e
commit 2f6502ce20
2 changed files with 216 additions and 120 deletions

View File

@ -1,6 +1,5 @@
#include "treppe.h" #include "treppe.h"
/* /*
dimm_stufe dimm_stufe
- dimmt stufe (0 - 15, PCA9685 outputs) mit linearen ticks - dimmt stufe (0 - 15, PCA9685 outputs) mit linearen ticks
@ -10,16 +9,16 @@
*/ */
bool Treppe::dimm_stufe(uint8_t stufe) bool Treppe::dimm_stufe(uint8_t stufe)
{ {
if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN) if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN)
current_pwm += differenz_pwm_pro_tick; current_pwm += differenz_pwm_pro_tick;
else else
current_pwm -= differenz_pwm_pro_tick; current_pwm -= differenz_pwm_pro_tick;
pwmController.setChannelPWM(stufe, static_cast<uint16_t> (current_pwm)); pwmController.setChannelPWM(stufe, static_cast<uint16_t>(current_pwm));
current_tick++; current_tick++;
if (current_tick >= ticks_pro_stufe) if (current_tick >= ticks_pro_stufe)
return false; return false;
return true; return true;
} }
/* /*
@ -29,150 +28,242 @@ bool Treppe::dimm_stufe(uint8_t stufe)
*/ */
void Treppe::anim_tick() void Treppe::anim_tick()
{ {
if (!dimm_stufe(stufe)) if (!dimm_stufe(stufe))
{ {
Serial.printf("anim_tick(): stufe: %d, start: %d, ziel: %d, current %f\n", Serial.printf("anim_tick(): stufe: %d, start: %d, ziel: %d, current %f\n",
stufe, start_pwm, ziel_pwm, current_pwm); stufe, start_pwm, ziel_pwm, current_pwm);
if (fsm_outputs.laufrichtung == LR_HOCH) if (fsm_outputs.laufrichtung == LR_HOCH)
{ {
if (stufe >= stufen-1) { if (stufe >= stufen - 1)
anim_beendet = true; {
return; anim_beendet = true;
} return;
stufe++; }
} stufe++;
else
{
if (stufe <= 0) {
anim_beendet = true;
return;
}
stufe--;
}
current_tick = 0;
current_pwm = start_pwm;
} }
else
{
if (stufe <= 0)
{
anim_beendet = true;
return;
}
stufe--;
}
current_tick = 0;
current_pwm = start_pwm;
}
} }
// startbedingunen für animation // startbedingunen für animation
void Treppe::start_animation() { void Treppe::start_animation()
anim_beendet = false; {
anim_beendet = false;
if(fsm_outputs.laufrichtung == LR_HOCH) if (fsm_outputs.laufrichtung == LR_HOCH)
stufe = 0; stufe = 0;
else else
stufe = stufen-1; stufe = stufen - 1;
if(fsm_outputs.dimmrichtung == DR_AUFDIMMEN) {
start_pwm = idle_brightness;
ziel_pwm = active_brightness;
} else {
start_pwm = active_brightness;
ziel_pwm = idle_brightness;
}
current_tick = 0; if (fsm_outputs.dimmrichtung == DR_AUFDIMMEN)
current_pwm = start_pwm; {
start_pwm = idle_brightness;
ziel_pwm = active_brightness;
}
else
{
start_pwm = active_brightness;
ziel_pwm = idle_brightness;
}
current_tick = 0;
current_pwm = start_pwm;
} }
void Treppe::print_state_on_change() void Treppe::print_state_on_change()
{ {
static FSMTreppeModelClass::ExtU_FSMTreppe_T last_in; static FSMTreppeModelClass::ExtU_FSMTreppe_T last_in;
static FSMTreppeModelClass::ExtY_FSMTreppe_T last_out; static FSMTreppeModelClass::ExtY_FSMTreppe_T last_out;
if ( if (
fsm_inputs.anim_beendet != last_in.anim_beendet || fsm_inputs.anim_beendet != last_in.anim_beendet ||
fsm_inputs.sensor_oben != last_in.sensor_oben || fsm_inputs.sensor_oben != last_in.sensor_oben ||
fsm_inputs.sensor_unten != last_in.sensor_unten || fsm_inputs.sensor_unten != last_in.sensor_unten ||
fsm_outputs.dimmrichtung != last_out.dimmrichtung || fsm_outputs.dimmrichtung != last_out.dimmrichtung ||
fsm_outputs.laufrichtung != last_out.laufrichtung || fsm_outputs.laufrichtung != last_out.laufrichtung ||
fsm_outputs.status != last_out.status) fsm_outputs.status != last_out.status)
{ {
last_in.anim_beendet = fsm_inputs.anim_beendet; last_in.anim_beendet = fsm_inputs.anim_beendet;
last_in.sensor_oben = fsm_inputs.sensor_oben; last_in.sensor_oben = fsm_inputs.sensor_oben;
last_in.sensor_unten = fsm_inputs.sensor_unten; last_in.sensor_unten = fsm_inputs.sensor_unten;
last_out.dimmrichtung = fsm_outputs.dimmrichtung; last_out.dimmrichtung = fsm_outputs.dimmrichtung;
last_out.laufrichtung = fsm_outputs.laufrichtung; last_out.laufrichtung = fsm_outputs.laufrichtung;
last_out.status = fsm_outputs.status; last_out.status = fsm_outputs.status;
Serial.printf("FSM IN: s_u: %d, s_o: %d, beendet: %d =>", Serial.printf("FSM IN: s_u: %d, s_o: %d, beendet: %d =>",
fsm_inputs.sensor_oben, fsm_inputs.sensor_unten, fsm_inputs.anim_beendet); fsm_inputs.sensor_oben, fsm_inputs.sensor_unten, fsm_inputs.anim_beendet);
Serial.print(" step => "); Serial.print(" step => ");
Serial.printf("OUT: LR: %d DR: %d ST: %d\n", Serial.printf("OUT: LR: %d DR: %d ST: %d\n",
fsm_outputs.laufrichtung, fsm_outputs.dimmrichtung, fsm_outputs.status); 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()
{
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?
if(read_ldr() < ldr_schwelle) active = 1;
if(read_ldr() > ldr_schwelle + LDR_HYS) active = 0;
return active;
} }
void Treppe::task() void Treppe::task()
{ {
//Serial.printf("LDR: %f\n", ((float)analogRead(A0))/1023.*3.68); //Serial.printf("LDR: %f\n", ((float)analogRead(A0))/1023.*3.68);
fsm_inputs.ldr_schwelle = true; // <=== LDR implementierung !! fsm_inputs.ldr_schwelle = read_ldr(); // <=== LDR implementierung !!
fsm_inputs.sensor_oben = read_sensor(SENSOR_OBEN); fsm_inputs.sensor_oben = read_sensor(SENSOR_OBEN);
fsm_inputs.sensor_unten = read_sensor(SENSOR_UNTEN); fsm_inputs.sensor_unten = read_sensor(SENSOR_UNTEN);
fsm_inputs.anim_beendet = static_cast<bool>(anim_beendet); fsm_inputs.anim_beendet = static_cast<bool>(anim_beendet);
FSMTreppe_Obj.setExternalInputs(&fsm_inputs); FSMTreppe_Obj.setExternalInputs(&fsm_inputs);
FSMTreppe_Obj.step(); FSMTreppe_Obj.step();
fsm_outputs = FSMTreppe_Obj.getExternalOutputs(); fsm_outputs = FSMTreppe_Obj.getExternalOutputs();
print_state_on_change(); print_state_on_change();
if(fsm_outputs.status > ST_RUHEZUSTAND) { if (fsm_outputs.status > ST_RUHEZUSTAND)
if( anim_beendet == true && {
( fsm_outputs.status == ST_AUFDIMMEN_HOCH || fsm_outputs.status == ST_ABDIMMEN_HOCH || if (anim_beendet == true &&
fsm_outputs.status == ST_AUFDIMMEN_RUNTER || fsm_outputs.status == ST_ABDIMMEN_RUNTER )) (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(); {
} start_animation();
if( !anim_beendet )
anim_tick();
} }
if (!anim_beendet)
anim_tick();
}
} }
void Treppe::berechne_dimmer() { void Treppe::berechne_dimmer()
ticks_pro_stufe = time_per_stair / INT_TIME; // [ms] {
differenz_pwm_pro_tick = (float) (active_brightness - idle_brightness) ticks_pro_stufe = time_per_stair / INT_TIME; // [ms]
/ (float) ticks_pro_stufe; differenz_pwm_pro_tick = (float)(active_brightness - idle_brightness) / (float)ticks_pro_stufe;
} }
void Treppe::setup() void Treppe::setup()
{ {
pwmController.resetDevices(); pwmController.resetDevices();
// Deactive PCA9685 Phase Balancer due to LED Flickering // Deactive PCA9685 Phase Balancer due to LED Flickering
// https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15 // https://github.com/NachtRaveVL/PCA9685-Arduino/issues/15
// see also lib/PCA9685-Arduin/PCA9685.h:204 // see also lib/PCA9685-Arduin/PCA9685.h:204
pwmController.init(PCA9685_PhaseBalancer_None); pwmController.init(PCA9685_PhaseBalancer_None);
//pwmController.init(PCA9685_PhaseBalancer_Linear); //pwmController.init(PCA9685_PhaseBalancer_Linear);
pwmController.setPWMFrequency(100); pwmController.setPWMFrequency(100);
pwmController.setAllChannelsPWM(idle_brightness); pwmController.setAllChannelsPWM(idle_brightness);
pinMode(A0, INPUT); pinMode(A0, INPUT);
pinMode(SENSOR_OBEN, INPUT); pinMode(SENSOR_OBEN, INPUT);
pinMode(SENSOR_UNTEN, INPUT); pinMode(SENSOR_UNTEN, INPUT);
pinMode(OE, OUTPUT); pinMode(OE, OUTPUT);
digitalWrite(OE, 0); digitalWrite(OE, 0);
Serial.printf("differenz_pwm_pro_tick %f\n", differenz_pwm_pro_tick); Serial.printf("differenz_pwm_pro_tick %f\n", differenz_pwm_pro_tick);
Serial.printf("Treppe: initial parameters: stufen=%d\n", stufen); Serial.printf("Treppe: initial parameters: stufen=%d\n", stufen);
} }
// ################################################################################################################### // ###################################################################################################################
// GEBUFFERT => Erst im Ruhezustand übernehmen !!!! // GEBUFFERT => Erst im Ruhezustand übernehmen !!!!
void Treppe::set_idle_pwm(uint16_t _idle_brightness) void Treppe::set_idle_pwm(uint16_t _idle_brightness)
{ {
idle_brightness = _idle_brightness; idle_brightness = _idle_brightness;
berechne_dimmer(); berechne_dimmer();
Serial.printf("Treppe: idle_brightness=%d\n", idle_brightness); Serial.printf("Treppe: idle_brightness=%d\n", idle_brightness);
} }
void Treppe::set_active_pwm(uint16_t _active_brightness) void Treppe::set_active_pwm(uint16_t _active_brightness)
{ {
active_brightness = _active_brightness; active_brightness = _active_brightness;
berechne_dimmer(); berechne_dimmer();
Serial.printf("Treppe: active_brightness=%d\n", active_brightness); Serial.printf("Treppe: active_brightness=%d\n", active_brightness);
} }
void Treppe::set_time_per_stair(uint16_t _time_per_stair) void Treppe::set_time_per_stair(uint16_t _time_per_stair)
{ {
time_per_stair = _time_per_stair; time_per_stair = _time_per_stair;
berechne_dimmer(); berechne_dimmer();
Serial.printf("Treppe: time_per_stair=%d\n", time_per_stair); Serial.printf("Treppe: time_per_stair=%d\n", time_per_stair);
} }

View File

@ -3,6 +3,10 @@
#include "FSMTreppe2/FSMTreppe2.h" #include "FSMTreppe2/FSMTreppe2.h"
#include "PCA9685.h" #include "PCA9685.h"
// #define LDRDEBUG // comment in to override LDR measurement
#define LDR_HYS 5.0 // Hysteresis for switching off FSM [lux]
#define SENSOR_OBEN 2 #define SENSOR_OBEN 2
#define SENSOR_UNTEN 12 #define SENSOR_UNTEN 12
#define OE 14 #define OE 14
@ -16,6 +20,8 @@ private:
uint16_t idle_brightness = 0; uint16_t idle_brightness = 0;
uint16_t active_brightness = 500; uint16_t active_brightness = 500;
uint16_t ldr_schwelle = 7; // activation value for FSM [lx]
uint16_t start_pwm = 0; uint16_t start_pwm = 0;
uint16_t ziel_pwm = 0; uint16_t ziel_pwm = 0;
@ -56,10 +62,9 @@ private:
DR_AUFDIMMEN=1 DR_AUFDIMMEN=1
}; };
bool read_sensor(int sensor) { bool read_sensor(int sensor);
int pegel = digitalRead(sensor); float read_ldr();
return static_cast<bool>(pegel); bool check_ldr();
}
public: public:
Treppe(uint8_t _stufen) : stufen(_stufen){ Treppe(uint8_t _stufen) : stufen(_stufen){
FSMTreppe_Obj.initialize(); FSMTreppe_Obj.initialize();