untested wemos d1 mini firmware
This commit is contained in:
commit
941e64d263
|
@ -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 <Homie.h>
|
||||
#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 && brightness<set_brightness)) { //if brightness not reached
|
||||
brightness += brightness_change_per_loop;
|
||||
}
|
||||
if ( (temperature_change_per_loop<0 && temperature>set_temperature) || (temperature_change_per_loop>0 && temperature<set_temperature)) { //if temperature not reached
|
||||
temperature += temperature_change_per_loop;
|
||||
}
|
||||
|
||||
//calculate and update pwm
|
||||
if (brightness != set_brightness || temperature != set_temperature || flag_updatePWM) { //if target not reached
|
||||
flag_updatePWM=false; // reset flag
|
||||
//calculate pwm values
|
||||
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) {
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue