To get the DMX control of the Logic Machine one needs to get two scripts running. The first is a “handler” that needs to be added as a resident script:
-- This software may be used and distributed according to the terms of the -- GNU General Public License version 3, incorporated herein by reference. if not d then d = DMX:init({ channels = 16, transition = 1, }) log('DMX initialized') -- reset custom DMX RGB color settings to "off" (0), comment out if not needed storage.set('DMXrgbred', 0) storage.set('DMXrgbgreen', 0) storage.set('DMXrgbblue', 0) log('Reset RGB colors') end d:run()
and the second are the common functions, that you can just add to the end of the current common functions.
-- This code is copyright of openrb.com -- Open Source but != free DMX = { -- default params defaults = { -- storage key skey = 'dmx_chan_', -- RS-485 port port = '/dev/ttyAPP2', -- number of calls per second resolution = 20, -- total number of channels to use channels = 16, -- transition time in seconds, does not include DMX transfer time transition = 2, }, -- value setter set = function(i, v) -- validate channel number if type(i) == 'number' and i >= 1 and i < = 512 then -- validate channel value if type(v) == 'number' and v >= 0 and v < = 255 then storage.set(DMX.defaults.skey .. i, v) end end end } -- DMX init, returns new DMX object function DMX:init(params) log('starting DMX') require('luadmx') local n = setmetatable({}, { __index = DMX }) local k, v -- set user parameters n.params = params -- copy parameters that are set by user for k, v in pairs(DMX.defaults) do if n.params[ k ] == nil then n.params[ k ] = v end end n:reset() return n end function DMX:reset() local err, chan log('resetting DMX') self.dm, err = luadmx.open(self.params.port) -- error while opening if err then os.sleep(1) error(err) end -- set channel count self.dm:setcount(self.params.channels) -- number of transaction ticks self.ticks = math.max(1, self.params.transition * self.params.resolution) -- calculate sleep time self.sleep = 1 / self.params.resolution -- reset channel map self.channels = {} -- fill channel map for chan = 1, self.params.channels do self.channels[ chan ] = { current = 0, target = 0, ticks = 0 } -- turn off by default storage.set(self.params.skey .. chan, 0) self.dm:setchannel(chan, 0) end end -- get new values function DMX:getvalues() local chan, val --log('getting DMX values') -- check for new values for each channel for chan = 1, self.params.channels do val = storage.get(self.params.skey .. chan) -- target value differs, set transcation if val ~= self.channels[ chan ].target then self.channels[ chan ].target = val self.channels[ chan ].delta = (self.channels[ chan ].target - self.channels[ chan ].current) / self.ticks self.channels[ chan ].ticks = self.ticks end end end -- main loop handler function DMX:run() local i, bs, bm, as, am, delta local res = self.params.resolution if not self.calibrated then bs, bm = os.microtime() end self:getvalues() -- transition loop for i = 1, res do self:step() self.dm:send() -- wait until next step os.sleep(self.sleep) end -- calibrate delay loop to match 1 second if not self.calibrated then as, am = os.microtime() delta = (as - bs) + (am - bm) / 1000000 if delta > 1.05 then self.sleep = self.sleep - math.max(10, self.sleep / res) else self.calibrated = true end end end -- single transition step function DMX:step() local chan, t -- transition for each channel for chan = 1, self.params.channels do t = self.channels[ chan ].ticks -- transition is active if t > 0 then t = t - 1 self.channels[ chan ].current = self.channels[ chan ].target - self.channels[ chan ].delta * t self.channels[ chan ].ticks = t self.dm:setchannel(chan, self.channels[ chan ].current) end end end