Page 1 of 1

Can I change the ARTNET output rate without modifying source?

Posted: Wed Feb 03, 2021 2:29 am
by whoman
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

Re: Can I change the ARTNET output rate without modifying source?

Posted: Wed Feb 03, 2021 7:20 am
by mcallegari
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.

Re: Can I change the ARTNET output rate without modifying source?

Posted: Wed Feb 03, 2021 11:25 am
by GGGss
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?

Re: Can I change the ARTNET output rate without modifying source?

Posted: Wed Feb 03, 2021 12:55 pm
by sandinak
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()
  

Re: Can I change the ARTNET output rate without modifying source?

Posted: Fri Feb 05, 2021 12:06 am
by whoman
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!

Re: Can I change the ARTNET output rate without modifying source?

Posted: Fri Feb 05, 2021 12:32 am
by whoman
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!

Re: Can I change the ARTNET output rate without modifying source?

Posted: Fri Feb 05, 2021 9:14 am
by GGGss
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 ...

Re: Can I change the ARTNET output rate without modifying source?

Posted: Fri Feb 05, 2021 12:11 pm
by sandinak
whoman 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)
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 fixture :)

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.