Updated readme, removed obsolete usermods.

This commit is contained in:
Blaz Kristan 2021-05-03 13:32:11 +02:00
parent d5fd5954d1
commit 24932d6ba3
14 changed files with 28 additions and 867 deletions

View File

@ -1,21 +0,0 @@
/*
* Animated_Staircase compiletime confguration.
*
* Please see README.md on how to change this file.
*/
// Please change the pin numbering below to match your board.
#define TOP_PIR_PIN D5
#define BOTTOM_PIR_PIN D6
// Or uncumment and a pir and use an ultrasound HC-SR04 sensor,
// see README.md for details
#ifndef TOP_PIR_PIN
#define TOP_TRIGGER_PIN D2
#define TOP_ECHO_PIN D3
#endif
#ifndef BOTTOM_PIR_PIN
#define BOTTOM_TRIGGER_PIN D4
#define BOTTOM_ECHO_PIN D5
#endif

View File

@ -20,44 +20,10 @@ Edit `usermods_list.cpp`:
2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file 2. add `#include "../usermods/Animated_Staircase/Animated_Staircase.h"` to the top of the file
3. add `usermods.add(new Animated_Staircase());` to the end of the `void registerUsermods()` function. 3. add `usermods.add(new Animated_Staircase());` to the end of the `void registerUsermods()` function.
Edit `Animated_Staircase_config.h`: You can configure usermod using Usermods settings page.
1. Open `usermods/Animated_Staircase/Animated_Staircase_config.h` Please enter GPIO pins for PIR sensors or ultrasonic sensor (trigger and echo).
2. To use PIR sensors, change these lines to match your setup: If you use PIR sensor enter -1 for echo pin.
Using D7 and D6 pin notation as used on several boards: Maximum distance for ultrasonic sensor can be configured as a time needed for echo (see below).
```cpp
#define TOP_PIR_PIN D7
#define BOTTOM_PIR_PIN D6
```
Or using GPIO numbering for pins 25 and 26:
```cpp
#define TOP_PIR_PIN 26
#define BOTTOM_PIR_PIN 25
```
To use Ultrasonic HC-SR04 sensors instead of (one of the) PIR sensors,
uncomment one of the PIR sensor lines and adjust the pin numbers for the
connected Ultrasonic sensor. In the example below we use an Ultrasonic
sensor at the bottom of the stairs:
```cpp
#define TOP_PIR_PIN 32
//#define BOTTOM_PIR_PIN D6 /* This PIR sensor is disabled */
#ifndef TOP_PIR_PIN
#define TOP_SIGNAL_PIN D2
#define TOP_ECHO_PIN D3
#endif
#ifndef BOTTOM_PIR_PIN /* If the bottom PIR is disabled, */
#define BOTTOM_SIGNAL_PIN 25 /* This Ultrasonic sensor is used */
#define BOTTOM_ECHO_PIN 26
#endif
```
After these modifications, compile and upload your WLED binary to your board
and check the WLED info page to see if this usermod is enabled.
## Hardware installation ## Hardware installation
1. Stick the LED strip under each step of the stairs. 1. Stick the LED strip under each step of the stairs.
@ -201,3 +167,7 @@ curl -X POST -H "Content-Type: application/json" \
Have fun with this usermod.<br/> Have fun with this usermod.<br/>
www.rolfje.com www.rolfje.com
## Change log
2021-04
* Adaptation for runtime configuration.

View File

@ -1,9 +0,0 @@
# PIR sensor with MQTT
This simple usermod allows attaching a PIR sensor like the AM312 and publish the readings over MQTT. A message is sent when motion is detected as well as when motion has stopped.
This usermod has only been tested with the AM312 sensor though should work for any other PIR sensor. Note that this does not control the LED strip directly, it only publishes MQTT readings for use with other integrations like Home Assistant.
## Installation
Copy and replace the file `usermod.cpp` in wled00 directory.

View File

@ -1,55 +0,0 @@
#include "wled.h"
/*
* This v1 usermod file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* If you just need 8 bytes, use 2551-2559 (you do not need to increase EEPSIZE)
*
* Consider the v2 usermod API if you need a more advanced feature set!
*/
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
// PIR sensor pin
const int MOTION_PIN = 16;
// MQTT topic for sensor values
const char MQTT_TOPIC[] = "/motion";
int prevState = LOW;
//gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup()
{
pinMode(MOTION_PIN, INPUT);
}
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
void userConnected()
{
}
void publishMqtt(String state)
{
//Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr){
char subuf[38];
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, MQTT_TOPIC);
mqtt->publish(subuf, 0, true, state.c_str());
}
}
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
void userLoop()
{
if (digitalRead(MOTION_PIN) == HIGH && prevState == LOW) { // Motion detected
publishMqtt("ON");
prevState = HIGH;
}
if (digitalRead(MOTION_PIN) == LOW && prevState == HIGH) { // Motion stopped
publishMqtt("OFF");
prevState = LOW;
}
}

View File

@ -107,3 +107,7 @@ class MyUsermod : public Usermod {
``` ```
Have fun - @gegu Have fun - @gegu
## Change log
2021-04
* Adaptation for runtime configuration.

View File

@ -14,10 +14,10 @@ Copy the example `platformio_override.ini` to the root directory. This file sho
### Define Your Options ### Define Your Options
* `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp * `USERMOD_DALLASTEMPERATURE` - define this to have this user mod included wled00\usermods_list.cpp
* `USERMOD_DALLASTEMPERATURE_CELSIUS` - define this to report temperatures in degrees celsious, otherwise fahrenheit will be reported
* `USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL` - the number of milliseconds between measurements, defaults to 60 seconds
* `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds * `USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
All parameters can be configured at runtime using Usermods settings page.
## Project link ## Project link
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link * [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
@ -41,8 +41,6 @@ default_envs = d1_mini
... ...
lib_deps = lib_deps =
... ...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For Dallas sensor uncomment following 2 lines #For Dallas sensor uncomment following 2 lines
DallasTemperature@~3.8.0 DallasTemperature@~3.8.0
OneWire@~2.3.5 OneWire@~2.3.5
@ -56,3 +54,5 @@ lib_deps =
* Do not report low temperatures that indicate an error to mqtt * Do not report low temperatures that indicate an error to mqtt
* Disable plugin if temperature sensor not detected * Disable plugin if temperature sensor not detected
* Report the number of seconds until the first read in the info screen instead of sensor error * Report the number of seconds until the first read in the info screen instead of sensor error
2021-04
* Adaptation for runtime configuration.

View File

@ -1,15 +0,0 @@
WLED v2 UserMod for running macros at sunrise and sunset.
At the time of this text, this user mod requires code to be changed to set certain variables:
1. To reflect the user's graphical location (latitude/longitude) used for calculating apparent sunrise/sunset
2. To specify which macros will be run at sunrise and/or sunset. (defaults to 15 at sunrise and 16 at sunset)
3. To optionally provide an offset from sunrise/sunset, in minutes (max of +/- 2 hours), when the macro will be run.
In addition, WLED must be configured to get time from NTP (and the time must be retrieved via NTP.)
Please open the UserMod_SunRiseAndSet.h file for instructions on what needs to be changed, where to copy files, etc.
If this usermod proves useful enough, the code might eventually be updated to allow prompting for the required information
via the web interface and to store settings in EEPROM instead of hard-coding in the .h file.
This usermod has only been tested on the esp32dev platform, but there's no reason it wouldn't work on other platforms.

View File

@ -1,166 +0,0 @@
#pragma once
#include "wled.h"
#include <Dusk2Dawn.h>
/*
*
* REQUIREMENTS:
* The Dusk2Dawn library must be installed. This can be found at https://github.com/dmkishi/Dusk2Dawn. The 1.0.1 version of this library found via
* Arduino or platformio library managers is buggy and won't compile. The latest version from github should be used.
*
* NTP must be enabled and functional. It simply makes no sense to have events on sunrise/sunset when an accurate time isn't available.
*
* The user's geographical latitude and longitude must be configured (in decimal, not degrees/minutes/etc) using m_fLatitude and m_fLongitude
*
* if desired, an offset of up to +/- 2 hours can be specified for each of sunrise/sunset using m_sunriseOffset and m_sunsetOffset (defaults to 0)
*
* The specific macro to run at sunrise and/or sunset can be changed using m_sunriseMacro and m_sunsetMacro. (defaults to 15 and 16)
*
* From the Dusk2Dawn library:
* HINT: An easy way to find the longitude and latitude for any location is
* to find the spot in Google Maps, right click the place on the map, and
* select "What's here?". At the bottom, youll see a card with the
* coordinates.
*
* Once configured, copy UserMod_SunRiseAndSet.h to the sketch file (the same folder as wled00.ino exists),
* and then edit "usermods_list.cpp":
* Add '#include "UserMod_SunRiseAndSet.h"' in the 'includes' area
* Add 'usermods.add(new UserMod_SunRiseAndSet());' in the registerUsermods() area
*
*/
class UserMod_SunRiseAndSet : public Usermod
{
private:
/**** USER SETTINGS ****/
float m_fLatitude = 40.6; // latitude where sunrise/set are calculated
float m_fLongitude = -79.80; // longitude where sunrise/set are calculated
int8_t m_sunriseOffset = 0; // offset from sunrise, in minutes, when macro should be run (negative for before sunrise, positive for after sunrise)
int8_t m_sunsetOffset = 0; // offset from sunset, in minutes, when macro should be run (negative for before sunset, positive for after sunset)
uint8_t m_sunriseMacro = 15; // macro number to run at sunrise
uint8_t m_sunsetMacro = 16; // macro number to run at sunset
/**** END OF USER SETTINGS. DO NOT EDIT BELOW THIS LINE! ****/
Dusk2Dawn *m_pD2D = NULL; // this must be dynamically allocated in order for parameters to be loaded from EEPROM
int m_nUserSunrise = -1; // time, in minutes from midnight, of sunrise
int m_nUserSunset = -1; // time, in minutes from midnight, of sunset
byte m_nLastRunMinute = -1; // indicates what minute the userloop was last run - used so that the code only runs once per minute
public:
virtual void setup(void)
{
/* TODO: From EEPROM, load the following variables:
*
* int16_t latitude16 = 4060; // user provided latitude, multiplied by 100 and rounded
* int16_t longitude16 = -7980; // user provided longitude, multiplied by 100 and rounded.
* int8_t sunrise_offset = 0; // number of minutes to offset the sunrise macro trigger (positive for minutes after sunrise, negative for minutes before)
* int8_t sunset_offset = 0; // number of minutes to offset the sunset macro trigger (positive for minutes after sunset, negative for minutes before)
*
* then:
* m_fLatitude = (float)latitude / 100.0;
* m_fLongitude = (float)longitude / 100.0;
* m_sunriseOffset = sunrise_offset;
* m_sunsetOffset = sunset_offset;
*/
if ((0.0 != m_fLatitude) || (0.0 != m_fLongitude))
{
m_pD2D = new Dusk2Dawn (m_fLatitude, m_fLongitude, 0 /* UTC */);
// can't really check for failures. if the alloc fails, the mod just doesn't work.
}
}
void loop(void)
{
// without NTP, or a configured lat/long, none of this stuff is going to work...
// As an alternative, need to figure out how to determine if the user has manually set the clock or not.
if (m_pD2D && (999000000L != ntpLastSyncTime))
{
// to prevent needing to import all the timezone stuff from other modules, work completely in UTC
time_t timeUTC = now();
tmElements_t tmNow;
breakTime(timeUTC, tmNow);
int nCurMinute = tmNow.Minute;
if (m_nLastRunMinute != nCurMinute) //only check once a new minute begins
{
m_nLastRunMinute = nCurMinute;
int numMinutes = (60 * tmNow.Hour) + m_nLastRunMinute; // how many minutes into the day are we?
// check to see if sunrise/sunset should be re-determined. Only do this if neither sunrise nor sunset
// are set. That happens when the device has just stated, and after both sunrise/sunset have already run.
if ((-1 == m_nUserSunrise) && (-1 == m_nUserSunset))
{
m_nUserSunrise = m_pD2D->sunrise(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
m_nUserSunset = m_pD2D->sunset(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
if (m_nUserSunrise > numMinutes) // has sunrise already passed? if so, recompute for tomorrow
{
breakTime(timeUTC + (60*60*24), tmNow);
m_nUserSunrise = m_pD2D->sunrise(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
if (m_nUserSunset > numMinutes) // if sunset has also passed, recompute that as well
{
m_nUserSunset = m_pD2D->sunset(tmNow.Year + 1970, tmNow.Month, tmNow.Day, false) % 1440;
}
}
// offset by user provided values. becuase the offsets are signed bytes, the max offset is just over 2 hours.
m_nUserSunrise += m_sunriseOffset;
m_nUserSunset += m_sunsetOffset;
}
if (numMinutes == m_nUserSunrise) // Good Morning!
{
if (m_sunriseMacro)
applyMacro(m_sunriseMacro); // run macro 15
m_nUserSunrise = -1;
}
else if (numMinutes == m_nUserSunset) // Good Night!
{
if (m_sunsetMacro)
applyMacro(m_sunsetMacro); // run macro 16
m_nUserSunset = -1;
}
} // if (m_nLastRunMinute != nCurMinute)
} // if (m_pD2D && (999000000L != ntpLastSyncTime))
}
void addToJsonState(JsonObject& root)
{
JsonObject user = root["SunRiseAndSet"];
if (user.isNull()) user = root.createNestedObject("SunRiseAndSet");
char buf[10];
if (-1 != m_nUserSunrise)
{
snprintf(buf, 10, "%02d:%02d UTC", m_nUserSunrise / 60, m_nUserSunrise % 60);
user["rise"] = buf;
}
if (-1 != m_nUserSunset)
{
snprintf(buf, 10, "%02d:%02d UTC", m_nUserSunset / 60, m_nUserSunset % 60);
user["set"] = buf;
}
JsonObject vars = user.createNestedObject("vars");
vars["lat"] = m_fLatitude;
vars["long"] = m_fLongitude;
vars["rise_mac"] = m_sunriseMacro;
vars["set_mac"] = m_sunsetMacro;
vars["rise_off"] = m_sunriseOffset;
vars["set_off"] = m_sunsetOffset;
}
~UserMod_SunRiseAndSet(void)
{
if (m_pD2D) delete m_pD2D;
}
};

View File

@ -1,515 +0,0 @@
//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103
#ifndef NpbWrapper_h
#define NpbWrapper_h
// make sure we're using esp32 platform
#ifndef ARDUINO_ARCH_ESP32
#error This version of NbpWrapper.h only works with ESP32 hardware.
#endif
#ifndef NUM_STRIPS
#error Need to define number of LED strips using build flag -D NUM_STRIPS=4 for 4 LED strips
#endif
#ifndef PIXEL_COUNTS
#error Need to define pixel counts using build flag -D PIXEL_COUNTS="25, 25, 25, 25" for 4 LED strips with 25 LEDs each
#endif
#ifndef DATA_PINS
#error Need to define data pins using build flag -D DATA_PINS="1, 2, 3, 4" if LED strips are on data pins 1, 2, 3, and 4
#endif
// //PIN CONFIGURATION
#ifndef LEDPIN
#define LEDPIN 1 // Legacy pin def required by some other portions of code. This pin is not used do drive LEDs.
#endif
#ifndef IRPIN
#define IRPIN -1 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#endif
#ifndef RLYPIN
#define RLYPIN -1 //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
#include <NeoPixelBrightnessBus.h>
#include "const.h"
const uint8_t numStrips = NUM_STRIPS; // max 8 strips allowed on esp32
const uint16_t pixelCounts[numStrips] = {PIXEL_COUNTS}; // number of pixels on each strip
const uint8_t dataPins[numStrips] = {DATA_PINS}; // change these pins based on your board
#define PIXELFEATURE3 NeoGrbFeature
#define PIXELFEATURE4 NeoGrbwFeature
// ESP32 has 8 RMT interfaces available, each of which can drive a strip of pixels
// Convenience #defines for creating NeoPixelBrightnessBus on each RMT interface for both GRB and GRBW LED strips
#define NeoPixelBrightnessBusGrbRmt0 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt0Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt1 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt1Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt2 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt2Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt3 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt3Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt4 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt4Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt5 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt5Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt6 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt6Ws2812xMethod>
#define NeoPixelBrightnessBusGrbRmt7 NeoPixelBrightnessBus<PIXELFEATURE3, NeoEsp32Rmt7Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt0 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt0Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt1 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt1Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt2 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt2Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt3 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt3Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt4 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt4Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt5 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt5Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt6 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt6Ws2812xMethod>
#define NeoPixelBrightnessBusGrbwRmt7 NeoPixelBrightnessBus<PIXELFEATURE4, NeoEsp32Rmt7Ws2812xMethod>
enum NeoPixelType
{
NeoPixelType_None = 0,
NeoPixelType_Grb = 1,
NeoPixelType_Grbw = 2,
NeoPixelType_End = 3
};
class NeoPixelWrapper
{
public:
NeoPixelWrapper() :
_type(NeoPixelType_None)
{
// On initialization fill in the pixelStripStartIdx array with the beginning index of each strip
// relative to th entire array.
uint16_t totalPixels = 0;
for (uint8_t idx = 0; idx < numStrips; idx++)
{
pixelStripStartIdx[idx] = totalPixels;
totalPixels += pixelCounts[idx];
}
}
~NeoPixelWrapper()
{
cleanup();
}
void Begin(NeoPixelType type, uint16_t pixelCount)
{
cleanup();
_type = type;
switch (_type)
{
case NeoPixelType_Grb:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrb0 = new NeoPixelBrightnessBusGrbRmt0(pixelCounts[idx], dataPins[idx]); pGrb0->Begin(); break;
case 1: pGrb1 = new NeoPixelBrightnessBusGrbRmt1(pixelCounts[idx], dataPins[idx]); pGrb1->Begin(); break;
case 2: pGrb2 = new NeoPixelBrightnessBusGrbRmt2(pixelCounts[idx], dataPins[idx]); pGrb2->Begin(); break;
case 3: pGrb3 = new NeoPixelBrightnessBusGrbRmt3(pixelCounts[idx], dataPins[idx]); pGrb3->Begin(); break;
case 4: pGrb4 = new NeoPixelBrightnessBusGrbRmt4(pixelCounts[idx], dataPins[idx]); pGrb4->Begin(); break;
case 5: pGrb5 = new NeoPixelBrightnessBusGrbRmt5(pixelCounts[idx], dataPins[idx]); pGrb5->Begin(); break;
case 6: pGrb6 = new NeoPixelBrightnessBusGrbRmt6(pixelCounts[idx], dataPins[idx]); pGrb6->Begin(); break;
case 7: pGrb7 = new NeoPixelBrightnessBusGrbRmt7(pixelCounts[idx], dataPins[idx]); pGrb7->Begin(); break;
}
}
break;
}
case NeoPixelType_Grbw:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrbw0 = new NeoPixelBrightnessBusGrbwRmt0(pixelCounts[idx], dataPins[idx]); pGrbw0->Begin(); break;
case 1: pGrbw1 = new NeoPixelBrightnessBusGrbwRmt1(pixelCounts[idx], dataPins[idx]); pGrbw1->Begin(); break;
case 2: pGrbw2 = new NeoPixelBrightnessBusGrbwRmt2(pixelCounts[idx], dataPins[idx]); pGrbw2->Begin(); break;
case 3: pGrbw3 = new NeoPixelBrightnessBusGrbwRmt3(pixelCounts[idx], dataPins[idx]); pGrbw3->Begin(); break;
case 4: pGrbw4 = new NeoPixelBrightnessBusGrbwRmt4(pixelCounts[idx], dataPins[idx]); pGrbw4->Begin(); break;
case 5: pGrbw5 = new NeoPixelBrightnessBusGrbwRmt5(pixelCounts[idx], dataPins[idx]); pGrbw5->Begin(); break;
case 6: pGrbw6 = new NeoPixelBrightnessBusGrbwRmt6(pixelCounts[idx], dataPins[idx]); pGrbw6->Begin(); break;
case 7: pGrbw7 = new NeoPixelBrightnessBusGrbwRmt7(pixelCounts[idx], dataPins[idx]); pGrbw7->Begin(); break;
}
}
break;
}
}
}
void Show()
{
switch (_type)
{
case NeoPixelType_Grb:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrb0->Show(); break;
case 1: pGrb1->Show(); break;
case 2: pGrb2->Show(); break;
case 3: pGrb3->Show(); break;
case 4: pGrb4->Show(); break;
case 5: pGrb5->Show(); break;
case 6: pGrb6->Show(); break;
case 7: pGrb7->Show(); break;
}
}
break;
}
case NeoPixelType_Grbw:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrbw0->Show(); break;
case 1: pGrbw1->Show(); break;
case 2: pGrbw2->Show(); break;
case 3: pGrbw3->Show(); break;
case 4: pGrbw4->Show(); break;
case 5: pGrbw5->Show(); break;
case 6: pGrbw6->Show(); break;
case 7: pGrbw7->Show(); break;
}
}
break;
}
}
}
bool CanShow()
{
bool canShow = true;
switch (_type)
{
case NeoPixelType_Grb:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: canShow &= pGrb0->CanShow(); break;
case 1: canShow &= pGrb1->CanShow(); break;
case 2: canShow &= pGrb2->CanShow(); break;
case 3: canShow &= pGrb3->CanShow(); break;
case 4: canShow &= pGrb4->CanShow(); break;
case 5: canShow &= pGrb5->CanShow(); break;
case 6: canShow &= pGrb6->CanShow(); break;
case 7: canShow &= pGrb7->CanShow(); break;
}
}
break;
}
case NeoPixelType_Grbw:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: canShow &= pGrbw0->CanShow(); break;
case 1: canShow &= pGrbw1->CanShow(); break;
case 2: canShow &= pGrbw2->CanShow(); break;
case 3: canShow &= pGrbw3->CanShow(); break;
case 4: canShow &= pGrbw4->CanShow(); break;
case 5: canShow &= pGrbw5->CanShow(); break;
case 6: canShow &= pGrbw6->CanShow(); break;
case 7: canShow &= pGrbw7->CanShow(); break;
}
}
break;
}
}
return canShow;
}
void SetPixelColorRaw(uint16_t indexPixel, RgbwColor c)
{
// figure out which strip this pixel index is on
uint8_t stripIdx = 0;
for (uint8_t idx = 0; idx < numStrips; idx++)
{
if (indexPixel >= pixelStripStartIdx[idx])
{
stripIdx = idx;
}
else
{
break;
}
}
// subtract strip start index so we're addressing just this strip instead of all pixels on all strips
indexPixel -= pixelStripStartIdx[stripIdx];
switch (_type)
{
case NeoPixelType_Grb:
{
RgbColor rgb = RgbColor(c.R, c.G, c.B);
switch (stripIdx)
{
case 0: pGrb0->SetPixelColor(indexPixel, rgb); break;
case 1: pGrb1->SetPixelColor(indexPixel, rgb); break;
case 2: pGrb2->SetPixelColor(indexPixel, rgb); break;
case 3: pGrb3->SetPixelColor(indexPixel, rgb); break;
case 4: pGrb4->SetPixelColor(indexPixel, rgb); break;
case 5: pGrb5->SetPixelColor(indexPixel, rgb); break;
case 6: pGrb6->SetPixelColor(indexPixel, rgb); break;
case 7: pGrb7->SetPixelColor(indexPixel, rgb); break;
}
break;
}
case NeoPixelType_Grbw:
{
switch (stripIdx)
{
case 0: pGrbw0->SetPixelColor(indexPixel, c); break;
case 1: pGrbw1->SetPixelColor(indexPixel, c); break;
case 2: pGrbw2->SetPixelColor(indexPixel, c); break;
case 3: pGrbw3->SetPixelColor(indexPixel, c); break;
case 4: pGrbw4->SetPixelColor(indexPixel, c); break;
case 5: pGrbw5->SetPixelColor(indexPixel, c); break;
case 6: pGrbw6->SetPixelColor(indexPixel, c); break;
case 7: pGrbw7->SetPixelColor(indexPixel, c); break;
}
break;
}
}
}
void SetPixelColor(uint16_t indexPixel, RgbwColor c)
{
/*
Set pixel color with necessary color order conversion.
*/
RgbwColor col;
uint8_t co = _colorOrder;
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
//reorder channels to selected order
switch (co)
{
case 0: col.G = c.G; col.R = c.R; col.B = c.B; break; //0 = GRB, default
case 1: col.G = c.R; col.R = c.G; col.B = c.B; break; //1 = RGB, common for WS2811
case 2: col.G = c.B; col.R = c.R; col.B = c.G; break; //2 = BRG
case 3: col.G = c.R; col.R = c.B; col.B = c.G; break; //3 = RBG
case 4: col.G = c.B; col.R = c.G; col.B = c.R; break; //4 = BGR
default: col.G = c.G; col.R = c.B; col.B = c.R; break; //5 = GBR
}
col.W = c.W;
SetPixelColorRaw(indexPixel, col);
}
void SetBrightness(byte b)
{
switch (_type)
{
case NeoPixelType_Grb:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrb0->SetBrightness(b); break;
case 1: pGrb1->SetBrightness(b); break;
case 2: pGrb2->SetBrightness(b); break;
case 3: pGrb3->SetBrightness(b); break;
case 4: pGrb4->SetBrightness(b); break;
case 5: pGrb5->SetBrightness(b); break;
case 6: pGrb6->SetBrightness(b); break;
case 7: pGrb7->SetBrightness(b); break;
}
}
break;
}
case NeoPixelType_Grbw:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: pGrbw0->SetBrightness(b); break;
case 1: pGrbw1->SetBrightness(b); break;
case 2: pGrbw2->SetBrightness(b); break;
case 3: pGrbw3->SetBrightness(b); break;
case 4: pGrbw4->SetBrightness(b); break;
case 5: pGrbw5->SetBrightness(b); break;
case 6: pGrbw6->SetBrightness(b); break;
case 7: pGrbw7->SetBrightness(b); break;
}
}
break;
}
}
}
void SetColorOrder(byte colorOrder)
{
_colorOrder = colorOrder;
}
uint8_t GetColorOrder()
{
return _colorOrder;
}
RgbwColor GetPixelColorRaw(uint16_t indexPixel) const
{
// figure out which strip this pixel index is on
uint8_t stripIdx = 0;
for (uint8_t idx = 0; idx < numStrips; idx++)
{
if (indexPixel >= pixelStripStartIdx[idx])
{
stripIdx = idx;
}
else
{
break;
}
}
// subtract strip start index so we're addressing just this strip instead of all pixels on all strips
indexPixel -= pixelStripStartIdx[stripIdx];
switch (_type)
{
case NeoPixelType_Grb:
{
switch (stripIdx)
{
case 0: return pGrb0->GetPixelColor(indexPixel);
case 1: return pGrb1->GetPixelColor(indexPixel);
case 2: return pGrb2->GetPixelColor(indexPixel);
case 3: return pGrb3->GetPixelColor(indexPixel);
case 4: return pGrb4->GetPixelColor(indexPixel);
case 5: return pGrb5->GetPixelColor(indexPixel);
case 6: return pGrb6->GetPixelColor(indexPixel);
case 7: return pGrb7->GetPixelColor(indexPixel);
}
break;
}
case NeoPixelType_Grbw:
switch (stripIdx)
{
case 0: return pGrbw0->GetPixelColor(indexPixel);
case 1: return pGrbw1->GetPixelColor(indexPixel);
case 2: return pGrbw2->GetPixelColor(indexPixel);
case 3: return pGrbw3->GetPixelColor(indexPixel);
case 4: return pGrbw4->GetPixelColor(indexPixel);
case 5: return pGrbw5->GetPixelColor(indexPixel);
case 6: return pGrbw6->GetPixelColor(indexPixel);
case 7: return pGrbw7->GetPixelColor(indexPixel);
}
break;
}
return 0;
}
// NOTE: Due to feature differences, some support RGBW but the method name
// here needs to be unique, thus GetPixeColorRgbw
uint32_t GetPixelColorRgbw(uint16_t indexPixel) const
{
RgbwColor col = GetPixelColorRaw(indexPixel);
uint8_t co = _colorOrder;
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
switch (co)
{
// W G R B
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
}
return 0;
}
private:
NeoPixelType _type;
byte _colorOrder = 0;
uint16_t pixelStripStartIdx[numStrips];
// pointers for every possible type for up to 8 strips
NeoPixelBrightnessBusGrbRmt0 *pGrb0;
NeoPixelBrightnessBusGrbRmt1 *pGrb1;
NeoPixelBrightnessBusGrbRmt2 *pGrb2;
NeoPixelBrightnessBusGrbRmt3 *pGrb3;
NeoPixelBrightnessBusGrbRmt4 *pGrb4;
NeoPixelBrightnessBusGrbRmt5 *pGrb5;
NeoPixelBrightnessBusGrbRmt6 *pGrb6;
NeoPixelBrightnessBusGrbRmt7 *pGrb7;
NeoPixelBrightnessBusGrbwRmt0 *pGrbw0;
NeoPixelBrightnessBusGrbwRmt1 *pGrbw1;
NeoPixelBrightnessBusGrbwRmt2 *pGrbw2;
NeoPixelBrightnessBusGrbwRmt3 *pGrbw3;
NeoPixelBrightnessBusGrbwRmt4 *pGrbw4;
NeoPixelBrightnessBusGrbwRmt5 *pGrbw5;
NeoPixelBrightnessBusGrbwRmt6 *pGrbw6;
NeoPixelBrightnessBusGrbwRmt7 *pGrbw7;
void cleanup()
{
switch (_type)
{
case NeoPixelType_Grb:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: delete pGrb0; pGrb0 = NULL; break;
case 1: delete pGrb1; pGrb1 = NULL; break;
case 2: delete pGrb2; pGrb2 = NULL; break;
case 3: delete pGrb3; pGrb3 = NULL; break;
case 4: delete pGrb4; pGrb4 = NULL; break;
case 5: delete pGrb5; pGrb5 = NULL; break;
case 6: delete pGrb6; pGrb6 = NULL; break;
case 7: delete pGrb7; pGrb7 = NULL; break;
}
}
break;
}
case NeoPixelType_Grbw:
{
for (uint8_t idx = 0; idx < numStrips; idx++)
{
switch (idx)
{
case 0: delete pGrbw0; pGrbw0 = NULL; break;
case 1: delete pGrbw1; pGrbw1 = NULL; break;
case 2: delete pGrbw2; pGrbw2 = NULL; break;
case 3: delete pGrbw3; pGrbw3 = NULL; break;
case 4: delete pGrbw4; pGrbw4 = NULL; break;
case 5: delete pGrbw5; pGrbw5 = NULL; break;
case 6: delete pGrbw6; pGrbw6 = NULL; break;
case 7: delete pGrbw7; pGrbw7 = NULL; break;
}
}
}
}
}
};
#endif

View File

@ -1,22 +0,0 @@
# esp32_multistrip
This usermod enables up to 8 data pins to be used from an esp32 module to drive separate LED strands. This only works with one-wire LEDs like the WS2812.
The esp32 RMT hardware is used for data output. See here for hardware driver implementation details: https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
Pass the following variables to the compiler as build flags:
- `ESP32_MULTISTRIP`
- Define this to use usermod NpbWrapper.h instead of default one in WLED.
- `NUM_STRIPS`
- Number of strips in use
- `PIXEL_COUNTS`
- List of pixel counts in each strip
- `DATA_PINS`
- List of data pins each strip is attached to. There may be board-specific restrictions on which pins can be used for RTM.
From the perspective of WLED software, the LEDs are addressed as one long strand. The modified NbpWrapper.h file addresses the appropriate strand from the overall LED index based on the number of LEDs defined in each strand.
See `platformio_override.ini` for example configuration.
Tested on low cost ESP-WROOM-32 dev boards from Amazon, such as those sold by KeeYees.

View File

@ -1,16 +0,0 @@
; Example platformio_override.ini that shows how to configure your environment to use the multistrip usermod.
; Copy this file to the base wled directory that contains platformio.ini.
; Multistrip requires ESP32 because it has many more pins that can be used as LED outputs.
; Need to define NUM_STRIPS, PIXEL_COUNTS, and DATA_PINS as shown below.
[platformio]
default_envs = esp32_multistrip
[env:esp32_multistrip]
extends=env:esp32dev
build_flags = ${env:esp32dev.build_flags}
-D ESP32_MULTISTRIP ; define this variable to use ESP32_MULTISTRIP usermod
-D NUM_STRIPS=4 ; number of pixel strips in use
-D PIXEL_COUNTS="50, 50, 50, 50" ; number of pixels in each strip
-D DATA_PINS="25, 26, 32, 33" ; esp32 pins used for each pixel strip. available pins depends on esp32 module.

View File

@ -49,3 +49,7 @@ Usermod can be configured in Usermods settings page.
If there is no MultiRelay section, just save current configuration and re-open Usermods settings page. If there is no MultiRelay section, just save current configuration and re-open Usermods settings page.
Have fun - @blazoncek Have fun - @blazoncek
## Change log
2021-04
* First implementation.

View File

@ -30,8 +30,8 @@ This file should be placed in the same directory as `platformio.ini`.
* `USERMOD_AUTO_SAVE` - define this to have this the Auto Save usermod included wled00\usermods_list.cpp * `USERMOD_AUTO_SAVE` - define this to have this the Auto Save usermod included wled00\usermods_list.cpp
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details) * `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells this usermod that the display is available (see the Four Line Display usermod `readme.md` for more details)
* `AUTOSAVE_SETTLE_MS` - Minimum time to wave before auto saving, defaults to 10000 (10s)
* `AUTOSAVE_PRESET_NUM` - Preset number to auto-save to, auto-load at startup from, defaults to 99 You can configure auto-save parameters using Usermods settings page.
### PlatformIO requirements ### PlatformIO requirements
@ -43,3 +43,5 @@ Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.
2021-02 2021-02
* First public release * First public release
2021-04
* Adaptation for runtime configuration.

View File

@ -1,4 +1,4 @@
# Rotary Encoder UI Usermod # I2C 4 Line Display Usermod
First, thanks to the authors of the ssd11306_i2c_oled_u8g2 mod. First, thanks to the authors of the ssd11306_i2c_oled_u8g2 mod.
@ -22,10 +22,8 @@ This file should be placed in the same directory as `platformio.ini`.
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells Rotary Encoder usermod, if installed, that the display is available * `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp - also tells Rotary Encoder usermod, if installed, that the display is available
* `FLD_PIN_SCL` - The display SCL pin, defaults to 5 * `FLD_PIN_SCL` - The display SCL pin, defaults to 5
* `FLD_PIN_SDA` - The display SDA pin, defaults to 4 * `FLD_PIN_SDA` - The display SDA pin, defaults to 4
* `FLIP_MODE` - Set to 0 or 1
* `LINE_HEIGHT` - Set to 1 or 2
There are other `#define` values in the Usermod that might be of interest. All of the parameters can be configured using Usermods settings page, inluding GPIO pins.
### PlatformIO requirements ### PlatformIO requirements
@ -37,3 +35,5 @@ UI usermod folder for how to include these using `platformio_override.ini`.
2021-02 2021-02
* First public release * First public release
2021-04
* Adaptation for runtime configuration.