esp-deckenlicht/esp-deckenlicht.ino

464 lines
12 KiB
C++

#include <Homie.h>
#include <ArduinoOTA.h>
#define PIN_LIGHT D5
#define PIN_LIGHT1 D6
#define PIN_LIGHT2 D7
#define PIN_LIGHT3 D8
#define PIN_SENSOR D0
#define FULL 255
#define LOWER 50
#define MINIMUM 1
#define OFF 0
int timeout = (1000-50);
#define FW_NAME "esp-deckenlicht"
#define FW_VERSION "1.0.1"
int w0;
int w1;
int w2;
int w3;
int w0b, w1b, w2b, w3b;
int step = 0;
int strobo = 1;
bool disco = false;
int lastEvent = 0;
//Fluorescent effect
int fluorescentSet=0;
bool fluorescentActive=false;
long fluorescentLastActivated=0;
#define FLUORESCENT_TIMEDIVIDE 10
int fluorescentTemp=0;
#define FLUORESCENTUPDATEINTERVAL 20
long fluorescentLastUpdated=0;
int fluorescentCurrentBrightness0=0; //current brightness for effect duration
int fluorescentCurrentBrightness1=0;
int fluorescentCurrentBrightness2=0;
int fluorescentCurrentBrightness3=0;
#define FLUORESCENTTEMPMAX 400
int fluorescentAge=0;
#define FLUORESCENTAGEMAX 20
bool lastSensorValue = false;
HomieNode lightNode("strip", "strip");
HomieNode sensorNode("sensor", "sensor");
Bounce debouncer = Bounce();
bool speedHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "speed " << ": " << value << endl;
timeout = value.toInt();
lightNode.setProperty("speed").send(value);
return true;
}
bool stroboToggleHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "stroboToggle " << ": " << value << endl;
lightNode.setProperty("stroboToggle").send(value);
strobo *= -1;
if (strobo == 1)
{
w0 = w1 = w2 = w3 = FULL;
}
else
{
w0 = w1 = w2 = w3 = OFF;
}
output();
}
bool beatHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "beat " << ": " << value << endl;
lightNode.setProperty("beat").send(value);
if (step >= 4) {
step = 0;
}
// Cycle each light from 255 to 50 to 1 to off
switch (step)
{
case 0:
w0 = FULL;
w1 = OFF;
w2 = MINIMUM;
w3 = LOWER;
break;
case 1:
w1 = FULL;
w2 = OFF;
w3 = MINIMUM;
w0 = LOWER;
break;
case 2:
w2 = FULL;
w3 = OFF;
w0 = MINIMUM;
w1 = LOWER;
break;
case 3:
w3 = FULL;
w0 = OFF;
w1 = MINIMUM;
w2 = LOWER;
break;
default:
w0 = w1 = w2 = w3 = 0;
break;
}
output();
step++;
}
bool discoHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "disco " << ": " << value << endl;
lightNode.setProperty("disco").send(value);
if (value.toInt() == 0)
{
disco = false;
// Return to previous state
w0 = w0b;
w1 = w1b;
w2 = w2b;
w3 = w3b;
output();
} else
{
step = 0;
w0b = w0;
w1b = w1;
w2b = w2;
w3b = w3;
disco = true;
}
return true;
}
bool fluorescentHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "fluorescent " << ": " << value << endl;
lightNode.setProperty("fluorescent").send(value);
fluorescentSet=value.toInt();
disco = false;
if (fluorescentSet==0){ // turned off
fluorescentActive=false; //set effect off
w0 = 0;
w1 = 0;
w2 = 0;
w3 = 0;
}else{ //turned on
if (w0==0 && w1==0 && w2==0 && w3==0){ //turned on and was off before
//Initialization
fluorescentActive=true; //start effect
fluorescentLastActivated=millis();
fluorescentLastUpdated=millis();
fluorescentTemp=0; //"temperature" for warmup
fluorescentCurrentBrightness0=0; //brightness for effect duration
fluorescentCurrentBrightness1=0;
fluorescentCurrentBrightness2=0;
fluorescentCurrentBrightness3=0;
}else{
fluorescentActive=false; //set effect off
w0 = w1 = w2 = w3 = fluorescentSet;
}
}
output();
return true;
}
bool fluorescentAgeHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "fluorescentAge " << ": " << value << endl;
fluorescentAge=value.toInt();
if (fluorescentAge<0){
fluorescentAge=0;
}else if(fluorescentAge>FLUORESCENTAGEMAX){
fluorescentAge=FLUORESCENTAGEMAX;
}
return true;
}
bool lightHandler(const HomieRange& range, const String& value) {
Homie.getLogger() << "light " << ": " << value << endl;
disco = false;
w0 = value.toInt();
w1 = value.toInt();
w2 = value.toInt();
w3 = value.toInt();
lightNode.setProperty("light").send(value);
output();
return true;
}
bool light0Handler(const HomieRange& range, const String& value) {
Homie.getLogger() << "light0 " << ": " << value << endl;
w0 = value.toInt();
disco = false;
lightNode.setProperty("light0").send(value);
output();
return true;
}
bool light1Handler(const HomieRange& range, const String& value) {
Homie.getLogger() << "light1 " << ": " << value << endl;
w1 = value.toInt();
disco = false;
lightNode.setProperty("light1").send(value);
output();
return true;
}
bool light2Handler(const HomieRange& range, const String& value) {
Homie.getLogger() << "light2 " << ": " << value << endl;
w2 = value.toInt();
disco = false;
lightNode.setProperty("light2").send(value);
output();
return true;
}
bool light3Handler(const HomieRange& range, const String& value) {
Homie.getLogger() << "light3 " << ": " << value << endl;
w3 = value.toInt();
disco = false;
lightNode.setProperty("light3").send(value);
output();
return true;
}
void output() {
// * 4 to scale the input up for ESP Arduino default 10 bit PWM
if (w0 == FULL)
{
analogWrite(PIN_LIGHT, 1023);
} else {
analogWrite(PIN_LIGHT, w0*4);
}
if (w1 == FULL)
{
analogWrite(PIN_LIGHT1, 1023);
} else {
analogWrite(PIN_LIGHT1, w1*4);
}
if (w2 == FULL)
{
analogWrite(PIN_LIGHT2, 1023);
} else {
analogWrite(PIN_LIGHT2, w2*4);
}
if (w3 == FULL)
{
analogWrite(PIN_LIGHT3, 1023);
} else {
analogWrite(PIN_LIGHT3, w3*4);
}
}
void loopHandler()
{
if (disco)
{
if (millis() - lastEvent >= (1000-timeout) || lastEvent == 0) {
lastEvent = millis();
if (step >= 4) {
step = 0;
}
// Cycle each light from 255 to 50 to 1 to off
switch (step)
{
case 0:
w0 = FULL;
w1 = OFF;
w2 = MINIMUM;
w3 = LOWER;
break;
case 1:
w1 = FULL;
w2 = OFF;
w3 = MINIMUM;
w0 = LOWER;
break;
case 2:
w2 = FULL;
w3 = OFF;
w0 = MINIMUM;
w1 = LOWER;
break;
case 3:
w3 = FULL;
w0 = OFF;
w1 = MINIMUM;
w2 = LOWER;
break;
default:
w0 = w1 = w2 = w3 = 0;
break;
}
output();
step++;
}
}
if (fluorescentActive){
long _time=millis()-fluorescentLastActivated; //time since activated
//mosquitto_pub -h raum.ctdo.de -t "homie/esp-deckenlicht/strip/fluorescent/set" -m "255"
if (millis() > fluorescentLastUpdated+FLUORESCENTUPDATEINTERVAL){ //Update values
fluorescentLastUpdated=millis();
/*
fluorescentTemp+=random(0, 3); //min (inclusive), max (exclusive)
fluorescentLastUpdated=millis();
if (random(0,256)<fluorescentTemp*1.0/FLUORESCENTTEMPMAX*256){ //the warmer, the more often
if (random(0,40)==0){ //ignite
fluorescentCurrentBrightness=fluorescentSet/100.0*random(50,100);
}
}
if (random(0,256)>fluorescentTemp*1.0/FLUORESCENTTEMPMAX*256){ //the colder, the more often
if (fluorescentCurrentBrightness<5){ //not on
if (random(0,50)==0){ //ignite
fluorescentCurrentBrightness=fluorescentSet/100.0*random(50,100);
}
}
if (fluorescentCurrentBrightness>20){ //minimum brightness
fluorescentCurrentBrightness-=random(20,40);
}else{
fluorescentCurrentBrightness+=random(2,3)-2;
}
}
*/
int fluorescentTempIncreaseMax=61-(fluorescentAge*3);
fluorescentTemp+=1+ random(0,fluorescentTempIncreaseMax *fluorescentTemp/FLUORESCENTTEMPMAX);
//fluorescentTemp+=3;
if (random(0,80)==0){ //ignite
fluorescentCurrentBrightness0=fluorescentSet*random(50,100)/100;
fluorescentCurrentBrightness1=fluorescentSet*random(50,100)/100;
fluorescentCurrentBrightness2=fluorescentSet*random(50,100)/100;
fluorescentCurrentBrightness3=fluorescentSet*random(50,100)/100;
}
if (fluorescentTemp>200){ // warm enough to glow
if (fluorescentCurrentBrightness0<20){ //if under glow brightness
fluorescentCurrentBrightness0+=5; //start glowing
}else if(fluorescentCurrentBrightness0>50){ //too bright to glow
fluorescentCurrentBrightness0-=random(0,30); //reduce intensity
}
if (fluorescentCurrentBrightness1<20){ //if under glow brightness
fluorescentCurrentBrightness1+=5; //start glowing
}else if(fluorescentCurrentBrightness1>50){ //too bright to glow
fluorescentCurrentBrightness1-=random(0,30); //reduce intensity
}
if (fluorescentCurrentBrightness2<20){ //if under glow brightness
fluorescentCurrentBrightness2+=5; //start glowing
}else if(fluorescentCurrentBrightness2>50){ //too bright to glow
fluorescentCurrentBrightness2-=random(0,30); //reduce intensity
}
if (fluorescentCurrentBrightness3<20){ //if under glow brightness
fluorescentCurrentBrightness3+=5; //start glowing
}else if(fluorescentCurrentBrightness3>50){ //too bright to glow
fluorescentCurrentBrightness3-=random(0,30); //reduce intensity
}
}else{ //not warm enough to glow
if (fluorescentCurrentBrightness0>0){
fluorescentCurrentBrightness0-=random(20,50); //reduce intensity
}
if (fluorescentCurrentBrightness1>0){
fluorescentCurrentBrightness1-=random(20,50); //reduce intensity
}
if (fluorescentCurrentBrightness2>0){
fluorescentCurrentBrightness2-=random(20,50); //reduce intensity
}
if (fluorescentCurrentBrightness3>0){
fluorescentCurrentBrightness3-=random(20,50); //reduce intensity
}
}
if (fluorescentTemp>=FLUORESCENTTEMPMAX){ //finished
fluorescentActive=false;
fluorescentCurrentBrightness0=fluorescentSet; //set disired value
fluorescentCurrentBrightness1=fluorescentSet; //set disired value
fluorescentCurrentBrightness2=fluorescentSet; //set disired value
fluorescentCurrentBrightness3=fluorescentSet; //set disired value
}
fluorescentCurrentBrightness0=_min(255,_max(0,fluorescentCurrentBrightness0));
fluorescentCurrentBrightness1=_min(255,_max(0,fluorescentCurrentBrightness1));
fluorescentCurrentBrightness2=_min(255,_max(0,fluorescentCurrentBrightness2));
fluorescentCurrentBrightness3=_min(255,_max(0,fluorescentCurrentBrightness3));
w0 = fluorescentCurrentBrightness0;
w1 = fluorescentCurrentBrightness1;
w2 = fluorescentCurrentBrightness2;
w3 = fluorescentCurrentBrightness3;
output();
}
}
bool sensorValue = debouncer.read();
if (Homie.isConfigured() && Homie.isConnected() && sensorValue != lastSensorValue) {
sensorNode.setProperty("motion").send(sensorValue ? "true" : "false");
lastSensorValue = sensorValue;
}
}
void setup() {
Serial.begin(115200);
Serial << endl << endl;
pinMode(PIN_LIGHT, OUTPUT);
pinMode(PIN_LIGHT1, OUTPUT);
pinMode(PIN_LIGHT2, OUTPUT);
pinMode(PIN_LIGHT3, OUTPUT);
debouncer.attach(PIN_SENSOR,INPUT);
debouncer.interval(50);
Homie_setFirmware(FW_NAME, FW_VERSION);
Homie_setBrand(FW_NAME);
Homie.setLoopFunction(loopHandler);
lightNode.advertise("speed").settable(speedHandler);
lightNode.advertise("disco").settable(discoHandler);
lightNode.advertise("beat").settable(beatHandler);
lightNode.advertise("light").settable(lightHandler);
lightNode.advertise("light0").settable(light0Handler);
lightNode.advertise("light1").settable(light1Handler);
lightNode.advertise("light2").settable(light2Handler);
lightNode.advertise("light3").settable(light3Handler);
lightNode.advertise("fluorescent").settable(fluorescentHandler);
lightNode.advertise("fluorescentage").settable(fluorescentAgeHandler);
sensorNode.advertise("motion");
// Activate other PWM frequency. 1000 (1 KHz) is default
analogWriteFreq(30000);
// Restore last state
output();
Homie.setup();
ArduinoOTA.setHostname(Homie.getConfiguration().deviceId);
ArduinoOTA.begin();
}
void loop() {
Homie.loop();
debouncer.update();
ArduinoOTA.handle();
}