Two LED strips and two encoders to adjust the brightness

Hi everyone!

I’m trying to set up my first project using an ESP32 and WLED.
I would need to use two rotary encoders to adjust the brightness (only that) of two distinct LED strips (segment 1 and segment 2).

I found a usermod that seems to be mostly right for me (usermod_rotary_brightness_color), but unfortunately:

  • it seems to handle only one encoder
  • it doesn’t give me the ability to control a specific segment
  • the button integrated into the encoder is used to switch between the two modes: brightness control and color control. However, I would prefer to use it simply as a button for other purposes/functions.

I would also need the brightness to have a range from 10% to 100% with increments/decreases of 10%.

As I lack programming skills, I was wondering if someone could be so kind as to help me. Furthermore, could you explain how to install the mod on my ESP32 with WLED already installed?

Thank you very much, and happy holidays!

I spent a few hours looking at the various usermods for the use of rotary encoders and just as much time on chatGPT and I got this:

#include <WLED.h>
#include <Encoder.h>

#define USERMOD_ENCODER_PINS “Encoder Pins”

// Flag to enable/disable the encoders
bool encoder1Enabled;
bool encoder2Enabled;

// Definitions of encoder pins (to be assigned by the user)
int encoder1DTPin;
int encoder1CLKPin;

int encoder2DTPin;
int encoder2CLKPin;

// Segments associated with the encoders
int encoder1Segment;
int encoder2Segment;

// Variables for brightness variation for each segment
int varBriOptions = {12, 24, 36, 48};
int varBriSegment0;
int varBriSegment1;

// Digital input pins array
int digitalInputPins = {13, 14, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33}; // Updated list of digital input pins

Encoder encoder1(encoder1DTPin, encoder1CLKPin);
Encoder encoder2(encoder2DTPin, encoder2CLKPin);

void setup() {
loadConfig();
setupUsermodEncoderPins(); // Configure the encoder pins
WLED.begin();
}

void loop() {
static long oldPosition1 = 0;
static long oldPosition2 = 0;

if (encoder1Enabled) {
long newPosition1 = encoder1.read();
if (newPosition1 != oldPosition1) {
if (isSegmentOn(encoder1Segment)) {
setSegment(encoder1Segment, constrain(getSegmentBrightness(encoder1Segment) + (newPosition1 > oldPosition1 ? varBriSegment0 : -varBriSegment0), 25, 255), 0, 0);
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
}
oldPosition1 = newPosition1;
}
}

if (encoder2Enabled) {
long newPosition2 = encoder2.read();
if (newPosition2 != oldPosition2) {
if (isSegmentOn(encoder2Segment)) {
setSegment(encoder2Segment, constrain(getSegmentBrightness(encoder2Segment) + (newPosition2 > oldPosition2 ? varBriSegment1 : -varBriSegment1), 25, 255), 0, 0);
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
}
oldPosition2 = newPosition2;
}
}

WLED.loop();
delay(2); // Set the delay to 2 milliseconds
}

void setupUsermodEncoderPins() {
// Group for Encoder 1
usermodAddVariableGroup(USERMOD_ENCODER_PINS, “Settings for Encoder 1”);

usermodAddVariableCheckbox(USERMOD_ENCODER_PINS, “Enable Encoder 1”, &encoder1Enabled);
if (encoder1Enabled) {
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “DT Pin”, &encoder1DTPin, digitalInputPins);
removeAssignedPin(encoder1DTPin, digitalInputPins);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “CLK Pin”, &encoder1CLKPin, digitalInputPins);
removeAssignedPin(encoder1CLKPin, digitalInputPins);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “Assigned Segment”, &encoder1Segment, wledSegmentNames);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “Fade Amount”, &varBriSegment0, varBriOptions);
}

// Group for Encoder 2
usermodAddVariableGroup(USERMOD_ENCODER_PINS, “Settings for Encoder 2”);

usermodAddVariableCheckbox(USERMOD_ENCODER_PINS, “Enable Encoder 2”, &encoder2Enabled);
if (encoder2Enabled) {
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “DT Pin”, &encoder2DTPin, digitalInputPins);
removeAssignedPin(encoder2DTPin, digitalInputPins);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “CLK Pin”, &encoder2CLKPin, digitalInputPins);
removeAssignedPin(encoder2CLKPin, digitalInputPins);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “Assigned Segment”, &encoder2Segment, wledSegmentNames);
usermodAddVariableDropdown(USERMOD_ENCODER_PINS, “Fade Amount”, &varBriSegment1, varBriOptions);
}
}

void removeAssignedPin(int pinToRemove, int pinsArray) {
for (int i = 0; i < sizeof(pinsArray) / sizeof(pinsArray[0]); i++) {
if (pinsArray[i] == pinToRemove) {
pinsArray[i] = -1; // Mark the pin as removed
break;
}
}
}

bool isSegmentOn(int segment) {
return (WLED.segments[segment].mode != “off”);
}

Do you have opinions, comments, changes?

You already guessed it. You would need a custom usermod.
AFAIK nobody needed two rotary encoders until now so you are on your own.

My best advice (as I am not writing such thing) is to use existing usermod and duplicate relevant code for handling each rotary encoder separately.
You will need to think of something if you also want to utilise OLED display, if not, you can just delete that code.

Oh! And BTW, don’t use ChatGPT unless you want a lesson in frustration. :wink:

1 Like