How to wrap angles to dmx for motorized pan & tilt light


I have a pan tilt spot light which has a pan range of 540˚.
The dmx values 0-255 would move the light to one of these angles.

My app has a virtual light has a moved range of 360˚.
Wrapping my virtual angle from 0 to 360 causes a jump / wrap around movement of the robe light.
That makes sense as I am asking it to jump from DMX 169 back to DMX 0.

But how can I take better advantage of the fact that I actually have 540˚ to work with?
How would I make the code to know that I could go to DMX 170 instead of back to 0?

right now I am doing this, but I know it’s not what I need.

temp_angleX = ofWrapDegrees(temp_angleX, -180, 180);
dmx_object.panValue = ofMap(temp_angleX, -270 ,270,0, 255,true);  // pan max 540


i made an addon to write fixture classes, i already addressed those issue for Robe Robin, you could try to extend the addon to include your fixture or just steal some code from it


Thank you, looks like an awesome add-on.

I tried the basic example but noticed no dmx values where sent from the void ofxDmx::update(bool force) even after using manager.update();

I looked at the template example and the already existing fixtures. But I couldn’t see where you set what each specific dmx channels means on a fixture.

I tired the snapshots example but the lights did not move. The snapshots json file does not seem to store position and orientation info.

I am on macOS 10.12.6 with OF 0.10.1 using the standard ofxDMX


the basic example should have dmx disabled, check line 89

    manager.update( false ); // don't send dmx in this example

and change it to :

    manager.update( ); 

other examples should start already with DMX enabled


the example example_head_template could also be interesting to you for making a custom class for the clay paky sharpy, also check the other heads classes for other ofx::fixture::Head examples


thanks for the reply.

I forked your add-on and will see how it goes.
It’s very exciting.



Most moving heads are not designed to receive direct updates in the position in every DMX message. Instead you send the target end position and a speed parameter that you should have in your DMX charts fo your model and let the moving head interpolate the movement, using the closer value to your current value (either 0 or 170 in your example).

Most lighting consoles or software like WYSIWYG calculate an adjust intermediate target and speed during the planned movement several times during the expected effect, but not every frame.

Also I see that you ar using 8 bit resolution in your calculations. While that seems smooth when you see the moving head at close range, the effect can be choppy when the moving head is 10 / 15m away of the target.

Most moving heads allows a different “personalities” (a different arrangement of the channels) that allows you 16 bit precision (using 2 dmx channels) allowing you 65536 steps of rotation. We usually use that mode and do our calculations, and then you use bitwise operations to get the coarse and fine channels for every axis movement in the appropriate scale when transforming the values for DMX.


thanks for all the tips.

Lights are moving and get higher res info too :slight_smile:

I managed to create a custom fixture template for some cheap UKing lights I am using for testing.

I added a circular target demo and noticed that the real lights have the same flip problem I saw with my own code.
I did set the 540˚ pan range too.

Here are videos of what’s on the screen and what’s in the world.
screen video
live video


Sorry, i forgot to say that addressed those issue in the method for making the light follow a target, but when you manually set the angle (without using the target) then they will jump as usual, they will also jump when the available range is not enough. But i can easily add a method like avoidJump( float angle ) to set the angle from 0 to 360 without jumping when possible, and then you could be able to merge the update in your fork.


i’ve added the avoidJump( float angle ) method to the ofx::fixture::Head class, could you try with that? the movement should continue smoothly even if you jump from -180 to 180 and viceversa (just one time).


Will try tonight or in the morning.

But I want to point out that I did use the setTarget() function.
See here:


looking at your video, in the simulation the angle was going to superate the maximum range so it was rebound inside the range, that is normal and it will happen less when the target doesn’t move so much around the head.

On a side note, those addon is still a work in progress, the pan, degree change of colors and transition have been tested in a live show, but the target behavior is still to improve (but i won’t do it until I have another show to do so i’m open to contribution on that).


you are right that we reach the pan max of 270 and then it jumps to -89.

I was hoping the jump would happen after 540˚ motion and not after 360˚.
It’s hard to explain.
I do need the lights to rotate like a search light / watchtower. for about 400˚ and then go back.
I will poke around some more.
Thanks again for you advice.




the DMX let you control 540° so from -270 to 270, you can make it move from -200 to 200 without the target, disable “chase target” (by UI or head.chaseTarget=false ) and then set the pan value to achieve the desired effect


PS: for saving the snapshot, are you using the "one"); method? it won’t save by saving with the GUI


@npisanti your addon is awesome! Thanks for sharing it. :smiley:
I borrowed a pan tilt light and will try it tomorrow. I am very interested in the chase target feature so I will take a deep look at the algorithms there and improve it if I can.


I’ve borrowed the code from here

I tried to hack it for ofxFixture but it still doesn’t work in some head orientations.
In working on the chase target make sure the tilt remain constant, as most of the time you have enough pan range to avoid jumps.

I’m not that good on 3d algebra so your help is really welcomed! =)


nice. I’d let you know how it goes.