Hello everyone,
I'm trying to control my RGB smartbulbs in my home, with QLC+
I'm writing a simple python script that reads incoming ARTNET packets, and sends the commands to the smartbulb, using their API.
I've got this working, however after much testing, I've found that the smartbulbs can accept commands through their API only once every .035 seconds (~28hz).
Since QLC+ outputs at 50hz, the smartbulb API ignores many of the frames, causing the lights to act a bit erratic (not smooth).
Is there any way to change the artnet output rate in QLC+ without modifying source?
If not, what would be the correct way to do it within the source code?
I'd like to test out a few different rates to see which would be most optimal for the smartbulb's API.
Any insight would be greatly appreciated
Can I change the ARTNET output rate without modifying source?
- mcallegari
- Posts: 4712
- Joined: Sun Apr 12, 2015 9:09 am
- Location: Italy
- Real Name: Massimo Callegari
- Contact:
Hi, the only way I can think of is changing the QLC+ master clock
VERY dangerous thing to do
See 4.5 here https://www.qlcplus.org/docs/html_en_EN ... uning.html
Be warned though: changing master clock means ALL the QLC+ function timings will not be consistent anymore.
VERY dangerous thing to do
See 4.5 here https://www.qlcplus.org/docs/html_en_EN ... uning.html
Be warned though: changing master clock means ALL the QLC+ function timings will not be consistent anymore.
- GGGss
- Posts: 3052
- Joined: Mon Sep 12, 2016 7:15 pm
- Location: Belgium
- Real Name: Fredje Gallon
And what if you buffer incoming Artnet through your python script and deliver it to the API at its own pace?
You could even opt to create a buffer-overrun function, controlling what has to be done with the excess?
You could even opt to create a buffer-overrun function, controlling what has to be done with the excess?
All electric machines work on smoke... when the smoke escapes... they don't work anymore
- sandinak
- Posts: 191
- Joined: Mon Apr 03, 2017 5:40 pm
- Location: Yorktown, VA
- Real Name: Branson Matheson
- Contact:
Agree 100% with GGGss here... I had to do something similar for neopixels to make things work right. Here's an example of that code .. where I basically don't push any updates unless something has changed.. this helped alot with not overloading the update routine. I'd suggest similar ... and you could set a timing variable that will skip an update if < 0.35 seconds. I've done quite a bit with the ola python libraries .. they're easy to work with and very flexible. DM me if you need any help
Code: Select all
from ola.ClientWrapper import ClientWrapper
import board
import neopixel
count = 17
universe = 0
lastpx = []
pixels = neopixel.NeoPixel(board.D18, count, auto_write=False)
def NewData(data):
global lastpx
if (data != lastpx):
for i in range(0, count):
dmx_i=i*3
pixels[i] = data[dmx_i:(dmx_i+3)]
pixels.show()
lastpx=data
def run():
wrapper = ClientWrapper()
client = wrapper.Client()
client.RegisterUniverse(universe, client.REGISTER, NewData)
wrapper.Run()
-
- Posts: 7
- Joined: Wed Feb 03, 2021 2:22 am
- Real Name:
Thank you all so much for the help! Super appreciated!
sandinak, thank you for the example. I am doing exactly the same thing in my script already, to only send to the API if there's a change in value... I do have a neopixel ring that I plan on using for this project as well, so your example will be very handy.
I was thinking sandinak's suggestion of if < 0.35 could be the solution, however if I have a cue that raises one value from 0 to 255 and then stays there, and if by chance that particular artnet packet falls between the 0.35 update window, then the light will stay at 0. It would also cause a problem with strobing (going from 0 to 255 repeatedly)
I guess at this point I'll try editing the master clock, and test QLC+ thoroughly to see if it's stable enough for this.
Thank you for the heads up about the potential issues.
If that doesn't go well, I'll brainstorm possibly coming up with a python function that might overcome the scenario I mentioned above.
will post an update on my progress.
Thanks again everyone!
sandinak, thank you for the example. I am doing exactly the same thing in my script already, to only send to the API if there's a change in value... I do have a neopixel ring that I plan on using for this project as well, so your example will be very handy.
I was thinking sandinak's suggestion of if < 0.35 could be the solution, however if I have a cue that raises one value from 0 to 255 and then stays there, and if by chance that particular artnet packet falls between the 0.35 update window, then the light will stay at 0. It would also cause a problem with strobing (going from 0 to 255 repeatedly)
I guess at this point I'll try editing the master clock, and test QLC+ thoroughly to see if it's stable enough for this.
Thank you for the heads up about the potential issues.
If that doesn't go well, I'll brainstorm possibly coming up with a python function that might overcome the scenario I mentioned above.
will post an update on my progress.
Thanks again everyone!
-
- Posts: 7
- Joined: Wed Feb 03, 2021 2:22 am
- Real Name:
Oh wait actually if < .035 would work!
I just need to check if the last packet was sent to the API or discarded.
If the last packet was discarded then send the new packet, even if the values are the same.
Will give it a shot tonight and post an update.
Thanks much everyone!
I just need to check if the last packet was sent to the API or discarded.
If the last packet was discarded then send the new packet, even if the values are the same.
Will give it a shot tonight and post an update.
Thanks much everyone!
- GGGss
- Posts: 3052
- Joined: Mon Sep 12, 2016 7:15 pm
- Location: Belgium
- Real Name: Fredje Gallon
IMHO you will have to split up the logic, and work asynchronously. Artnet feeding the pile and the API logic eating from the pile. Now when the pile gets too big, you will have to decide what to do with it.
As you mention, mimicking a strobe, with those long latencies, I don't think you will achieve... because it will quickly fill up and overrun the pile... Assume you strobe at s slow 10Hz pace, meaning 100ms x 2 (on off) for 1 channel will fit inside the timeframe. But combining multiple channels will create buffer overruns for sure.
Keep me posted with your success ...
As you mention, mimicking a strobe, with those long latencies, I don't think you will achieve... because it will quickly fill up and overrun the pile... Assume you strobe at s slow 10Hz pace, meaning 100ms x 2 (on off) for 1 channel will fit inside the timeframe. But combining multiple channels will create buffer overruns for sure.
Keep me posted with your success ...
All electric machines work on smoke... when the smoke escapes... they don't work anymore
- sandinak
- Posts: 191
- Joined: Mon Apr 03, 2017 5:40 pm
- Location: Yorktown, VA
- Real Name: Branson Matheson
- Contact:
So .. since ArtNET is *constantly* streaming the data ... if a cue sends a frame that raises a channel value from 0 to 255 ... and if the timing on the current frame was below 0.35 .. then when you process the following frame it would likely be still raised from 0 to 255 and get updated then. Eg .. put your timing check to skip the frame *before* processing for change. What this means in practical terms is a delay somewhere between 0.35 and 0.70 for a frame change in specific instances. For small changes, you likely won't' notice .. but your mileage may vary. If you're strobing so fast you're coming in below 0.35... I don't' see a way to solve that simply. ( and you'd be better to use the strobing function of the fixturewhoman wrote: ↑Fri Feb 05, 2021 12:06 am
I was thinking sandinak's suggestion of if < 0.35 could be the solution, however, if I have a cue that raises one value from 0 to 255 and then stays there, and if by chance that particular Artnet packet falls between the 0.35 update window, then the light will stay at 0. It would also cause a problem with strobing (going from 0 to 255 repeatedly)
You could hold that frame in a temp var that you can apply on the next iteration .. however, what will you do if the following frame has more value skew on the channels .. merge them? Seems like a complex problem if you wanna try to manage every single case. I like GGGss idea of fill/drain .. that might be the best answer .. however, I think you'll still have overrun problems you'll have to handle and decide whether to drop frames. Seems like a lot of work .. depending on your application .. your ROI may not warrant it. Just my 2 cents.