copied brightness relevant code from tischlicht
This commit is contained in:
parent
4046b16f89
commit
b001ba10b3
|
@ -0,0 +1,354 @@
|
||||||
|
/*
|
||||||
|
* Wemos d1 mini
|
||||||
|
* Flash Size: 4M (1M SPIFFS)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Upload config: platformio run --target uploadfs
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Homie.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define FW_NAME "kuechenlicht"
|
||||||
|
#define FW_VERSION "1.0.0"
|
||||||
|
|
||||||
|
bool enableHandler(const HomieRange& range, const String& value);
|
||||||
|
bool fadetimeHandler(const HomieRange& range, const String& value);
|
||||||
|
bool brightnessHandler(const HomieRange& range, const String& value);
|
||||||
|
void loopHandler();
|
||||||
|
|
||||||
|
//#define DEBUG //turns on continuous serial debug printing
|
||||||
|
|
||||||
|
|
||||||
|
HomieNode lightNode("light", "Light", "light"); //paramters: topic, $name, $type
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define LED_PWM D5
|
||||||
|
|
||||||
|
#define BTN_A D7
|
||||||
|
|
||||||
|
#define PWM_MAX 1023 //10 bit dac
|
||||||
|
#define PWM_FREQUENCY 1000 //default: 1000 Hz
|
||||||
|
|
||||||
|
boolean enable=false;
|
||||||
|
float enable_fadevalue=0; //0=off, 1=on
|
||||||
|
float enable_fadevalue_change_per_loop=0.01; //fixed value. For manual calculatoin: enable_fadevalue_change_per_loop=_difference/fadetime*UPDATETIME;
|
||||||
|
|
||||||
|
float set_brightness=2; //0 to 1
|
||||||
|
#define BRIGHTNESS_MIN 0.0
|
||||||
|
#define BRIGHTNESS_MAX 2.0 //if temperature is in between both strips brightness of 2 means both are at full power. otherwise brightness will be clipped
|
||||||
|
#define BRIGHTNESSCURVE 1.4
|
||||||
|
float brightness=set_brightness;
|
||||||
|
float brightness_change_per_loop=0; //will be calculated by Handler
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t fadetime=0; //0=instant. value is time in milliseconds
|
||||||
|
#define FADETIME_MIN 0
|
||||||
|
#define FADETIME_MAX 60000
|
||||||
|
|
||||||
|
long last_updatetime=0;
|
||||||
|
#define UPDATETIME 10 //after how many ms pwm values will be updated
|
||||||
|
|
||||||
|
//Button stuff
|
||||||
|
#define BUTTONUPDATETIME 20
|
||||||
|
long last_buttonupdatetime=0;
|
||||||
|
uint8_t btnAstate=0; //for button state machine
|
||||||
|
long btnAtime=0;
|
||||||
|
#define BTNHOLDTIME 1000
|
||||||
|
|
||||||
|
boolean holdDirection_brightness=false;
|
||||||
|
|
||||||
|
#define HOLDBRIGHTNESSCHANGE_PER_LOOP 0.01 //depends on BUTTONUPDATETIME. BUTTONUPDATETIME/1000/HOLDBRIGHTNESSCHANGE_PER_LOOP=seconds to change a full cycle(0 to 1)
|
||||||
|
|
||||||
|
boolean flag_updatePWM=false; //if manually set brightness or temperature, set this flag
|
||||||
|
|
||||||
|
//Debug
|
||||||
|
long last_debugupdatetime=0;
|
||||||
|
#define DEBUGUPDATETIME 500
|
||||||
|
|
||||||
|
//To check if values changed (for mqtt response)
|
||||||
|
boolean known_enable=!enable; //start with differend known values, actual values will be send first
|
||||||
|
float known_set_brightness=set_brightness+1;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println("Hello");
|
||||||
|
pinMode(LED_PWM, OUTPUT);
|
||||||
|
analogWriteFreq(PWM_FREQUENCY);
|
||||||
|
analogWrite(LED_PWM, PWM_MAX); //high = off
|
||||||
|
|
||||||
|
pinMode(BTN_A, INPUT);
|
||||||
|
|
||||||
|
Homie_setFirmware(FW_NAME, FW_VERSION);
|
||||||
|
Homie_setBrand(FW_NAME);
|
||||||
|
Homie.setLoopFunction(loopHandler);
|
||||||
|
|
||||||
|
lightNode.advertise("brightness").settable(brightnessHandler);
|
||||||
|
lightNode.advertise("fadetime").settable(fadetimeHandler);
|
||||||
|
lightNode.advertise("enable").settable(enableHandler);
|
||||||
|
|
||||||
|
|
||||||
|
Homie.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Homie.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loopHandler() {
|
||||||
|
long loopmillis=millis();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (loopmillis >= last_buttonupdatetime+BUTTONUPDATETIME ) {
|
||||||
|
last_buttonupdatetime = loopmillis;
|
||||||
|
|
||||||
|
|
||||||
|
// #### Button A ####
|
||||||
|
boolean flag_btnApress=false; //short press on release
|
||||||
|
boolean flag_btnAholdstart=false; //long press on start
|
||||||
|
boolean flag_btnAhold=false; //long press after long press time
|
||||||
|
boolean flag_btnAholdrelease=false; //long press on release
|
||||||
|
|
||||||
|
if (digitalRead(BTN_A)) { //Button State Machine
|
||||||
|
switch (btnAstate) {
|
||||||
|
case 0: //was not pressed
|
||||||
|
btnAstate=1;
|
||||||
|
btnAtime=loopmillis; //start timer
|
||||||
|
break;
|
||||||
|
case 1: //was pressed last time checked
|
||||||
|
if (loopmillis>btnAtime+BTNHOLDTIME) {
|
||||||
|
btnAstate=2;
|
||||||
|
flag_btnAholdstart=true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: //button hold time reached
|
||||||
|
flag_btnAhold=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if (btnAstate==1) { //short press
|
||||||
|
btnAstate=0; //reset state
|
||||||
|
flag_btnApress=true;
|
||||||
|
}else if(btnAstate==2) { //long press released
|
||||||
|
flag_btnAholdrelease=true;
|
||||||
|
btnAstate=0; //reset state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #### END Button A Check ####
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Button handling
|
||||||
|
if (flag_btnApress){ //short press button
|
||||||
|
enable = !enable; //switch on/off
|
||||||
|
flag_updatePWM=true; //update pwm values
|
||||||
|
}
|
||||||
|
if (!enable && flag_btnAholdstart ) { //in not enabled and brightness button held down
|
||||||
|
enable=true; //enable light
|
||||||
|
set_brightness=0; //reset brightness
|
||||||
|
brightness=set_brightness; //immediately
|
||||||
|
holdDirection_brightness=true; //increase brightness
|
||||||
|
} else if (enable) { //only change values if enabled
|
||||||
|
// Button A Longpress Handling
|
||||||
|
if (flag_btnAholdstart) {
|
||||||
|
/* //Change only hold direction at extremes
|
||||||
|
if (set_brightness>=BRIGHTNESS_MAX) { //if hold started with brightness at one extreme
|
||||||
|
holdDirection_brightness=false; //direction decrease
|
||||||
|
}
|
||||||
|
if (set_brightness<=BRIGHTNESS_MIN) { //if hold started with brightness at one extreme
|
||||||
|
holdDirection_brightness=true; //direction increase
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
holdDirection_brightness=!holdDirection_brightness; //change direction everytime
|
||||||
|
|
||||||
|
}
|
||||||
|
if (flag_btnAhold) { //brightness
|
||||||
|
if (holdDirection_brightness) {
|
||||||
|
set_brightness += HOLDBRIGHTNESSCHANGE_PER_LOOP;
|
||||||
|
}else{
|
||||||
|
set_brightness -= HOLDBRIGHTNESSCHANGE_PER_LOOP;
|
||||||
|
}
|
||||||
|
set_brightness = constrain(set_brightness, BRIGHTNESS_MIN, BRIGHTNESS_MAX);
|
||||||
|
|
||||||
|
brightness=set_brightness; //change immediately
|
||||||
|
flag_updatePWM=true; //update pwm values
|
||||||
|
}
|
||||||
|
if (flag_btnAholdrelease) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loopmillis >= last_updatetime+UPDATETIME ) {
|
||||||
|
last_updatetime = loopmillis;
|
||||||
|
|
||||||
|
|
||||||
|
float old_brightness = brightness; //store last brightness
|
||||||
|
if ( (brightness_change_per_loop<0 && brightness>set_brightness) || (brightness_change_per_loop>0 && brightness<set_brightness)) { //if brightness not reached
|
||||||
|
brightness += brightness_change_per_loop;
|
||||||
|
if ( ( old_brightness <= set_brightness && set_brightness <= brightness ) || ( old_brightness >= set_brightness && set_brightness >= brightness ) ) { //overshot set value
|
||||||
|
brightness = set_brightness;
|
||||||
|
}
|
||||||
|
flag_updatePWM=true; //force update
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Sleep
|
||||||
|
if ( (!enable && enable_fadevalue>0) || (enable && enable_fadevalue<1) ) { //not fully turned off or on
|
||||||
|
if (!enable) { //turn off
|
||||||
|
enable_fadevalue-=enable_fadevalue_change_per_loop;
|
||||||
|
}else{ //turn on
|
||||||
|
enable_fadevalue+=enable_fadevalue_change_per_loop;
|
||||||
|
}
|
||||||
|
if (enable_fadevalue>1) { enable_fadevalue=1; } //limit
|
||||||
|
if (enable_fadevalue<0) { enable_fadevalue=0; } //limit
|
||||||
|
flag_updatePWM=true; //force update
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate and update pwm
|
||||||
|
if (brightness != set_brightness || flag_updatePWM) { //if target not reached
|
||||||
|
flag_updatePWM=false; // reset flag
|
||||||
|
//calculate pwm values
|
||||||
|
uint16_t pwm;
|
||||||
|
pwm=pow((brightness*enable_fadevalue)/2.0, BRIGHTNESSCURVE) *2.0 *PWM_MAX; //calculate brightness for led stripe, scale to 0-1, ^2, rescale to 0-2, scale for pwm
|
||||||
|
|
||||||
|
|
||||||
|
if (pwm>PWM_MAX) { pwm=PWM_MAX; } //limit
|
||||||
|
|
||||||
|
analogWrite(LED_PWM, PWM_MAX-pwm); //full pwm is led off
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//send new values back to broker
|
||||||
|
if (known_enable!=enable) {
|
||||||
|
lightNode.setProperty("enable").send(enable ? "true" : "false");
|
||||||
|
known_enable=enable;
|
||||||
|
}
|
||||||
|
if (known_set_brightness!=set_brightness) {
|
||||||
|
lightNode.setProperty("brightness").send(String(set_brightness));
|
||||||
|
known_set_brightness=set_brightness;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (loopmillis >= last_debugupdatetime+DEBUGUPDATETIME ) {
|
||||||
|
last_debugupdatetime = loopmillis;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!enable) { Serial.print("not enable. "); }
|
||||||
|
Serial.print("bright=");
|
||||||
|
Serial.print(brightness);
|
||||||
|
Serial.print(" set=");
|
||||||
|
Serial.print(set_brightness);
|
||||||
|
Serial.print("| temp=");
|
||||||
|
Serial.print(temperature);
|
||||||
|
Serial.print(" set=");
|
||||||
|
Serial.print(set_temperature);
|
||||||
|
Serial.print(" change=");
|
||||||
|
Serial.print(brightness_change_per_loop);
|
||||||
|
Serial.print(" enable_fadevalue=");
|
||||||
|
Serial.println(enable_fadevalue);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t pwmCW;
|
||||||
|
uint16_t pwmWW;
|
||||||
|
float temp=mapFloat(temperature, TEMPERATURE_MIN, TEMPERATURE_MAX, 0.0,1.0); //0=warmwhite, 1=coldwhite
|
||||||
|
pwmCW=pow((brightness*enable_fadevalue)*temp/2.0, 2) *2.0 *PWM_MAX; //calculate brightness for led stripe, scale to 0-1, ^2, rescale to 0-2, scale for pwm
|
||||||
|
pwmWW=pow((brightness*enable_fadevalue)*(1-temp)/2.0, 2) *2.0 *PWM_MAX;
|
||||||
|
|
||||||
|
if (pwmCW>PWM_MAX) { pwmCW=PWM_MAX; } //limit
|
||||||
|
if (pwmWW>PWM_MAX) { pwmWW=PWM_MAX; } //limit
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
Serial.print("bright=");
|
||||||
|
Serial.print(brightness);
|
||||||
|
Serial.print(PWM_MAX-pwmWW);
|
||||||
|
Serial.print(", ");
|
||||||
|
Serial.println(PWM_MAX-pwmCW);
|
||||||
|
}else{
|
||||||
|
Serial.print("off");
|
||||||
|
Serial.print(", ");
|
||||||
|
Serial.println("off");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool brightnessHandler(const HomieRange& range, const String& value) {
|
||||||
|
if (range.isRange) {
|
||||||
|
return false; //if range is given but index is not in allowed range
|
||||||
|
}
|
||||||
|
Homie.getLogger() << "brightness " << ": " << value << endl;
|
||||||
|
//lightNode.setProperty("brightness").send(value); //done in main loop
|
||||||
|
if (value.toFloat() >= BRIGHTNESS_MIN && value.toFloat() <= BRIGHTNESS_MAX) {
|
||||||
|
set_brightness=value.toFloat();
|
||||||
|
}else {
|
||||||
|
Homie.getLogger() << "Value outside range" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float _difference=set_brightness-brightness;
|
||||||
|
if (fadetime>0) {
|
||||||
|
brightness_change_per_loop = _difference/fadetime*UPDATETIME;
|
||||||
|
} else { //special case for instant change
|
||||||
|
brightness_change_per_loop = _difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fadetimeHandler(const HomieRange& range, const String& value) { //fadetime for temperature and brightness in milliseconds
|
||||||
|
if (range.isRange) {
|
||||||
|
return false; //if range is given but index is not in allowed range
|
||||||
|
}
|
||||||
|
Homie.getLogger() << "fadetime " << ": " << value << endl;
|
||||||
|
lightNode.setProperty("fadetime").send(value);
|
||||||
|
|
||||||
|
if (value.toInt() >= FADETIME_MIN && value.toInt() <= FADETIME_MAX) {
|
||||||
|
fadetime=value.toInt();
|
||||||
|
}else {
|
||||||
|
Homie.getLogger() << "Value outside range" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enableHandler(const HomieRange& range, const String& value) { //change on off
|
||||||
|
if (range.isRange) {
|
||||||
|
return false; //if range is given but index is not in allowed range
|
||||||
|
}
|
||||||
|
Homie.getLogger() << "enable " << ": " << value << endl;
|
||||||
|
//lightNode.setProperty("enable").send(value); //done in main loop
|
||||||
|
|
||||||
|
if (value=="false") {
|
||||||
|
enable=false;
|
||||||
|
} else if(value=="true") {
|
||||||
|
enable=true;
|
||||||
|
} else {
|
||||||
|
Homie.getLogger() << "Value outside range" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag_updatePWM=true; //force update
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float mapFloat(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue