I know this is called WLED and is made to control lighting, but I think it would be exceptionally easy to add servo control. I myself am a hobby programmer at best, but many moons ago, when I first started getting into this stuff, I had a lowly Arduino Nano and an Ethernet shield. I’ve long since lost the code I wrote, but I took the very basic code I had at the time that was accepting E1.31 signals and turned changed it into servo data instead of outputting WS2811 pulses.
That is to say, I used Vixen (that’s just what I use OK, is it really worse than XLights?) to synchronize some audio and a moving servo just to see if I should even consider doing some DIY animatronics, and it worked. It was pretty simple. In Vixen I just used the Pulse effect to fade from 0 to full bright (or vice versa) for the length of time I needed, then in the Arduino code I just took that data coming in, applied simple math to change the 0 ~ 255 values to 0 ~ 180 degree servo equivalent and send a servo signal out instead of a WS2811 signal.
Has anyone done this already in WLED? If not, could someone point me in the direction of where in the code I might try adding this functionality?
Not seen anyone who has done this on wled but you could abstract from this and make up a device that accepts ws2811 pulses and outputs 3 channels of servo control. Quite like the idea for controlling a lot of servos independently.
Otherwise WLED supports outputting RGB pwm signals so would be a case of altering the frequency and time period of this signal to match what servos expect. Im not really familiar with the WLED codebase but in NpbWrapper.h there is reference to setting up the pins for PWM depending on your board.
Does using the usermod file override existing stuff? The way I’m thinking about doing it, I feel like I’d need to edit the e131.cpp file, and thus begins the examples of how bad I am at programming. When it comes to me programming, I usually start with what I call “hard coding” things, instead of making everything variables; I usually get around to variables, but my brain doesn’t immediately go there.
In relation to what we’re talking about, I’m thinking of starting off with a specific need. That is to say, I’ll just edit the existing code to suite my personal needs. But it would be nice to eventually actually contribute to something for once, so I’d need to generalize it more.
What I think needs to happen is, we arbitrarily assign a specific universe(s) number(s) to be for servo control. Then, when WLED sees that universe, instead of outputting WS2812 (or whatever) PWM, it outputs a servo PWM (and possibly on a different pin). But, I don’t know anything about the e1.31 protocol, so maybe there’s a way to define something in the sequencing software so we don’t need to worry about universes. I know XLights has a Servo effect, but I don’t know how that differs from some other element. Vixen even mentions an Element can be anything, even a servo, but it doesn’t say much more about it; outside of users writing their own code, I haven’t seen many examples or explanations as to how they achieved it.
So, would doing something in the usermod folder possibly override what was already handled by the e131.cpp file? Or, am I just showing off my lack of knowledge?
Not really, mainly because, other than cohesus’ response, I haven’t seen much in the way of directing me to places to even start. I’m sure at some point in the next… 10 years I’ll get around to it ;-).
So, especially now that WLED supports multiple pins/strips, would it be possible to add a strip/LED type of “Servo”? I know I may be speaking simply and overstating the obvious, but this is how I think:
I would think since WLED knows some 13 different specific PWM protocols, or does it just send the e1.31 packet data to the installed libraries (Neopixel or FastLED), that you could include the Servo library, do some simple math to convert 0~255 (LED intensity) into 0~180 (servo degrees), and do a servo.write(packetData).
Am I over simplifying this, is it harder than this? If this is something I could do myself, where in the WLED code would I include a new strip/LED type? Is something in the usermods section able to add a strip/LED type?
Hey I just looked into this and I am surprised that nobody has proposed a solution so far. I would really like to introduce some motion to my wled projects.
At first sight it looks like you could try to change WLED_PWM_FREQ (wherever it is defined) to 50hz and hope it will just work. Maybe do some tests with ledc servo driving first (assuming you are using esp32). It could be also necessary to make some changes to BusPwm in BusManager.h.
50hz will look not pleasant if you are also using pwm on leds. Besides bending the existing pwm towards servos, the proper solution might be a new Bus implementation. You could copy a lot from BusPwm but need to add support in the gui as well. There will be up to five different types of new lights (1-5 Channels) if you use the existing concept. Also there might be problems with the timers (I am not sure if you can attach ledc outputs to different timers).
I have had my first look at the wled codebase only today. Therefore, please correct me if I’m wrong (;
So, I think when I did this many moons ago, this was the code I tested with. Again, my personal needs are using a show controller/DMX (Vixen, XLights, FPP, etc.) to drive my servo. I think the only change I made was to add #include <Servo.h> at the beginning, and add the appropriate definitions to define which pin the servo was on, and then change:
if (DMX.newFrame()) {
for(int i=1; i < DMX_NUM_CHANNELS; i++){
dmx_data[i] = dmx_getDimmer(i);
}
for(int i=0; i < NUM_LEDS; i++) {
leds[i].setRGB( dmx_data[i], 0,0);
}
FastLED.show();
}
Into:
if (DMX.newFrame()) {
for(int i=1; i < DMX_NUM_CHANNELS; i++){
dmx_data[i] = dmx_getDimmer(i);
}
for(int i=0; i < NUM_LEDS; i++) {
leds[i].setRGB( dmx_data[i], 0,0);
}
FastLED.show();
//Let's pretend I know the last "LED" is actually my servo
//convert a 0~255 value to a 0~180 value
leds[NUM_LEDS] = leds[NUM_LEDS]*0.7059
myservo.write(leds[NUM_LEDS])
}
So, my usermod would need to include the servo library, take in the e1.31/DMX data, convert it 180 and instead of calling FastLED (that’s what WLED does, right??), call the servo.write method/function/whatever. Am I barking up the wrong tree here? Has the DMX data been ingested in some other library and I just need convert it before it gets sent to FastLED?