A few things to note about the Waterfall macro:
1. The macro works for any wave shape, although Saw Down is probably the most practical.
2. The macro takes into account value saturation (where it sticks at 100% or 0%)
3. Some movers are faster than others. The Dimmer may go ON as the head is tilting as fast as it can. There are adjustments available to fine tune the response so the Dimmer stays OFF long enough for the head to move into position.
4. After running the macro, the Dimmers will be out of sync with the Tilt. Click the Tap-Tempo in Show Buddy Active to reset the oscillators (or in DMXIS, save the preset, choose a different preset, then go back to the saved preset).
Code: Select all
#==============================================================================================
# DMXIS Macro
# Waterfall.py (c) RCG, 4/10/2019
# Turns Dimmer ON for downward transition, OFF for stationary
# and up transitions
#
# Select fixtures in Tilt/Dimmer pairs.
# Dimmer is modified accordingly.
# Assumptions:
# 1. BPM and Speed are set slow enough for the fixtures to follow
# 2. Any fixture/channel inversions are set as desired
#==============================================================================================
#----------------------------------------------------------------------------------------------
# Custom Fine Tuning
# Modify these based on type of fixture.
# r: Range of movement. This determines the On/Off point for the fixture.
# Some waveshapes sit at 0% or 100% before they transition. For example, Saw Down with
# a shape of 100. This parameter controls the percent movement value when the light
# turns on. When set to 0.95, the fixture light will go ON at 95% tilt, and OFF at 5%.
# mnshp: Minimum Shape Value. This adjust the minimum ON duration for the fixture light.
# mnst_n: Minimum start point. Some fixtures move faster than others. For example, a scanner
# with a mirror moves more quickly than a moving head. These parameters control time
# to remain off while the fixture moves to the top of the waveform. The higher the
# number, the longer the off time as the fixture transitions. If a fixture is
# already sitting at the top of travel, then no delay is needed.
# Notes for specific types:
# Sine - The higher the shape value, the more the sine will look like a Saw Down
# waveform. The fixture may not be able to follow the abrupt waveform upward
# for transition high shape values. This value compensates for slow upward
# transitions which require no delay vs. fast transitions requiring some
# delay.
#
# Square - The square wave relies on the fixture's finite transition time from top to
# bottom. The downward transition happens at the shape value, then goes back
# up at 1.
#
# Triangle - The triangle type may linearly transition up and down, or may swoop up
# or down depending on the shape value. High or low shape values can
# in prolonged stays at high or low values. Adjusting the 'r' value can
# ensure the light does not stay lit while the fixture is stationary.
#
# Saw Up - The saw up type transitions downward at the end of the waveform. It's like
# the square wave because it relies on the fixture speed to dictate the
# amount of ON time.
#
# Saw Down - The saw down type is probably the most logical choice for this
# application. It follows the waveform downward, then quickly reverts
# back to the top point of travel. Since the upward transition happens
# at start of the waveform, a minimum start time should be set to avoid
# turning the light ON while the fixture is moving upward. The 'r' should
# be set to avoid turning the fixture ON while it is stationary.
#----------------------------------------------------------------------------------------------
print("===================================")
r = 0.98 #-- 0..1 Range of ON movement
mnshp = 0.05 #-- 0..1 Minimum Shape Value. Controls minimum ON time.
mnst_1 = 0.10 #-- 0..1 Minimum Start Sine Type.
mnst_2 = 0.0 #-- 0..1 Minimum Start Square Wave Type.
mnst_3 = 0.10 #-- 0..1 Minimum Start Triangle Type.
mnst_4 = 0.0 #-- 0..1 Minimum Start Saw Up Type.
mnst_5 = 0.10 #-- 0..1 Minimum Start Saw Down Type.
#--------------------------------------------------
# Get the user selected channels
#--------------------------------------------------
sel = GetAllSelCh(False)
nsel = len(sel)
#--------------------------------------------------
# Check user selection
#--------------------------------------------------
if nsel < 2:
Message("Select at least 2 channels")
elif nsel%2 > 0:
Message("Select an even number of channels")
else:
mx = 1.0 #-- maximum waveform value
mn = 0.0 #-- minimum waveform value
for i in range(0, nsel/2):
tch = sel[i*2] #-- Tilt Channel
dch = sel[i*2+1] #-- Dimmer Control Channel
nm = GetChName(tch).lower()
if nm == "tilt" or nm == "rotate":
nm = GetChName(dch).lower()
if nm == "dim" or nm == "dimmer":
mag = GetOscAmount(tch) #-- Oscillation +/- per unit magnitude
bias = float(GetChVal(tch))/255.0 #-- Bias point per unit value 0 = bottom of range 1 = top of range
otyp = GetOscType(tch) #-- Get Osc Type
oshp = GetOscShape(tch) #-- Get Osc Shape
ochs = GetOscChase(tch) #-- Get Osc Chase
#-- OFF Osc Type -------------------------------------------------------------
if otyp == 0:
print ("Osc Typ is OFF for selected fixture %d. No changes made." % (i+1))
else:
#-- Sine Osc Type -------------------------------------------------------------
if otyp == 1:
if oshp < (1 - mnst_1):
mnstr = 0.0
else:
mnstr = oshp - (1 - mnst_1)
sy = __builtins__.min( bias + r*mag, mx)
fy = __builtins__.max( bias - r*mag, mn)
x = (sy-bias)/mag
#-- 15th order approximation of asin(x)
asinx = 6.12683146168e-010+9.87783240580e-001*x-6.43155298791e-008*x*x+7.20086973441e-001*x*x*x+1.10581741541e-006*x*x*x*x-7.05868447545e+000*x*x*x*x*x-7.13154427362e-006*x*x*x*x*x*x+4.00656807560e+001*x*x*x*x*x*x*x+2.18726319233e-005*x*x*x*x*x*x*x*x-1.14049647532e+002*x*x*x*x*x*x*x*x*x-3.43685066853e-005*x*x*x*x*x*x*x*x*x*x+1.72788558895e+002*x*x*x*x*x*x*x*x*x*x*x+2.67183864481e-005*x*x*x*x*x*x*x*x*x*x*x*x-1.32449399902e+002*x*x*x*x*x*x*x*x*x*x*x*x*x-8.14116000307e-006*x*x*x*x*x*x*x*x*x*x*x*x*x*x+4.05067623852e+001*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x
start = oshp*(0.5 - asinx/3.14159)
x = (fy-bias)/mag
#-- 15th order approximation of asin(x)
asinx = 6.12683146168e-010+9.87783240580e-001*x-6.43155298791e-008*x*x+7.20086973441e-001*x*x*x+1.10581741541e-006*x*x*x*x-7.05868447545e+000*x*x*x*x*x-7.13154427362e-006*x*x*x*x*x*x+4.00656807560e+001*x*x*x*x*x*x*x+2.18726319233e-005*x*x*x*x*x*x*x*x-1.14049647532e+002*x*x*x*x*x*x*x*x*x-3.43685066853e-005*x*x*x*x*x*x*x*x*x*x+1.72788558895e+002*x*x*x*x*x*x*x*x*x*x*x+2.67183864481e-005*x*x*x*x*x*x*x*x*x*x*x*x-1.32449399902e+002*x*x*x*x*x*x*x*x*x*x*x*x*x-8.14116000307e-006*x*x*x*x*x*x*x*x*x*x*x*x*x*x+4.05067623852e+001*x*x*x*x*x*x*x*x*x*x*x*x*x*x*x
fin = oshp*(0.5 - asinx/3.14159)
#-- Square Wave Osc Type -------------------------------------------------------------
elif otyp == 2:
mnstr = mnst_2
start = oshp
fin = oshp
#-- Triangle Osc Type -------------------------------------------------------------
elif otyp == 3:
mnstr = mnst_3
sy = __builtins__.min(bias + r*mag, mx)
fy = __builtins__.max(bias - r*mag, mn)
if oshp < 0.5:
n = 7 - 12*oshp
start = 1 - (2**(-(n+1)/n))*( (sy-bias+mag)/mag )**(1/n)
fin = 1 - (2**(-(n+1)/n))*( (fy-bias+mag)/mag )**(1/n)
else:
n = 12*oshp - 5
start = 0.5 + (2**(-(n+1)/n))*( (bias+mag-sy)/mag )**(1/n)
fin = 0.5 + (2**(-(n+1)/n))*( (bias+mag-fy)/mag )**(1/n)
#-- Saw Up Osc Type -------------------------------------------------------------
elif otyp == 4:
mnstr = mnst_4
start = 1
fin = 1
#-- Saw Down Osc Type -------------------------------------------------------------
elif otyp == 5:
mnstr = mnst_5
sy = __builtins__.min(bias + r*mag, mx)
fy = __builtins__.max(bias - r*mag, mn)
if oshp < 0.5:
n = 7 - 12*oshp
start = 1 - ( (sy - bias + mag) / (2*mag) )**(1/n)
fin = 1 - ( (fy - bias + mag) / (2*mag) )**(1/n)
else:
n = 12*oshp - 5
start = ( (bias + mag - sy) / (2*mag) )**(1/n)
fin = ( (bias + mag - fy) / (2*mag) )**(1/n)
start = __builtins__.max(start, mnstr)
shape = __builtins__.max(fin - start, mnshp)
phase = ochs + 1 - start #-- Align start with descent point
if phase > 1.0:
phase -= 1.0
print ("fx=%d mg= %5.3f bi=%5.3f str=%5.3f fin=%5.3f ph=%5.3f shp=%5.3f" % (i+1, mag, bias, start, fin, phase, shape))
SetChVal(dch, 128)
SetOscAmount(dch, 1)
SetOscType(dch, 2)
SetOscSpeed(dch, GetOscSpeed(tch))
SetOscChase(dch, phase)
SetOscShape(dch, shape)
else:
print ("Invalid Dimmer channel for selected fixture %d. No changes made." % (i+1))
else:
print ("Invalid Tilt channel for selected fixture %d. No changes made." % (i+1))