(Lua) Serial DALI interface

Open Source software contributions and discussions that supplement or extend the Palette / Light Palette software
Post Reply
User avatar
RobertBell
Posts: 2421
Joined: Fri Oct 12, 2007 1:11 pm
Primary Venue / Use: Other
Where I Am: Horizon Control Inc
Location: On the dark side just north of Toronto
Contact:

(Lua) Serial DALI interface

Post by RobertBell » Thu Jun 12, 2008 3:08 pm

If you have an RS232 to DALI interface, the serial commands can be a bit cryptic. This is a very simple show file that just does a DALIInit() on startup to open ports and set a range of fixtures, then loops once a second to do a DALIUpdate(). Save the following code in a file called DALI.lau and put it in the show file directory.

Code: Select all

---------------------------------
--dump the data as hex to stdoout
function hexdump( data )
	for i = 1,string.len(data) do 
		print ( string.format( "%02X ", data:byte(i)))
	end

    print( "\r\n")
end

-----------------------------------------------
-- convert the data to a table of ascii numbers
function bintoascii_d_table( data)
	retval = ""
	t= {}
	for i = 1,string.len(data) do 
		t[i] = string.format( "%d ", data:byte(i))
	end
   return t
end

------------------------
--send data to a ballast
function DALIBallastSend( port, address, command)
	
	grp = ( address   * 2 ) + 1
	out = string.char( 0x20, 0 , 0, 0, grp , command  , bit.bxor(0x20, command, grp))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( port, data )
	
end

------------------------------
--send data to a 1-based group
function DALIGroupSend ( port, group, command )

	
	grp = ( ( group  ) * 2 ) + 0x80 + 1
	out = string.char( 0x20, 0 , 0, 0, grp , command  ,bit.bxor(0x20, command, grp))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( port, data )
		
end

------------------------
--send level to a ballast
function DALIArcPower(address, level)
	
	level = math.floor(level * 2.55)
	level = math.max (level, 0)
	level = math.min(level, 254)
	addr = (address-1)  * 2  -- MQ fixture 1 is DALI ballast 0

	out = string.char( 0xA3, 0 , 0, 0, addr , level, bit.bxor(0xA3, level, addr))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( DALIPort, data )
	
end

function DALIInit(port, startfix, endfix)
	HC.SerialOpen(port,'19200,N,8,1')
	DALIPort = port
	DALIStart = startfix
	DALIEnd = endfix
	DALILights = {}
	for i = startfix, endfix do
		NewLevel = HC.AttributeGetValue(i)
		DALILights[i] = NewLevel 
		DALIArcPower(i,NewLevel)
	end
	HC.Status('DALI setup for fixtures ' .. startfix .. ' to ' .. endfix)
end 

function DALIUpdate()
	for i = DALIStart, DALIEnd do
		NewLevel = HC.AttributeGetValue(i)
		if NewLevel ~= DALILights[i] then
		   DALILights[i]= NewLevel 
		   DALIArcPower(i,NewLevel)
		end
	end
end


-- Load verification-----
HC.Status('DALI functionality loaded')


-- NOTES ----------------------
-- Direct Arc Power Commands (level set for ballasts - what we want)
-- if msb is high sending to a group
-- if msb is low sending to a short address (or ballast)
-- lsb is zero - direct ballast arc control 
-- address 1 bitshitfted by 2 therefore first byte short addres * 2 + 1 
-- second byte 0 to 254 (as msb is off) for level 0 to full (0 for FE)

-- examples:

-- A3 00 00 00 00 00 A3 	send ballast 0 to off
-- A3 00 00 00 00 55 F6 	send ballast 0 to 85 (min)
-- A3 00 00 00 00 FE 5D 	send ballast 0 to 254 (max)

-- A3 00 00 00 02 FE 5F		send ballast 1 to 254 (max)
-- A3 00 00 00 04 FE 59		send ballast 2 to 254 (max)
-- A3 00 00 00 06 FE 5B		send ballast 3 to 254 (max)
-- A3 00 00 00 06 00 A5		send ballast 3 to 0 (min)

-- max for balast 0
--out = string.char( 0x20, 0 , 0, 0,0x81,0x05 ,0xA4) 
--DALIBallastSend( 4, 0, 5)
--DALIGroupSend( 4, 0, 5)

-- min for balast 0
--out = string.char( 0x20, 0 , 0, 0,0x81,0x06 ,0xA7) 
--DALIBallastSend( 4, 0, 6)
--DALIGroupSend( 4, 0, 6)
Attachments
Dali.spf
(34.44 KiB) Downloaded 66 times
Robert Bell - Product Manager - Horizon Control Inc.

User avatar
RobertBell
Posts: 2421
Joined: Fri Oct 12, 2007 1:11 pm
Primary Venue / Use: Other
Where I Am: Horizon Control Inc
Location: On the dark side just north of Toronto
Contact:

Re: (Lua) Serial DALI interface

Post by RobertBell » Thu Jan 08, 2009 11:28 pm

This new script takes advantage of the new HC.AddUserFunctionDescription() so it's visible in the script editor.
You can use the with the Tridonic Dali BM RS232

Code: Select all

--[[
DALI out macros
    Copyright (C) 2007-09  Horizon Control Inc.  --  support @ www.strand-dev.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

This set of macros allows you to control a DALI lighting network (following regular channels in your show)
by sending data out the serial port to the DALA RS232 converter.
--]]
---------------------------------
--dump the data as hex to stdoout
function hexdump( data )
	for i = 1,string.len(data) do 
		print ( string.format( "%02X ", data:byte(i)))
	end

    print( "\r\n")
end

-----------------------------------------------
-- convert the data to a table of ascii numbers
function bintoascii_d_table( data)
	retval = ""
	t= {}
	for i = 1,string.len(data) do 
		t[i] = string.format( "%d ", data:byte(i))
	end
   return t
end

------------------------
--send data to a ballast
function DALIBallastSend( port, address, command)
	
	grp = ( address   * 2 ) + 1
	out = string.char( 0x20, 0 , 0, 0, grp , command  , bit.bxor(0x20, command, grp))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( port, data )
	
end

------------------------------
--send data to a 1-based group
function DALIGroupSend ( port, group, command )

	
	grp = ( ( group  ) * 2 ) + 0x80 + 1
	out = string.char( 0x20, 0 , 0, 0, grp , command  ,bit.bxor(0x20, command, grp))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( port, data )
		
end

------------------------
--send level to a ballast
function DALIArcPower(address, level)
	
	level = math.floor(level * 2.55)
	level = math.max (level, 0)
	level = math.min(level, 254)
	addr = (address-1)  * 2  -- MQ fixture 1 is DALI ballast 0

	out = string.char( 0xA3, 0 , 0, 0, addr , level, bit.bxor(0xA3, level, addr))
	--hexdump(out)
	data = bintoascii_d_table(out)
	HC.SerialWrite( DALIPort, data )
	
end

function DALIInit(port, startfix, endfix)
	HC.SerialOpen(port,'19200,N,8,1')
	DALIPort = port
	DALIStart = startfix
	DALIEnd = endfix
	DALILights = {}
	for i = startfix, endfix do
		NewLevel = HC.AttributeGetValue(i)
		DALILights[i] = NewLevel 
		DALIArcPower(i,NewLevel)
	end
	HC.Status('DALI setup for fixtures ' .. startfix .. ' to ' .. endfix)
end 

function DALIUpdate()
	for i = DALIStart, DALIEnd do
		NewLevel = HC.AttributeGetValue(i)
		if NewLevel ~= DALILights[i] then
		   DALILights[i]= NewLevel 
		   DALIArcPower(i,NewLevel)
		end
	end
end


-- Load verification-----
HC.Status('DALI functionality loaded')
HC.AddUserFunctionDescription('DALIInit(port, startfix, endfix)')
HC.AddUserFunctionDescription('DALIUpdate()')

--[[
NOTES ----------------------
Direct Arc Power Commands (level set for ballasts - what we want)
if msb is high sending to a group
if msb is low sending to a short address (or ballast)
lsb is zero - direct ballast arc control 
address 1 bitshitfted by 2 therefore first byte short addres * 2 + 1 
second byte 0 to 254 (as msb is off) for level 0 to full (0 for FE)
examples:

A3 00 00 00 00 00 A3 	send ballast 0 to off
A3 00 00 00 00 55 F6 	send ballast 0 to 85 (min)
A3 00 00 00 00 FE 5D 	send ballast 0 to 254 (max)

A3 00 00 00 02 FE 5F		send ballast 1 to 254 (max)
A3 00 00 00 04 FE 59		send ballast 2 to 254 (max)
A3 00 00 00 06 FE 5B		send ballast 3 to 254 (max)
A3 00 00 00 06 00 A5		send ballast 3 to 0 (min)

max for balast 0
out = string.char( 0x20, 0 , 0, 0,0x81,0x05 ,0xA4) 
DALIBallastSend( 4, 0, 5)
DALIGroupSend( 4, 0, 5)

min for balast 0
out = string.char( 0x20, 0 , 0, 0,0x81,0x06 ,0xA7) 
DALIBallastSend( 4, 0, 6)
DALIGroupSend( 4, 0, 6)
--]]
Attachments
DALI.spf
Sample show file with Init autorun and monitoring looping cue list
(35.01 KiB) Downloaded 53 times
Robert Bell - Product Manager - Horizon Control Inc.

Post Reply