diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index 1ce0322e..6532680b 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -4,13 +4,13 @@ #include //DS18B20 -//Pin defaults for QuinLed Dig-Uno +//Pin defaults for QuinLed Dig-Uno if not overriden #ifndef TEMPERATURE_PIN -#ifdef ARDUINO_ARCH_ESP32 -#define TEMPERATURE_PIN 18 -#else //ESP8266 boards -#define TEMPERATURE_PIN 14 -#endif + #ifdef ARDUINO_ARCH_ESP32 + #define TEMPERATURE_PIN 18 + #else //ESP8266 boards + #define TEMPERATURE_PIN 14 + #endif #endif // the frequency to check temperature, 1 minute @@ -20,19 +20,22 @@ // how many seconds after boot to take first measurement, 20 seconds #ifndef USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT -#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000 +#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000 #endif -OneWire oneWire(TEMPERATURE_PIN); -DallasTemperature sensor(&oneWire); - class UsermodTemperature : public Usermod { private: + OneWire *oneWire; + DallasTemperature *sensor; // The device's unique 64-bit serial code stored in on-board ROM. // Reading directly from the sensor device address is faster than // reading from index. When reading by index, DallasTemperature // must first look up the device address at the specified index. DeviceAddress sensorDeviceAddress; + // GPIO pin used for sensor (with a default compile-time fallback) + int8_t temperaturePin = TEMPERATURE_PIN; + // measurement unit (true==°C, false==°F) + bool degC = true; // set last reading as "40 sec before boot", so first reading is taken after 20 sec unsigned long lastMeasurement = UINT32_MAX - (USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT); // last time requestTemperatures was called @@ -51,21 +54,19 @@ class UsermodTemperature : public Usermod { bool disabled = false; void requestTemperatures() { - // there is requestTemperaturesByAddress however it - // appears to do more work, + // there is requestTemperaturesByAddress however it + // appears to do more work, // TODO: measure exection time difference - sensor.requestTemperatures(); + sensor->requestTemperatures(); lastTemperaturesRequest = millis(); waitingForConversion = true; } void getTemperature() { if (strip.isUpdating()) return; - #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS - temperature = sensor.getTempC(sensorDeviceAddress); - #else - temperature = sensor.getTempF(sensorDeviceAddress); - #endif + + if (degC) temperature = sensor->getTempC(sensorDeviceAddress); + else temperature = sensor->getTempF(sensorDeviceAddress); lastMeasurement = millis(); waitingForConversion = false; @@ -76,21 +77,29 @@ class UsermodTemperature : public Usermod { void setup() { - sensor.begin(); + + // pin retrieved from cfg.json (readFromConfig()) prior to running setup() + if (!pinManager.allocatePin(temperaturePin,false)) { + temperaturePin = -1; // allocation failed + DEBUG_PRINTLN(F("Temperature pin allocation failed.")); + } else { + oneWire = new OneWire(temperaturePin); + sensor = new DallasTemperature(oneWire); + if (sensor) sensor->begin(); + else + DEBUG_PRINTLN(F("Temperature sensor allocation failed.")); + } // get the unique 64-bit serial code stored in on-board ROM // if getAddress returns false, the sensor was not found - disabled = !sensor.getAddress(sensorDeviceAddress, 0); + disabled = (temperaturePin==-1) || !sensor->getAddress(sensorDeviceAddress, 0); if (!disabled) { DEBUG_PRINTLN(F("Dallas Temperature found")); // set the resolution for this specific device - sensor.setResolution(sensorDeviceAddress, 9, true); + sensor->setResolution(sensorDeviceAddress, 9, true); // do not block waiting for reading - sensor.setWaitForConversion(false); - // allocate pin & prevent other use - if (!pinManager.allocatePin(TEMPERATURE_PIN,false)) - disabled = true; + sensor->setWaitForConversion(false); } else { DEBUG_PRINTLN(F("Dallas Temperature not found")); } @@ -98,7 +107,7 @@ class UsermodTemperature : public Usermod { void loop() { if (disabled || strip.isUpdating()) return; - + unsigned long now = millis(); // check to see if we are due for taking a measurement @@ -106,21 +115,19 @@ class UsermodTemperature : public Usermod { // is complete the the reading is finished if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL) return; - // we are due for a measurement, if we are not already waiting + // we are due for a measurement, if we are not already waiting // for a conversion to complete, then make a new request for temps - if (!waitingForConversion) - { + if (!waitingForConversion) { requestTemperatures(); return; } // we were waiting for a conversion to complete, have we waited log enough? - if (now - lastTemperaturesRequest >= 94 /* 93.75ms per the datasheet */) - { + if (now - lastTemperaturesRequest >= 94 /* 93.75ms per the datasheet */) { getTemperature(); - + if (WLED_MQTT_CONNECTED) { - char subuf[38]; + char subuf[64]; strcpy(subuf, mqttDeviceTopic); if (-100 <= temperature) { // dont publish super low temperature as the graph will get messed up @@ -159,11 +166,77 @@ class UsermodTemperature : public Usermod { } temp.add(temperature); - #ifdef USERMOD_DALLASTEMPERATURE_CELSIUS - temp.add(F("°C")); - #else - temp.add(F("°F")); - #endif + if (degC) temp.add(F("°C")); + else temp.add(F("°F")); + } + + /** + * 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")] = temperaturePin; + root[F("mode_Temperature")] = degC ? ("C") : ("F"); + } + + /** + * 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) { + int8_t pin = (int)root[F("pin_Temperature")]; + // deallocate pin and release memory + pinManager.deallocatePin(temperaturePin); + delete sensor; + delete oneWire; + // disable usermod + temperaturePin = -1; + disabled = true; + // check if pin is OK + if (pin>=0 && pinManager.allocatePin(pin,false)) { + // allocat memory + oneWire = new OneWire(pin); + sensor = new DallasTemperature(oneWire); + if (sensor) { + temperaturePin = pin; + sensor->begin(); + disabled = !sensor->getAddress(sensorDeviceAddress, 0); + } else { + pinManager.deallocatePin(pin); + } + } + } + if (root[F("mode_Temperature")] != nullptr) { + degC = (root[F("mode_Temperature")]==String(PSTR("C"))); + } + } + + /** + * addToConfig() (called from set.cpp) stores persistent properties to cfg.json + */ + void addToConfig(JsonObject &root) { + // we add JSON object: {"Temperature": {"pin": 0, "degC": true}} + JsonObject top = root.createNestedObject(F("Temperature")); + top[F("pin")] = temperaturePin; + top[F("degC")] = degC; + } + + /** + * readFromConfig() is called before setup() to populate properties from values stored in cfg.json + */ + void readFromConfig(JsonObject &root) { + // we look for JSON object: {"Temperature": {"pin": 0, "degC": true}} + JsonObject top = root[F("Temperature")]; + if (!top.isNull() && top[F("pin")] != nullptr) { + temperaturePin = (int)top[F("pin")]; + degC = top[F("degC")] != nullptr ? top[F("degC")] : true; + } else { + DEBUG_PRINTLN(F("No Temperature sensor config found. (Using defaults.)")); + } } uint16_t getId() diff --git a/wled00/FX.h b/wled00/FX.h index d38c0718..4cc7c80c 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -603,7 +603,7 @@ class WS2812FX { setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), show(void), setRgbwPwm(void), - setColorOrder(uint8_t co), +// setColorOrder(uint8_t co), setPixelSegment(uint8_t n); bool @@ -629,7 +629,7 @@ class WS2812FX { getMaxSegments(void), //getFirstSelectedSegment(void), getMainSegmentId(void), - getColorOrder(void), +// getColorOrder(void), gamma8(uint8_t), gamma8_cal(uint8_t, float), get_random_wheel_index(uint8_t); diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e1d6ff1b..f181b0b2 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -511,14 +511,14 @@ uint32_t WS2812FX::getLastShow(void) { return _lastShow; } -//TODO these need to be on a per-strip basis -uint8_t WS2812FX::getColorOrder(void) { - return COL_ORDER_GRB; -} - -void WS2812FX::setColorOrder(uint8_t co) { - //bus->SetColorOrder(co); -} +// there is no longer any need for these two +//uint8_t WS2812FX::getColorOrder(void) { +// return COL_ORDER_GRB; +//} +// +//void WS2812FX::setColorOrder(uint8_t co) { +// //bus->SetColorOrder(co); +//} void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) { if (n >= MAX_NUM_SEGMENTS) return; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index ad450975..9268a219 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -54,7 +54,7 @@ class Bus { virtual uint8_t getPins(uint8_t* pinArray) { return 0; } - uint16_t getStart() { + inline uint16_t getStart() { return _start; } @@ -76,11 +76,11 @@ class Bus { return false; } - uint8_t getType() { + inline uint8_t getType() { return _type; } - bool isOk() { + inline bool isOk() { return _valid; } @@ -119,11 +119,11 @@ class BusDigital : public Bus { //Serial.printf("Successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n",nr, len, type, pins[0],pins[1],_iType); }; - void show() { + inline void show() { PolyBus::show(_busPtr, _iType); } - bool canShow() { + inline bool canShow() { return PolyBus::canShow(_busPtr, _iType); } @@ -150,11 +150,11 @@ class BusDigital : public Bus { return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrder); } - uint8_t getColorOrder() { + inline uint8_t getColorOrder() { return _colorOrder; } - uint16_t getLength() { + inline uint16_t getLength() { return _len - _skip; } @@ -169,11 +169,11 @@ class BusDigital : public Bus { _colorOrder = colorOrder; } - bool isRgbw() { + inline bool isRgbw() { return _rgbw; } - void reinit() { + inline void reinit() { PolyBus::begin(_busPtr, _iType, _pins); } @@ -271,7 +271,7 @@ class BusPwm : public Bus { } } - void setBrightness(uint8_t b) { + inline void setBrightness(uint8_t b) { _bri = b; } @@ -285,7 +285,7 @@ class BusPwm : public Bus { return (_type > TYPE_ONOFF && _type <= TYPE_ANALOG_5CH && _type != TYPE_ANALOG_3CH); } - void cleanup() { + inline void cleanup() { deallocatePins(); } @@ -326,8 +326,6 @@ class BusManager { } else { busses[numBusses] = new BusPwm(bc); } -// numBusses++; -// return numBusses -1; return numBusses++; } @@ -385,7 +383,7 @@ class BusManager { return busses[busNr]; } - uint8_t getNumBusses() { + inline uint8_t getNumBusses() { return numBusses; } diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 514c3fba..fed97495 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -90,9 +90,9 @@ void deserializeConfig() { // 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; - ledCount = 0; + CJSON(ledCount, hw_led[F("total")]); + if (ledCount > MAX_LEDS) ledCount = MAX_LEDS; + uint16_t lC = 0; CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]); CJSON(strip.milliampsPerLed, hw_led[F("ledma")]); @@ -109,20 +109,16 @@ void deserializeConfig() { uint8_t pins[5] = {255, 255, 255, 255, 255}; JsonArray pinArr = elm[F("pin")]; if (pinArr.size() == 0) continue; -// pins[0] = pinArr[0]; uint8_t i = 0; for (int p : pinArr) { pins[i++] = p; -// i++; if (i>4) break; } uint16_t length = elm[F("len")]; - if (length==0 || length+ledCount > MAX_LEDS) continue; // zero length or we reached max. number of LEDs, just stop - // maybe we should have - // start = ledCount; // length of previous strips + if (length==0 || length+lC > MAX_LEDS) continue; // zero length or we reached max. number of LEDs, just stop uint16_t start = elm[F("start")] | 0; - if (start >= ledCount+length) continue; // something is very wrong :) + if (start >= lC+length) continue; // something is very wrong :) //limit length of strip if it would exceed total configured LEDs //if (start + length > ledCount) length = ledCount - start; uint8_t colorOrder = (int)elm[F("order")]; @@ -134,10 +130,11 @@ void deserializeConfig() { if ((bool)elm[F("rgbw")]) SET_BIT(ledType,7); else UNSET_BIT(ledType,7); // hack bit 7 to indicate RGBW (as an override if necessary) useRGBW |= (bool)elm[F("rgbw")]; s++; - ledCount += length; + lC += length; BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst); busses.add(bc); } + if (lC > ledCount) ledCount = lC; // fix incorrect total length (honour analog setup) strip.finalizeInit(); JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0]; @@ -458,7 +455,7 @@ void serializeConfig() { if (!bus || bus->getLength()==0) break; JsonObject ins = hw_led_ins.createNestedObject(); ins[F("en")] = true; - ins[F("start")] = bus->getStart(); // really needed? + ins[F("start")] = bus->getStart(); ins[F("len")] = bus->getLength(); JsonArray ins_pin = ins.createNestedArray("pin"); uint8_t pins[5]; diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 635804db..92039373 100644 --- a/wled00/data/settings_leds.htm +++ b/wled00/data/settings_leds.htm @@ -117,10 +117,10 @@ LK.value=""; } } - d.getElementById("ls"+n).readOnly = !(type >= 32 && type < 48); // not analog - d.getElementById("LC").readOnly = !(type >= 32 && type < 48); // not analog + d.getElementById("ls"+n).readOnly = !(type > 31 && type < 48); // not analog + d.getElementById("LC").readOnly = !(type > 31 && type < 48); // not analog if (change) { - d.getElementById("ew"+n).checked = (type == 30 || type == 31 || type == 44 || type == 45); // TYPE_xxxx values from const.h + d.getElementById("ew"+n).checked = (type == 30 || type == 31 || type == 44 || type == 45); // RGBW checkbox, TYPE_xxxx values from const.h } isRGBW |= d.getElementById("ew"+n).checked; d.getElementById("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline"; @@ -138,7 +138,12 @@ var sLC = 0, maxLC = 0; for (i=0; imaxLC)maxLC=c;}continue;} + if (nm=="LC" && LCs[i].name !== "LC") { + var c=parseInt(LCs[i].value,10); + if(d.getElementById("ls"+n).readOnly) d.getElementById("ls"+n).value=sLC; + if(c){sLC+=c;if(c>maxLC)maxLC=c;} + continue; + } if (nm=="L0" || nm=="L1") { var lc=d.getElementsByName("LC"+LCs[i].name.substring(2))[0]; p3u|=(LCs[i].value==3); @@ -207,45 +212,47 @@ var f = d.getElementById("mLC"); if (n==1) { - var cn = `
- ${i>0?'
':''} - ${i+1}: -   - Color Order: - - RGBW:
- Pin: - Clock: - - - -
- Start:   -
- Count:
- Reverse:

-
`; +// npm run build has trouble minimizing spaces inside string + var cn = +`
+ ${i>0?'
':''} + ${i+1}: +   + Color Order: + + RGBW:
+ Pin: + Clock: + + + +
+ Start:   +
+ Count:
+ Reverse:

+
`; f.insertAdjacentHTML("beforeend", cn); } if (n==-1) { diff --git a/wled00/html_settings.h b/wled00/html_settings.h index fddc8d54..05e7f082 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -72,7 +72,7 @@ Do not enable if WiFi is working correctly, increases power consumption.
LED Settings