Управление освещением
    Презентации
    Технические решения на LogicMachine
    Визуализация
      evika.ru    Технические решения на LogicMachine    Управление DMX освещением при помощи LogicMachine

    Управление DMX освещением при помощи LogicMachine

    Шаг 1 – Подключение библиотеки DMX

    Сначала необходимо подключить библиотеку DMX. Для этого в разделе Скрипты – > Пользовательские библиотеки (Scripts -> User libraries) нажмите  Добавить библиотеку (Add new library) и создайте библиотеку с названием dmx.


    Скопируйте в редактор библиотеки следующий код:

     

    local luadmx = require('luadmx')
    module('DMX', package.seeall)
     
    local DMX = {}
     
    -- default params
    local defaults = {
      -- storage key
      skey = 'dmx_chan_',
      -- RS-485 port
      port = '/dev/RS485-1', 
      -- number of calls per second
      resolution = 10,
      -- total number of channels to use
      channels = 3,
      -- transition time in seconds, does not include DMX transfer time
      transition = 2,
    }
     
    -- value setter
    function set(chan, val, key)
      key = key or defaults.skey
     
      -- validate channel number
      if type(chan) == 'number' and chan >= 1 and chan <= 512 then     
    -- validate channel value     
    if type(val) == 'number' and val >= 0 and val <= 255 then
    storage.set(key .. chan, val)     
    end   
    end 
    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 {}  
     
    -- merge parameters that are set by user   
    for k, v in pairs(defaults) do     
    if not n.params[ k ] then       
    n.params[ k ] = v     
    end   
    end   
    n:reset()   
    return n 
    end 
    function DMX:reset()   
    local err, chan   
     
    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   
     
    -- 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, sec, usec   
     
    if not self.calibrated then     
    sec, usec = os.microtime()   
    end   
     
    self:getvalues()   
     
    -- transition loop   
    for i = 1, self.params.resolution 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     
    -- lower slep time by a small step     
    if os.udifftime(sec, usec) > 1.02 then
          self.sleep = self.sleep - 0.05 / self.params.resolution
        -- calibration ok
        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

    Шаг 2 – Создание DMX обработчика

    Внутри резидентного сценария должен быть размещен DMX обработчик (handler). Значение интервала запуска должно быть выставлено равно «0».

    if not dmxhandler then
      require('user.dmx')
      dmxhandler = DMX.init({
        -- количество каналов для использования
    	channels = 3,
    	-- время мягкого перехода в секундах
        transition = 2,
    	-- название и номер порта RS-485
    	port = '/dev/RS485-2', -- для LM2 используйте port = '/dev/ttyS2'
      })
    end
     
    dmxhandler:run()

    Параметры (таблица)

    • channels (каналы) – (опционально, стандартное значение — 3) количество каналов для использования
    • resolution (разрешение) – (опционально, стандартное значение — 20) количество обновлений DMX в секунду. Большее значение дает более гладкие переходы при большем использовании CPU
    • transition (переход) – (опционально, стандартное значение — 2) время мягкого перехода в секундах
    • port (порт) – (опционально) название и номер порта RS-485.

    Если в dmx handler не выставлены какие-либо значения параметров, то эти значения используются по умолчанию из библиотеки.

    Шаг 3 – Создание резидентного или событийного сценария

    Для того чтобы отправить определенное значение на канал DMX следует воспользоваться следующим кодом:

    DMX.set(channel, value)

    • channel (канал) – значение DMX канала [1..512]
    • value (значение) – значение DMX канала [0..255]

    Пример отправки определенного цвета:
    Следующий пример должен быть размещен внутри резидентного сценария. При каждом срабатывании скрипта, будет получено значение, которое будет отправляться в первый канал.

    -- объявление библиотеки dmx
    require('user.dmx')
     
    -- получение значение события (размерность - 1 байт)
    value = event.getvalue()
     
    -- конвертация [0..100] -> [0..255]
    value = math.floor(value * 2.55)
     
    -- отправление значения в первый канал
    DMX.set(1, value)

    Пример предопределенной сцены:
    Следующий пример должен быть размещен внутри резидентного сценария.
    Длительность проигрывания сцены можно менять через параметр «интервал запуска» скрипта (минимум 1 секунда).
    —код dmx_scenes.lua

    -- объявление библиотеки dmx
    require('user.dmx')
     
    if not scenes then
      -- сцена для 3х каналов
      scenes = {
        { 255, 0, 0 },
        { 0, 255, 0 },
        { 0, 0, 255 },
        { 255, 255, 0 },
        { 0, 255, 255 },
        { 255, 0, 255 },
        { 255, 255, 255 },
       }
      current = 1
    end
     
    -- установить значения текущей сцены
    scene = scenes[ current ]
    for i, v in ipairs(scene) do
       DMX.set(i, v)
    end
     
    -- переключить к следующей сцене
    current = current + 1
    if current > #scenes then
       current = 1
    end

    Пример случайной сцены:
    Следующий пример должен быть размещен внутри резидентного сценария. Длительность проигрывания сцены можно менять через параметр «интервал запуска» скрипта (минимум 1 секунда).
    — код dmx_rand.lua
    -- объявление библиотеки dmx
    require('user.dmx')
     
    -- количество шагов, например 3 шага = { 0, 127, 255 }
    steps = 5
    -- количество каналов
    channels = 3
    -- номер первого канала
    offset = 1
     
    for i = offset, channels do
      v = math.random(0, (steps - 1)) * 255 / (steps - 1)
      DMX.set(i, math.floor(v))
    end




    Copyright © Evika.ru 2017
    All Rights Reserved