From 941e64d263c7ef7a503a76731af7cf1591b45f6d Mon Sep 17 00:00:00 2001 From: Fisch Date: Thu, 10 Oct 2019 20:10:45 +0200 Subject: [PATCH] untested wemos d1 mini firmware --- controllerHomie/controllerHomie.ino | 395 ++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 controllerHomie/controllerHomie.ino diff --git a/controllerHomie/controllerHomie.ino b/controllerHomie/controllerHomie.ino new file mode 100644 index 0000000..faa524f --- /dev/null +++ b/controllerHomie/controllerHomie.ino @@ -0,0 +1,395 @@ +/* + * NodeMCU 1.0 (ESP-12E) + * Flash Size: 4M (1M SPIFFS) + * EN, RST -> VCC + * GPIO15 -> 10k -> GND + * GPIO0 -> Switch (Connect to Flash) -> GND + * + * Pinout: https://www.mikrocontroller-elektronik.de/wp-content/uploads/2017/02/ESP12E-Pinbelegung-1.png + */ + +#include +#define FW_NAME "tischlicht" +#define FW_VERSION "1.0.0" + +/* + * To Update configuration (wifi credentials) from data/homie/config.json: + * Connect to serial. On ESP-12E connect flash jumper + * Apply Power to ESP + * Optional: upload sketch + * Tools - Sketch Data Upload + * Remove jumper + * / + +//http://homieiot.github.io/homie-esp8266/docs/develop/configuration/json-configuration-file/ +//curl -X PUT http://homie.config/config -d @config.json --header "Content-Type: application/json" +/*Example data/homie/config.json +{ +"name": "pringleslight", +"device_id": "pringleslight", +"wifi": { +"ssid": "CTDO-IoT", +"password": "12345678" +}, +"mqtt": { +"host": "raum.ctdo.de", +"port": 1883, +"auth": false +}, +"ota": { +"enabled": false +} +} + */ + +HomieNode lightNode("light", "light"); + +//(pin x) nunbering CCW starting with rst + + +#define LED_CW 14 //D5 = GPIO14 (pin5) +#define LED_WW 12 //D6 = GPIO12 (pin6) + +#define BTN_A 13 //D7 = GPIO13 (pin 7) +#define BTN_B 15 //D8 = GPIO15 (pin 10) + +/* + * VCC (pin 8) + * GND (pin 9) + */ + +#define PWM_MAX 1023 //10 bit dac + +boolean sleep=true; //true turns lights off + +float set_brightness=0; //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 +float brightness=set_brightness; +float brightness_change_per_loop=100; //will be calculated by Handler + + +#define TEMPERATURE_MIN 3000 //temperature of warm white leds +#define TEMPERATURE_MAX 5000//temperature of cold white leds +float set_temperature=(TEMPERATURE_MAX+TEMPERATURE_MIN)/2; +float temperature=set_temperature; +float temperature_change_per_loop=100; //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; +uint8_t btnBstate=0; //for button state machine +long btnBtime=0; +#define BTNHOLDTIME 1000 + +boolean holdDirection_brightness=false; +boolean holdDirection_temperature=false; + +#define HOLDBRIGHTNESSCHANGE_PER_LOOP 0.01 //depends on BUTTONUPDATETIME. BUTTONUPDATETIME/1000/HOLDBRIGHTNESSCHANGE_PER_LOOP=seconds to change a full cycle(0 to 1) +#define HOLDTEMPERATURECHANGE_PER_LOOP 10.0 // (TEMPERATURE_MAX-TEMPERATURE_MIN)*BUTTONUPDATETIME/1000/HOLDBRIGHTNESSCHANGE_PER_LOOP=seconds to change a full cycle (min to max) + +boolean flag_updatePWM=false; //if manually set brightness or temperature, set this flag + +//Debug +long last_debugupdatetime=0; +#define DEBUGUPDATETIME 500 + +void setup() { + Serial.begin(115200); + Serial.println("Hello"); + pinMode(LED_WW, OUTPUT); + pinMode(LED_CW, OUTPUT); + digitalWrite(LED_CW, HIGH); //high = off + digitalWrite(LED_WW, HIGH); //high = off + + pinMode(BTN_A, INPUT); + pinMode(BTN_B, INPUT); + + Homie_setFirmware(FW_NAME, FW_VERSION); + Homie_setBrand(FW_NAME); + Homie.setLoopFunction(loopHandler); + + lightNode.advertise("brightness").settable(brightnessHandler); + lightNode.advertise("temperature").settable(temperatureHandler); + lightNode.advertise("fadetime").settable(fadetimeHandler); + + + 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 B #### + boolean flag_btnBpress=false; //short press on release + boolean flag_btnBholdstart=false; //long press on start + boolean flag_btnBhold=false; //long press after long press time + boolean flag_btnBholdrelease=false; //long press on release + + if (digitalRead(BTN_B)) { //Button State Machine + switch (btnBstate) { + case 0: //was not pressed + btnBstate=1; + btnBtime=loopmillis; //start timer + break; + case 1: //was pressed last time checked + if (loopmillis>btnBtime+BTNHOLDTIME) { + btnBstate=2; + flag_btnBholdstart=true; + } + break; + case 2: //button hold time reached + flag_btnBhold=true; + break; + } + }else { + if (btnBstate==1) { //short press + btnBstate=0; //reset state + flag_btnBpress=true; + }else if(btnBstate==2) { //long press released + flag_btnBholdrelease=true; + btnBstate=0; //reset state + } + } + // #### END Button B Check #### + + + //Button handling + if (flag_btnApress || flag_btnBpress){ //short press either button + sleep = !sleep; //switch on/off + flag_updatePWM=true; //update pwm values + } + + if (!sleep) { //only change values if not in sleep mode + // Button A Longpress Handling + if (flag_btnAholdstart) { + if (set_brightness>=BRIGHTNESS_MAX || set_brightness<=BRIGHTNESS_MIN) { //if hold started with brightness at one extreme + holdDirection_brightness=!holdDirection_brightness; //invert direction + } + } + 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) { + + } + + // Button B Longpress Handling + if (flag_btnBholdstart) { + if (set_temperature>=TEMPERATURE_MAX || set_temperature<=TEMPERATURE_MIN) { //if hold started with brightness at one extreme + holdDirection_temperature=!holdDirection_temperature; //invert direction + } + } + if (flag_btnBhold) { //brightness + if (holdDirection_temperature) { + set_temperature += HOLDTEMPERATURECHANGE_PER_LOOP; + }else{ + set_temperature -= HOLDTEMPERATURECHANGE_PER_LOOP; + } + set_temperature = constrain(set_temperature, TEMPERATURE_MIN, TEMPERATURE_MAX); + + temperature=set_temperature; //change immediately + flag_updatePWM=true; //update pwm values + } + if (flag_btnBholdrelease) { + + } + } + + } + + if (loopmillis >= last_updatetime+UPDATETIME ) { + last_updatetime = loopmillis; + + + + if ( (brightness_change_per_loop<0 && brightness>set_brightness) || (brightness_change_per_loop>0 && brightnessset_temperature) || (temperature_change_per_loop>0 && temperaturePWM_MAX) { pwmCW=PWM_MAX; } //limit + if (pwmWW>PWM_MAX) { pwmWW=PWM_MAX; } //limit + + if (!sleep) { + analogWrite(LED_WW, pwmWW); + analogWrite(LED_CW, pwmCW); + }else{ + digitalWrite(LED_WW, HIGH); //light off + digitalWrite(LED_CW, HIGH); //light off + } + } + } + + if (loopmillis >= last_debugupdatetime+DEBUGUPDATETIME ) { + last_debugupdatetime = loopmillis; + + if (sleep) { Serial.print("Sleep. "); } + /*Serial.print("bright="); + Serial.print(brightness); + Serial.print(" set="); + Serial.print(set_brightness); + Serial.print("| temp="); + Serial.print(temperature); + Serial.print(" set="); + Serial.println(set_temperature); + */ + + + uint16_t pwmCW; + uint16_t pwmWW; + float temp=mapFloat(temperature, TEMPERATURE_MIN, TEMPERATURE_MAX, 0.0,1.0); //0=warmwhite, 1=coldwhite + pwmCW=brightness*PWM_MAX*temp; + pwmWW=brightness*PWM_MAX*(1-temp); + + if (pwmCW>PWM_MAX) { pwmCW=PWM_MAX; } //limit + if (pwmWW>PWM_MAX) { pwmWW=PWM_MAX; } //limit + + if (!sleep) { + Serial.print(pwmWW); + Serial.print(", "); + Serial.println(pwmCW); + }else{ + Serial.print(0); + Serial.print(", "); + Serial.println(0); + } + + } + +} + + + +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); + 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; + brightness_change_per_loop = _difference/fadetime*UPDATETIME; + + return true; +} + +bool temperatureHandler(const HomieRange& range, const String& value) { + if (range.isRange) { + return false; //if range is given but index is not in allowed range + } + Homie.getLogger() << "temperature " << ": " << value << endl; + lightNode.setProperty("temperature").send(value); + + if (value.toFloat() >= TEMPERATURE_MIN && value.toFloat() <= TEMPERATURE_MAX) { + set_temperature=value.toFloat(); + }else { + Homie.getLogger() << "Value outside range" << endl; + return false; + } + + float _difference=set_temperature-temperature; + temperature_change_per_loop = _difference/fadetime*UPDATETIME; + + + 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; +} + +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; +}