Merge pull request #1675 from Aircoookie/blazoncek-dev

Dynamic bus configuration and pin management
This commit is contained in:
Aircoookie 2021-01-19 18:46:51 +01:00 committed by GitHub
commit 94471c0d1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 626 additions and 250 deletions

View File

@ -5,11 +5,13 @@
#include <DallasTemperature.h> //DS18B20
//Pin defaults for QuinLed Dig-Uno
#ifndef TEMPERATURE_PIN
#ifdef ARDUINO_ARCH_ESP32
#define TEMPERATURE_PIN 18
#else //ESP8266 boards
#define TEMPERATURE_PIN 14
#endif
#endif
// the frequency to check temperature, 1 minute
#ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL
@ -58,6 +60,7 @@ class UsermodTemperature : public Usermod {
}
void getTemperature() {
if (strip.isUpdating()) return;
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
temperature = sensor.getTempC(sensorDeviceAddress);
#else
@ -80,18 +83,21 @@ class UsermodTemperature : public Usermod {
disabled = !sensor.getAddress(sensorDeviceAddress, 0);
if (!disabled) {
DEBUG_PRINTLN("Dallas Temperature found");
DEBUG_PRINTLN(F("Dallas Temperature found"));
// set the resolution for this specific device
sensor.setResolution(sensorDeviceAddress, 9, true);
// do not block waiting for reading
sensor.setWaitForConversion(false);
sensor.setWaitForConversion(false);
// allocate pin & prevent other use
if (!pinManager.allocatePin(TEMPERATURE_PIN,false))
disabled = true;
} else {
DEBUG_PRINTLN("Dallas Temperature not found");
DEBUG_PRINTLN(F("Dallas Temperature not found"));
}
}
void loop() {
if (disabled) {
if (disabled || strip.isUpdating()) {
return;
}
@ -125,7 +131,7 @@ class UsermodTemperature : public Usermod {
// dont publish super low temperature as the graph will get messed up
// the DallasTemperature library returns -127C or -196.6F when problem
// reading the sensor
strcat(subuf, "/temperature");
strcat_P(subuf, PSTR("/temperature"));
mqtt->publish(subuf, 0, true, String(temperature).c_str());
} else {
// publish something else to indicate status?
@ -140,33 +146,59 @@ class UsermodTemperature : public Usermod {
return;
}
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonObject user = root[F("u")];
if (user.isNull()) user = root.createNestedObject(F("u"));
JsonArray temp = user.createNestedArray("Temperature");
JsonArray temp = user.createNestedArray(F("Temperature"));
if (!getTemperatureComplete) {
// if we haven't read the sensor yet, let the user know
// that we are still waiting for the first measurement
temp.add((USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - millis()) / 1000);
temp.add(" sec until read");
temp.add(F(" sec until read"));
return;
}
if (temperature <= -100) {
temp.add(0);
temp.add(" Sensor Error!");
temp.add(F(" Sensor Error!"));
return;
}
temp.add(temperature);
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
temp.add("°C");
temp.add(F("°C"));
#else
temp.add("°F");
temp.add(F("°F"));
#endif
}
/**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
* Add "pin_Temperature" to json state. This can be used to check which GPIO pin usermod uses.
*/
void addToJsonState(JsonObject &root)
{
root[F("pin_Temperature")] = TEMPERATURE_PIN;
}
/**
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
* Read "pin_Temperature" from json state and and change GPIO pin used.
*/
void readFromJsonState(JsonObject &root)
{
/*
if (root[F("pin_Temperature")] != nullptr)
{
if (pinManager.allocatePin((int)root[F("pin_Temperature")],false))
temperaturePin = (int)root["PIRenabled"];
}
*/
}
uint16_t getId()
{
return USERMOD_ID_TEMPERATURE;

View File

@ -29,36 +29,6 @@
#ifndef WS2812FX_h
#define WS2812FX_h
//TEMPORARY DEFINES FOR TESTING - MAKE THESE RUNTIME CONFIGURABLE TOO!
#ifndef LEDPIN
#define LEDPIN 2
#endif
#ifndef BTNPIN
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#endif
#ifndef TOUCHPIN
//#define TOUCHPIN T0 //touch pin. Behaves the same as button. ESP32 only.
#endif
#ifndef IRPIN
#define IRPIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#endif
#ifndef RLYPIN
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
#endif
#ifndef AUXPIN
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
#endif
#ifndef RLYMDE
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
#endif
//END OF TEMP DEFINES
#ifdef ESP32_MULTISTRIP
#include "../usermods/esp32_multistrip/NpbWrapper.h"
#else
@ -661,6 +631,8 @@ class WS2812FX {
paletteFade = 0,
paletteBlend = 0,
milliampsPerLed = 55,
// getStripType(uint8_t strip=0),
// setStripType(uint8_t type, uint8_t strip=0),
getBrightness(void),
getMode(void),
getSpeed(void),
@ -675,11 +647,17 @@ class WS2812FX {
get_random_wheel_index(uint8_t);
int8_t
// setStripPin(uint8_t strip, int8_t pin),
// getStripPin(uint8_t strip=0),
// setStripPinClk(uint8_t strip, int8_t pin),
// getStripPinClk(uint8_t strip=0),
tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec);
uint16_t
ablMilliampsMax,
currentMilliamps,
// setStripLen(uint8_t strip, uint16_t len),
// getStripLen(uint8_t strip=0),
triwave16(uint16_t);
uint32_t

View File

@ -17,9 +17,7 @@ void shortPressAction()
bool isButtonPressed()
{
#if defined(BTNPIN) && BTNPIN > -1
if (digitalRead(BTNPIN) == LOW) return true;
#endif
if (btnPin>=0 && digitalRead(btnPin) == LOW) return true;
#ifdef TOUCHPIN
if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true;
#endif
@ -29,8 +27,7 @@ bool isButtonPressed()
void handleButton()
{
#if (defined(BTNPIN) && BTNPIN > -1) || defined(TOUCHPIN)
if (!buttonEnabled) return;
if (btnPin<0 || !buttonEnabled) return;
if (isButtonPressed()) //pressed
{
@ -75,7 +72,6 @@ void handleButton()
buttonWaitTime = 0;
shortPressAction();
}
#endif
}
void handleIO()
@ -88,37 +84,43 @@ void handleIO()
lastOnTime = millis();
if (offMode)
{
#if RLYPIN >= 0
digitalWrite(RLYPIN, RLYMDE);
#endif
if (rlyPin>=0) {
pinMode(rlyPin, OUTPUT);
digitalWrite(rlyPin, rlyMde);
}
offMode = false;
}
} else if (millis() - lastOnTime > 600)
{
if (!offMode) {
#if LEDPIN == LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
if (!offMode) {
#ifdef ESP8266
for (uint8_t s=0; s<strip.numStrips; s++) {
if (strip.getStripPin(s)==LED_BUILTIN) {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
break;
}
}
#endif
#if RLYPIN >= 0
digitalWrite(RLYPIN, !RLYMDE);
#endif
}
if (rlyPin>=0) {
pinMode(rlyPin, OUTPUT);
digitalWrite(rlyPin, !rlyMde);
}
}
offMode = true;
}
#if AUXPIN >= 0
//output
if (auxActive || auxActiveBefore)
if (auxPin>=1 && (auxActive || auxActiveBefore))
{
if (!auxActiveBefore)
{
auxActiveBefore = true;
switch (auxTriggeredState)
{
case 0: pinMode(AUXPIN, INPUT); break;
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
case 0: pinMode(auxPin, INPUT); break;
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
}
auxStartTime = millis();
}
@ -128,11 +130,10 @@ void handleIO()
auxActiveBefore = false;
switch (auxDefaultState)
{
case 0: pinMode(AUXPIN, INPUT); break;
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
case 0: pinMode(auxPin, INPUT); break;
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
}
}
}
#endif
}

View File

@ -89,31 +89,59 @@ void deserializeConfig() {
JsonObject hw = doc[F("hw")];
// initialize LED pins and lengths prior to other HW
JsonObject hw_led = hw[F("led")];
CJSON(ledCount, hw_led[F("total")]);
if (ledCount > MAX_LEDS) ledCount = MAX_LEDS;
// CJSON(ledCount, hw_led[F("total")]);
ledCount = 0;
CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]);
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]);
CJSON(strip.reverseMode, hw_led[F("rev")]);
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
JsonObject hw_led_ins_0 = hw_led[F("ins")][0];
//bool hw_led_ins_0_en = hw_led_ins_0[F("en")]; // true
//int hw_led_ins_0_start = hw_led_ins_0[F("start")]; // 0
//int hw_led_ins_0_len = hw_led_ins_0[F("len")]; // 1200
//int hw_led_ins_0_pin_0 = hw_led_ins_0[F("pin")][0]; // 2
strip.setColorOrder(hw_led_ins_0[F("order")]);
//bool hw_led_ins_0_rev = hw_led_ins_0[F("rev")]; // false
skipFirstLed = hw_led_ins_0[F("skip")]; // 0
useRGBW = (hw_led_ins_0[F("type")] == TYPE_SK6812_RGBW);
JsonVariant strVar = hw_led["ins"];
if (strVar.is<JsonObject>()) {
// some safety measures here?
} else {
JsonArray elms = strVar.as<JsonArray>();
uint8_t s=0;
for ( JsonObject elm : elms ) {
if (s>=WLED_MAX_BUSSES) break;
int8_t pins[2] = {-1,-1};
pins[0] = elm[F("pin")][0];
if (pins[0] >= 0 && pinManager.allocatePin(pins[0])) {
if (elm[F("pin")].size()==2) {
pins[1] = elm[F("pin")][1];
if (pins[1] >= 0)
if (!pinManager.allocatePin(pins[1])) {
pinManager.deallocatePin(pins[0]);
break; // pin not ok
}
}
} else {
break; // pin not ok
}
uint16_t length = elm[F("len")]);
if (length==0) break;
uint8_t colorOrder = (int)elm[F("order")];
uint8_t skipFirstLed = elm[F("skip")]; // 0
uint8_t ledType = elm[F("type")];
uint8_t useRGBW = ((ledType == TYPE_SK6812_RGBW) || ledType == TYPE_TM1814);
ledCount += length;
busses->add(ledType? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, ledCount, colorOrder);
}
}
if (ledCount > MAX_LEDS) ledCount = MAX_LEDS;
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
buttonEnabled = hw_btn_ins_0[F("en")] | buttonEnabled;
//int hw_btn_ins_0_pin_0 = hw_btn_ins_0[F("pin")][0]; // 0
CJSON(buttonEnabled, hw_btn_ins_0[F("type")]);
int hw_btn_pin = hw_btn_ins_0[F("pin")][0];
if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP);
} else {
btnPin = -1;
}
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
CJSON(macroButton, hw_btn_ins_0_macros[0]);
@ -122,11 +150,24 @@ void deserializeConfig() {
//int hw_btn_ins_0_type = hw_btn_ins_0[F("type")]; // 0
//int hw_ir_pin = hw[F("ir")][F("pin")]; // 4
CJSON(irEnabled, hw[F("ir")][F("type")]); // 0
#ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = hw[F("ir")][F("pin")]; // 4
if (pinManager.allocatePin(hw_ir_pin,false)) {
irPin = hw_ir_pin;
} else {
irPin = -1;
}
#endif
CJSON(irEnabled, hw[F("ir")][F("type")]);
//int hw_relay_pin = hw[F("relay")][F("pin")]; // 12
//bool hw_relay_rev = hw[F("relay")][F("rev")]; // false
int hw_relay_pin = hw[F("relay")][F("pin")];
if (pinManager.allocatePin(hw_relay_pin,true)) {
rlyPin = hw_relay_pin;
pinMode(rlyPin, OUTPUT);
} else {
rlyPin = -1;
}
CJSON(rlyMde, hw[F("relay")][F("rev")]);
//int hw_status_pin = hw[F("status")][F("pin")]; // -1
@ -404,70 +445,57 @@ void serializeConfig() {
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
JsonObject hw_led_ins_0 = hw_led_ins.createNestedObject();
hw_led_ins_0[F("en")] = true;
hw_led_ins_0[F("start")] = 0;
hw_led_ins_0[F("len")] = ledCount;
JsonArray hw_led_ins_0_pin = hw_led_ins_0.createNestedArray("pin");
hw_led_ins_0_pin.add(LEDPIN);
#ifdef DATAPIN
hw_led_ins_0_pin.add(DATAPIN);
#endif
hw_led_ins_0[F("order")] = strip.getColorOrder();
hw_led_ins_0[F("rev")] = false;
hw_led_ins_0[F("skip")] = skipFirstLed ? 1 : 0;
//this is very crude and temporary
byte ledType = TYPE_WS2812_RGB;
if (useRGBW) ledType = TYPE_SK6812_RGBW;
#ifdef USE_WS2801
ledType = TYPE_WS2801;
#endif
#ifdef USE_APA102
ledType = TYPE_APA102;
#endif
#ifdef USE_LPD8806
ledType = TYPE_LPD8806;
#endif
#ifdef USE_P9813
ledType = TYPE_P9813;
#endif
#ifdef USE_TM1814
ledType = TYPE_TM1814;
#endif
hw_led_ins_0[F("type")] = ledType;
uint16_t start = 0;
for (uint8_t s=0; s<busses->getNumBusses(); s++) {
Bus *bus = busses->getBus(s);
if (!bus || bus->getLength()==0) break;
JsonObject hw_led_ins_0 = hw_led_ins.createNestedObject();
hw_led_ins_0[F("en")] = true;
hw_led_ins_0[F("start")] = start;
start += bus->getLength();
hw_led_ins_0[F("len")] = bus->getLength();
JsonArray hw_led_ins_0_pin = hw_led_ins_0.createNestedArray("pin");
hw_led_ins_0_pin.add(bus->getBusPins(s)[0]);
if (bus->getBusPins(s)[1]>=0) hw_led_ins_0_pin.add(bus->getBusPins(s)[1]);
hw_led_ins_0[F("order")] = bus->getColorOrder();
hw_led_ins_0[F("rev")] = false;
hw_led_ins_0[F("skip")] = skipFirstLed ? 1 : 0;
hw_led_ins_0[F("type")] = bus->getType();
}
JsonObject hw_btn = hw.createNestedObject("btn");
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
#if defined(BTNPIN) && BTNPIN > -1
// button BTNPIN
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
hw_btn_ins_0[F("type")] = (buttonEnabled) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
hw_btn_ins_0_pin.add(BTNPIN);
hw_btn_ins_0_pin.add(btnPin);
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
hw_btn_ins_0_macros.add(macroButton);
hw_btn_ins_0_macros.add(macroLongPress);
hw_btn_ins_0_macros.add(macroDoublePress);
#ifndef WLED_DISABLE_INFRARED
if (irPin>=0) {
JsonObject hw_ir = hw.createNestedObject("ir");
hw_ir[F("pin")] = irPin;
hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled )
}
#endif
#if defined(IRPIN) && IRPIN > -1
JsonObject hw_ir = hw.createNestedObject("ir");
hw_ir[F("pin")] = IRPIN;
hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled )
#endif
#if defined(RLYPIN) && RLYPIN > -1
JsonObject hw_relay = hw.createNestedObject("relay");
hw_relay[F("pin")] = RLYPIN;
hw_relay[F("rev")] = (RLYMDE) ? false : true;
JsonObject hw_status = hw.createNestedObject("status");
hw_status[F("pin")] = -1;
#endif
hw_relay[F("pin")] = rlyPin;
hw_relay[F("rev")] = rlyMde;
//JsonObject hw_status = hw.createNestedObject("status");
//hw_status[F("pin")] = -1;
JsonObject hw_aux = hw.createNestedObject("aux");
hw_aux[F("pin")] = auxPin;
JsonObject light = doc.createNestedObject("light");
light[F("scale-bri")] = briMultiplier;

View File

@ -52,13 +52,53 @@
myC[i].style.display = (d.getElementById('rgbw').checked) ? 'inline':'none';
}
d.getElementById('ledwarning').style.display = (d.Sf.LC.value > 1000) ? 'inline':'none';
d.getElementById('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none';
if (d.Sf.LA.value == 255) laprev = 12;
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
if (d.Sf.LA.value == 255) laprev = 12;
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
var s = d.getElementsByTagName("select");
for (i=0; i<s.length; i++) {
if (s[i].name.substring(0,5)=="LTsel") {
n=s[i].name.substring(5);
d.getElementsByName("EW"+n)[0].checked = (parseInt(s[i].value)==30||parseInt(s[i].value)==54); // TYPE_xxxx values from const.h
var LK = d.getElementsByName("LK"+n)[0];
var o = d.getElementsByName("iLK");
n=(n==""?0:parseInt(n,10));
if (s[i].value>49 && s[i].value!=54) // TYPE_xxxx values from const.h
{
o[n].style = "display:inline;";
LK.required = true;
} else {
o[n].style = "display:none;";
LK.required = false;
LK.value="";
}
}
}
var LCs = d.getElementsByTagName("input");
var sLC = 0;
for (i=0; i<LCs.length; i++) {
var nm = LCs[i].name.substring(0,2);
if (nm=="LC") {sLC+=parseInt(LCs[i].value,10);continue;}
if (nm=="LP") {var lc=d.getElementsByName("LC"+LCs[i].name.substring(2))[0]; if(LCs[i].value==3) lc.max=500; else lc.max=1500;}
if (nm=="LP" || nm=="LK" || nm=="RL" || nm=="BT" || nm=="IR" || nm=="AX")
if (LCs[i].value!="" && LCs[i].value!="-1") {
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert("Usermod pin clash!");LCs[i].value="";LCs[i].focus();continue;}
for (j=0; j<LCs.length; j++)
{
if (i==j) continue;
var n2 = LCs[j].name.substring(0,2);
if (n2=="LP" || n2=="LK" || n2=="RL" || n2=="BT" || n2=="IR" || n2=="AX")
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {alert("Pin clash!");LCs[i].value="";LCs[i].focus();break;}
}
}
}
d.getElementById('ledwarning').style.display = (sLC > 1000) ? 'inline':'none';
//var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
var val = Math.ceil((100 + sLC * laprev)/500)/2;
val = (val > 5) ? Math.ceil(val) : val;
var s = "";
var is12V = (d.Sf.LAsel.value == 30);
@ -79,11 +119,91 @@
s2 += "A is enough)<br>";
d.getElementById('psu').innerHTML = s;
d.getElementById('psu2').innerHTML = isWS2815 ? "" : s2;
}
}
function addLEDs(n)
{
if (n>1) {d.maxST=n; d.getElementById("+").style="display:inline;"; return;}
var o = d.getElementsByName("iST");
var i = o.length;
if ((n==1 && i>=d.maxST) || (n==-1 && i<=1)) return;
var f = d.getElementById("mLC");
if (n==1) {
var s, t = d.createElement("div");
t.setAttribute("name","iST");
t.appendChild(d.createTextNode((i+1)+": "));
s = d.createElement("select");
s.setAttribute("name","LTsel"+i);
s.onchange = function(){UI()}
o = d.createElement("option"); o.text = "WS281x"; o.value = "22"; s.add(o);
o = d.createElement("option"); o.text = "SK6812"; o.value = "30"; s.add(o);
o = d.createElement("option"); o.text = "WS2801"; o.value = "50"; s.add(o);
o = d.createElement("option"); o.text = "APA102"; o.value = "51"; s.add(o);
o = d.createElement("option"); o.text = "LPD8806"; o.value = "52"; s.add(o);
o = d.createElement("option"); o.text = "P9813"; o.value = "53"; s.add(o);
o = d.createElement("option"); o.text = "TM1814"; o.value = "54"; s.add(o);
t.appendChild(s);
t.appendChild(d.createTextNode(" CO: "));
s = d.createElement("select");
s.setAttribute("name","CO"+i);
o = d.createElement("option"); o.text = "GRB"; o.value = "0"; s.add(o);
o = d.createElement("option"); o.text = "RGB"; o.value = "1"; s.add(o);
o = d.createElement("option"); o.text = "BRG"; o.value = "2"; s.add(o);
o = d.createElement("option"); o.text = "RBG"; o.value = "3"; s.add(o);
o = d.createElement("option"); o.text = "BGR"; o.value = "4"; s.add(o);
o = d.createElement("option"); o.text = "GBR"; o.value = "5"; s.add(o);
t.appendChild(s);
t.appendChild(d.createTextNode(" RGBW: "));
s = d.createElement("input");
s.type = "checkbox";
s.setAttribute("name","EW"+i);
t.appendChild(s);
t.appendChild(d.createElement("br"));
t.appendChild(d.createTextNode("pin:"));
var e = d.createElement("input");
e.type = "number"; e.value = ""; e.name = "LP"+i; e.min=0; e.max=40; e.required=true; e.onchange=function(){UI()};
t.appendChild(e);
var b = d.createElement("div");
b.setAttribute("name","iLK");
b.appendChild(d.createTextNode(" clk:"));
e = d.createElement("input");
e.type = "number"; e.value = ""; e.name = "LK"+i; e.min=0; e.max=40; e.onchange=function(){UI()};
if (d.getElementsByName("LTsel")[0].value>49) e.required = true;
b.appendChild(e);
t.appendChild(b);
t.appendChild(d.createTextNode(" count:"));
e = d.createElement("input");
e.type = "number"; e.value = "0"; e.name = "LC"+i; e.min=0; e.max=1000; e.required=true; e.oninput = function(){UI()};
t.appendChild(e);
t.appendChild(d.createElement("br"));
f.appendChild(t);
}
if (n==-1) {
o[--i].remove();--i;
}
var p = d.getElementById("+");
var m = d.getElementById("-");
if (i<d.maxST-1) {p.style="display:inline";} else {p.style="display:none";}
if (i>0) {m.style="display:inline";} else {m.style="display:none";}
UI();
}
function GetV()
{
//values injected by server while sending HTML
}
//values injected by server while sending HTML
}
</script>
<style>
@import url("style.css");
@ -93,12 +213,44 @@
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>LED setup</h2>
LED count: <input name="LC" type="number" min="1" max="1500" oninput="UI()" required><br>
<h2>LED &amp; HW setup</h2>
LED strips
<button type="button" id="+" onclick="addLEDs(1)" style="display:none;">+</button><button type="button" id="-" onclick="addLEDs(-1)" style="display:none;">-</button><br>
<div id="mLC">
<div name="iST">
1:
<select name="LTsel" onchange="UI()">
<option value="22">WS281x</option><!--TYPE_WS2812_RGB-->
<option value="30">SK6812</option><!--TYPE_WS2812_RGB-->
<option value="50">WS2801</option><!--TYPE_WS2801-->
<option value="51">APA102</option><!--TYPE_APA102-->
<option value="52">LPD8806</option><!--TYPE_LPD8806-->
<option value="53">P9813</option><!--TYPE_P9813-->
<option value="54">TM1814</option><!--TYPE_TM1814-->
</select>
CO:
<select name="CO">
<option value=0>GRB</option>
<option value=1>RGB</option>
<option value=2>BRG</option>
<option value=3>RBG</option>
<option value=4>BGR</option>
<option value=5>GBR</option>
</select>
RGBW: <input type="checkbox" name="EW" onchange=UI() id="rgbw"><br>
pin:<input name="LP" type="number" min="0" max="40" required onchange="UI()">
<div name="iLK" style="display:inline;">clk:<input name="LK" type="number" min="0" max="40" onchange="UI()"></div>
count:<input name="LC" type="number" min="1" max="1500" oninput="UI()" required>
</div>
</div><hr>
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()"> Active high? <input type="checkbox" name="RM"><br>
Button pin: <input type="number" min="-1" max="40" name="BT" onchange="UI()"><br>
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()"><br>
AUX pin: <input type="number" min="-1" max="40" name="AX" onchange="UI()"><hr>
<div id="ledwarning" style="color: orange; display: none;">
&#9888; You might run into stability or lag issues.<br>
Use less than 1000 LEDs per ESP for the best experience!<br>
</div>
</div>
<i>Recommended power supply for brightest white:</i><br>
<b><span id="psu">?</span></b><br>
<span id="psu2"><br></span>
@ -128,10 +280,9 @@
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
</div>
<br>
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW" onchange=UI() id="rgbw"><br>
<span class="wc">
Auto-calculate white channel from RGB:<br>
<select name=AW>
<select name="AW">
<option value=0>None</option>
<option value=1>Brighter</option>
<option value=2>Accurate</option>
@ -139,15 +290,6 @@
<option value=4>Legacy</option>
</select>
<br></span>
Color order:
<select name="CO">
<option value=0>GRB</option>
<option value=1>RGB</option>
<option value=2>BRG</option>
<option value=3>RBG</option>
<option value=4>BGR</option>
<option value=5>GBR</option>
</select>
<h3>Defaults</h3>
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br><br>
@ -180,7 +322,7 @@
<option value="3">None (not recommended)</option>
</select><br>
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
Skip first LED: <input type="checkbox" name="SL"><hr>
Skip first LED: <input type="checkbox" name="SL"><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>

File diff suppressed because one or more lines are too long

View File

@ -488,7 +488,7 @@ void initIR()
{
if (irEnabled > 0)
{
irrecv = new IRrecv(IRPIN);
irrecv = new IRrecv(irPin);
irrecv->enableIRIn();
}
}

View File

@ -75,18 +75,123 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//LED SETTINGS
if (subPage == 2)
{
int t = request->arg(F("LC")).toInt();
String LC=F("LC"), LP=F("LP"), LK=F("LK"), CO=F("CO"), LTsel=F("LTsel");
int8_t pin;
int t;
// deallocate all pins
for (uint8_t s=0; s<busses->getNumBuses(); s++) {
Bus *bus = busses->getBus(s);
pinManager.deallocatePin(bus->getPins()[0]);
pinManager.deallocatePin(bus->getPins()[1]);
}
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
#ifndef WLED_DISABLE_INFRARED
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
#endif
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin);
// remove all busses
busses->removeAll();
// initial bus
uint8_t colorOrder, type;
uint8_t ledType = request->arg(LTsel).toInt();
uint16_t length;
int8_t pins[2] = {-1,-1};
pins[0] = request->arg(LP).toInt();
if (pinManager.allocatePin(pins[0])) {
t = length = request->arg(LC).toInt();
if ( request->hasArg(LK.c_str()) ) {
pins[1] = (request->arg(LK)).length() > 0 ? request->arg(LK).toInt() : -1;
if (pinManager.allocatePin(pins[1])) {
} else {
// fallback
pins[1] = -1;
}
}
colorOrder = request->arg(CO).toInt();
type = request->arg(LTsel).toInt();
busses->add(type? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, length, colorOrder);
} else {
// fallback
}
// secondary busses
for (uint8_t i=1; i<WLED_MAX_BUSSES; i++) {
if ( request->hasArg((LP+i).c_str()) ) {
pins[0] = request->arg((LP+i).c_str()).toInt();
if (pinManager.allocatePin(pins[0])) {
if ( request->hasArg((LK+i).c_str()) ) {
pins[1] = (request->arg(LK+i)).length() > 0 ? request->arg((LK+i).c_str()).toInt() : -1;
if (pins[1]>=0) {
pinManager.allocatePin(pins[1]);
}
}
} else {
DEBUG_PRINTLN(F("Pin not ok."));
type = TYPE_NONE;
break; // pin not ok
}
type = request->arg((LTsel+i).c_str()).toInt();
} else {
DEBUG_PRINTLN("No data.");
type = TYPE_NONE;
break; // no parameter
}
if ( request->hasArg((LC+i).c_str()) && request->arg((LC+i).c_str()).toInt() > 0 ) {
t += lenght = request->arg((LC+i).c_str()).toInt();
} else {
type = TYPE_NONE;
break; // no parameter
}
colorOrder = request->arg((CO+i).c_str()).toInt();
busses->add(type? TYPE_SK6812_RGBW : TYPE_WS2812_RGB, pins, 0, length, colorOrder);
}
// what to do with these?
if (t > 0 && t <= MAX_LEDS) ledCount = t;
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
if ( pinManager.isPinAllocated(3) && ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
#endif
// upate other pins
#ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = request->arg(F("IR")).toInt();
if (pinManager.isPinOk(hw_ir_pin) && pinManager.allocatePin(hw_ir_pin,false)) {
irPin = hw_ir_pin;
} else {
irPin = -1;
}
#endif
int hw_rly_pin = request->arg(F("RL")).toInt();
if (pinManager.allocatePin(hw_rly_pin,true)) {
rlyPin = hw_rly_pin;
} else {
rlyPin = -1;
}
rlyMde = (bool)request->hasArg(F("RM"));
int hw_btn_pin = request->arg(F("BT")).toInt();
if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP);
} else {
btnPin = -1;
}
int hw_aux_pin = request->arg(F("AX")).toInt();
if (pinManager.allocatePin(hw_aux_pin,true)) {
auxPin = hw_aux_pin;
} else {
auxPin = -1;
}
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
strip.milliampsPerLed = request->arg(F("LA")).toInt();
useRGBW = request->hasArg(F("EW"));
strip.setColorOrder(request->arg(F("CO")).toInt());
strip.rgbwMode = request->arg(F("AW")).toInt();
briS = request->arg(F("CA")).toInt();
@ -328,8 +433,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
DMXFixtureMap[i] = t;
}
}
#endif
if (subPage != 6 || !doReboot) serializeConfig(); //do not save if factory reset
if (subPage == 2) doInitStrip = true;
if (subPage == 4) alexaInit();
@ -644,15 +749,15 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
if (nightlightMode > NL_MODE_SUN) nightlightMode = NL_MODE_SUN;
#if AUXPIN >= 0
//toggle general purpose output
pos = req.indexOf(F("AX="));
if (pos > 0) {
auxTime = getNumVal(&req, pos);
auxActive = true;
if (auxTime == 0) auxActive = false;
if (auxPin>=0) {
pos = req.indexOf(F("AX="));
if (pos > 0) {
auxTime = getNumVal(&req, pos);
auxActive = true;
if (auxTime == 0) auxActive = false;
}
}
#endif
pos = req.indexOf(F("TT="));
if (pos > 0) transitionDelay = getNumVal(&req, pos);

View File

@ -285,8 +285,16 @@ void WLED::setup()
updateFSInfo();
deserializeConfig();
#if STATUSLED && STATUSLED != LEDPIN
pinMode(STATUSLED, OUTPUT);
#if STATUSLED
bool lStatusLed = false;
for (uint8_t i=0; i<strip.numStrips; i++) {
if (strip.getStripPin(i)==STATUSLED) {
lStatusLed = true;
break;
}
}
if (!lStatusLed)
pinMode(STATUSLED, OUTPUT);
#endif
//DEBUG_PRINTLN(F("Load EEPROM"));
@ -299,7 +307,8 @@ void WLED::setup()
WiFi.persistent(false);
WiFi.onEvent(WiFiEvent);
Serial.println(F("Ada"));
// Serial.println(F("Ada"));
DEBUG_PRINTLN(F("Ada"));
// generate module IDs
escapedMac = WiFi.macAddress();
@ -343,12 +352,6 @@ void WLED::setup()
void WLED::beginStrip()
{
// Initialize NeoPixel Strip and button
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA)
ledCount = MAX_LEDS_DMA; // DMA method uses too much ram
#endif
#endif
if (ledCount > MAX_LEDS || ledCount == 0)
ledCount = 30;
@ -357,11 +360,6 @@ void WLED::beginStrip()
strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw);
#if defined(BTNPIN) && BTNPIN > -1
pinManager.allocatePin(BTNPIN, false);
pinMode(BTNPIN, INPUT_PULLUP);
#endif
if (bootPreset > 0) applyPreset(bootPreset);
if (turnOnAtBoot) {
if (briS > 0) bri = briS;
@ -371,24 +369,13 @@ void WLED::beginStrip()
}
colorUpdated(NOTIFIER_CALL_MODE_INIT);
// init relay pin
#if RLYPIN >= 0
pinManager.allocatePin(RLYPIN);
pinMode(RLYPIN, OUTPUT);
#if RLYMDE
digitalWrite(RLYPIN, bri);
#else
digitalWrite(RLYPIN, !bri);
#endif
#endif
// init relay pin
if (rlyPin>=0)
digitalWrite(rlyPin, (rlyMde ? bri : !bri));
// disable button if it is "pressed" unintentionally
#if (defined(BTNPIN) && BTNPIN > -1) || defined(TOUCHPIN)
if (isButtonPressed())
if (btnPin>=0 && isButtonPressed())
buttonEnabled = false;
#else
buttonEnabled = false;
#endif
}
void WLED::initAP(bool resetAP)
@ -419,7 +406,7 @@ void WLED::initAP(bool resetAP)
udp2Connected = notifier2Udp.begin(udpPort2);
}
e131.begin(false, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", WiFi.softAPIP());
}
@ -483,7 +470,7 @@ void WLED::initConnection()
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
char hostname[25] = "wled-";
prepareHostname(hostname);
#ifdef ESP8266
WiFi.hostname(hostname);
#endif
@ -634,7 +621,13 @@ void WLED::handleConnection()
void WLED::handleStatusLED()
{
#if STATUSLED && STATUSLED != LEDPIN
#if STATUSLED
for (uint8_t s=0; s<strip.numStrips; s++) {
if (strip.getStripPin(s)==STATUSLED) {
return; // pin used for strip
}
}
ledStatusType = WLED_CONNECTED ? 0 : 2;
if (mqttEnabled && ledStatusType != 2) // Wi-Fi takes presendence over MQTT
ledStatusType = WLED_MQTT_CONNECTED ? 0 : 4;
@ -650,7 +643,7 @@ void WLED::handleStatusLED()
#else
digitalWrite(STATUSLED, LOW);
#endif
}
#endif
}
}

View File

@ -131,7 +131,7 @@
Comment out this error message to build regardless.
#endif
#if IRPIN < 0
#if !defined(IRPIN) || IRPIN < 0
#ifndef WLED_DISABLE_INFRARED
#define WLED_DISABLE_INFRARED
#endif
@ -184,13 +184,29 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
// Hardware CONFIG (only changeble HERE, not at runtime)
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
#ifndef BTNPIN
WLED_GLOBAL int8_t btnPin _INIT(-1);
#else
WLED_GLOBAL int8_t btnPin _INIT(BTNPIN);
#endif
#ifndef RLYPIN
WLED_GLOBAL int8_t rlyPin _INIT(-1);
#else
WLED_GLOBAL int8_t rlyPin _INIT(RLYPIN);
#endif
#ifndef RLYMDE
WLED_GLOBAL bool rlyMde _INIT(1);
#else
WLED_GLOBAL bool rlyMde _INIT(RLYMDE);
#endif
#ifndef IRPIN
WLED_GLOBAL int8_t irPin _INIT(-1);
#else
WLED_GLOBAL int8_t irPin _INIT(IRPIN);
#endif
//WLED_GLOBAL byte presetToApply _INIT(0);
#if AUXPIN >= 0
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
#endif
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
@ -463,12 +479,18 @@ WLED_GLOBAL long lastInterfaceUpdate _INIT(0);
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
#if AUXPIN >= 0
// auxiliary debug pin
WLED_GLOBAL byte auxTime _INIT(0);
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
WLED_GLOBAL bool auxActive _INIT(false, auxActiveBefore _INIT(false);
// auxiliary debug pin
#ifndef AUXPIN
WLED_GLOBAL int8_t auxPin _INIT(-1);
#else
WLED_GLOBAL int8_t auxPin _INIT(AUXPIN);
#endif
WLED_GLOBAL byte auxTime _INIT(0);
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
WLED_GLOBAL bool auxActive _INIT(false);
WLED_GLOBAL bool auxActiveBefore _INIT(false);
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
// alexa udp
WLED_GLOBAL String escapedMac;
@ -533,8 +555,10 @@ WLED_GLOBAL bool doInitStrip _INIT(false);
// Usermod manager
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
WLED_GLOBAL PinManagerClass pinManager _INIT(PinManagerClass());
// Status LED
#if STATUSLED && STATUSLED != LEDPIN
#if STATUSLED
WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0);
WLED_GLOBAL unsigned short ledStatusType _INIT(0); // current status type - corresponds to number of blinks per second
WLED_GLOBAL bool ledStatusState _INIT(0); // the current LED state

View File

@ -254,7 +254,32 @@ void getSettingsJS(byte subPage, char* dest)
}
if (subPage == 2) {
oappend(SET_F("d.Sf.LC.max="));
char nS[3];
// add usermod pins as d.um_p array
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
JsonObject mods = doc.createNestedObject(F("mods"));
usermods.addToJsonState(mods);
if (!mods.isNull()) {
uint8_t i=0;
oappend(SET_F("d.um_p=["));
for (JsonPair kv : mods) {
if (strncmp_P(kv.key().c_str(),PSTR("pin_"),4) == 0) {
if (i++) oappend(SET_F(","));
oappend(itoa((int)kv.value(),nS,10));
}
}
oappend(SET_F("];"));
}
#if defined(WLED_MAX_BUSSES) && WLED_MAX_BUSSES>1
oappend(SET_F("addLEDs("));
oappend(itoa(WLED_MAX_BUSSES,nS,10));
oappend(SET_F(");"));
#endif
Bus *bus = busses->getBus(0);
oappend(SET_F("d.Sf.LC.max=")); //TODO Formula for max LEDs on ESP8266 depending on types. 500 DMA or 1500 UART (about 4kB mem usage)
#if defined(ESP8266) && LEDPIN == 3
oappendi(MAX_LEDS_DMA);
#else
@ -263,6 +288,35 @@ void getSettingsJS(byte subPage, char* dest)
oappend(";");
sappend('v',SET_F("LC"),ledCount);
//sappend('v',SET_F("LC"),ledCount);
sappend('v',SET_F("LP"),bus->getPins()[0]);
if (bus->getPins()[1]>=0) sappend('v',SET_F("LK"),bus->getPins()[1]);
sappend('v',SET_F("LC"),bus->getLength());
sappend('v',SET_F("LTsel"),bus->getType());
sappend('v',SET_F("CO"),bus->getColorOrder());
for (uint8_t s=1; s<busses->getNumBusses(); s++){
bus = busses->getBus(s);
String LP = F("LP"), LK = F("LK"), LC = F("LC"), CO = F("CO"), LTsel = F("LTsel");
LP += s; LK += s; LC += s; CO += s; LTsel += s;
oappend(SET_F("addLEDs(1);"));
sappend('v',LP.c_str(),bus->getPins()[0]);
if (bus->getPins()[1]>=0) sappend('v',LK.c_str(),bus->getPins()[1]);
sappend('v',LC.c_str(),bus->getLength());
#ifdef ESP8266
if (bus->getPins()[0]==3) {
oappend(SET_F("d.Sf."));
oappend(LC.c_str());
oappend(SET_F(".max=500;"));
} else {
oappend(SET_F("d.Sf."));
oappend(LC.c_str());
oappend(SET_F(".max=1500;"));
}
#endif
sappend('v',LTsel.c_str(),bus->getType());
sappend('v',CO.c_str(),bus->getColorOrder());
}
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed);
if (strip.currentMilliamps)
@ -293,6 +347,11 @@ void getSettingsJS(byte subPage, char* dest)
sappend('i',SET_F("PB"),strip.paletteBlend);
sappend('c',SET_F("RV"),strip.reverseMode);
sappend('c',SET_F("SL"),skipFirstLed);
sappend('v',SET_F("RL"),rlyPin);
sappend('c',SET_F("RM"),rlyMde);
sappend('v',SET_F("BT"),btnPin);
sappend('v',SET_F("IR"),irPin);
sappend('v',SET_F("AX"),auxPin);
}
if (subPage == 3)