This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

DMX.set with more options
#1
I'm trying to modify the DMX sample my goal would be to create a set method where I have a parameter for the transition time.
I could use dmxhandler.channels in the resident script and manipulate the target and ticks value, but I don't like this idea.
I would be nicer to have a function within the user.dmx.
What I don't understand is how the data from storage.exec('lset', key, chan - 1, val) gets processed to land in the self.channels, so that I can modify it to pass not only the target value but also a transition time?


Thank's
Christian
Reply
#2
Try this, untested so might not work Smile
Use DMX.settransition to set value and transition time for a given channel.
Code:
local luadmx = require('luadmx')
module('DMX', package.seeall)

local DMX = {}

-- default params
local defaults = {
  -- storage key
  skey = 'dmx_line_1',
  -- RS-485 port
  port = '/dev/RS485',
  -- number of calls per second
  resolution = 20,
  -- total number of channels to use
  channels = 3,
  -- default transition time in seconds, does not include DMX transfer time
  transition = 2,
}

local tsuffix = '_transition'

-- match range
local function range(val, min, max)
  return min <= val and val <= max
end

-- value setter
function set(chan, val, skey)
  skey = skey or defaults.skey
  chan = tonumber(chan) or 0
  val = tonumber(val) or -1

  -- validate channel number and value
  if range(chan, 1, 512) and range(val, 0, 255) then
    storage.exec('lset', skey, chan - 1, val)
  end
end

-- value setter
function settransition(chan, val, tr, skey)
  local tkey
  skey = skey or defaults.skey
  chan = tonumber(chan) or 0
  val = tonumber(val) or -1
  tr = tonumber(val) or -1

  -- validate channel number and value
  if range(chan, 1, 512) and range(val, 0, 255) and range(tr, 0, 255) then
    tkey = skey .. tsuffix
    storage.exec('lset', skey, chan - 1, val)
    storage.exec('lset', tkey, chan - 1, tr)
  end
end

-- value getter
function get(chan, skey)
  local res, val
  skey = skey or defaults.skey
  chan = tonumber(chan) or 0

  -- validate channel number and value
  if chan >= 1 and chan <= 512 then
    res = storage.exec('lrange', skey, chan - 1, chan - 1)
    if type(res) == 'table' then
      val = tonumber(res[ 1 ])
    end
  end

  return val
end

-- DMX init, returns new DMX object
function init(params)
  local n, k, v, _

  -- create metatable and set user parameters
  n = setmetatable({}, { __index = DMX })
  n.params = params or {}

  _, n.conn = pcall(require('redis').connect)

  -- merge parameters that are set by user
  for k, v in pairs(defaults) do
    if n.params[ k ] == nil then
      n.params[ k ] = v
    end
  end

  n:reset()

  return n
end

function DMX:reset()
  local params, skey, tkey, transition, err

  params = self.params
  skey = params.skey
  tkey = skey .. tsuffix
  transition = params.transition

  self.dm, err = luadmx.open(params.port)

  -- error while opening
  if err then
    os.sleep(1)
    error(err)
  end

  -- set channel count
  self.dm:setcount(params.channels)

  -- calculate sleep time
  self.sleep = 1 / params.resolution

  -- reset channel map
  self.channels = {}

  -- empty channel value map
  self.conn:ltrim(skey, 1, 0)
  self.conn:ltrim(tkey, 1, 0)

  -- fill channel map
  for chan = 1, params.channels do
    self.channels[ chan ] = { current = 0, target = 0, ticks = 0 }

    -- turn off by default, set default transition
    self.conn:lpush(skey, 0)
    self.conn:lpush(tkey, transition)
    self.dm:setchannel(chan, 0)
  end
end

-- get new values
function DMX:getvalues()
  local skey, tkey, max, channels, values, transition, val, tr, ticks

  skey = self.params.skey
  tkey = skey .. tsuffix

  max = self.params.channels
  channels = self.channels
  values = self.conn:lrange(skey, 0, max - 1) or {}
  transitions = self.conn:lrange(tkey, 0, max - 1) or {}

  -- check for new values for each channel
  for chan = 1, max do
    val = tonumber(values[ chan ]) or 0
    tr = tonumber(transitions[ chan ]) or 0
    ticks = math.max(1, tr * self.params.resolution)

    -- target value differs, set transcation
    if val ~= channels[ chan ].target then
      channels[ chan ].target = val
      channels[ chan ].delta = (channels[ chan ].target - channels[ chan ].current) / ticks
      channels[ chan ].ticks = ticks
    end
  end
end

-- main loop handler
function DMX:run()
  self:getvalues()

  -- transition loop
  for i = 1, self.params.resolution do
    self:step()
    self.dm:send()
    os.sleep(self.sleep)
  end
end

-- single transition step
function DMX:step()
  local chan, channels, t

  channels = self.channels

  -- transition for each channel
  for chan = 1, self.params.channels do
    t = channels[ chan ].ticks

    -- transition is active
    if t > 0 then
      t = t - 1

      channels[ chan ].current = channels[ chan ].target - channels[ chan ].delta * t
      channels[ chan ].ticks = t

      self.dm:setchannel(chan, channels[ chan ].current)
    end
  end
end
Reply
#3
Thanks a lot, sems to work.
Line 150 should be: ticks = math.max(1, tr * self.params.resolution)
Reply


Forum Jump: