Skip to content

Flight Simulator Interface Using Lua

For how simple this looks, it was actually a really involved project. The concept was to build a hardware interface for the DCS World flight simulator. To accomplish this feat of pure nerddom, I did the following:

  1. Connected 15 switches to 2x 74HC4051 multiplexers. Covered Here.
  2. Sampled the switch positions using an Arduino 2560 board with an Ethernet Shield. Covered Here.
  3. Passed the switch positions via Ethernet to DCS World’s I/O interface using their Lua framework, which requires the user to write all of the I/O scripting. (See Lua code below)
  4. Added a [thus far] unused stream of parameters to the UDP traffic so that I can build a cockpit display if/when I want. (Also in Lua code)

You might be thinking that I did a lot of extra work to accomplish a small task. There is truth to that, BUT the goal here was to create an easily expandable architecture. You can simply sample switch positions using the I/O pins of the Arduino directly. You can also use the Arduino’s serial USB comm to transmit the data. If you did those things (among other simplifications), you would save a lot of time on the initial build but your problems would grow exponentially when trying to go from 15 switches to something like 200 switches.

local lfs = require('lfs')

local default_output_file = io.open(lfs.writedir().."/Logs/Export.log", "w")
default_output_file:write("DCS Started..\n")

ArdIP = "192.168.1.167"
ArdPort = "8090"
ExportInterval = 1

SwTbl = {}
SwMem = {}

SwTbl["001"] = 1;
SwTbl["002"] = 1;
SwTbl["003"] = 1;
SwTbl["004"] = 1;
SwTbl["005"] = 1;
SwTbl["006"] = 1;
SwTbl["007"] = 1;
SwTbl["008"] = 1;
SwTbl["999"] = 1;



function sleep(n)
	local t = os.clock()
	while os.clock()-t<=n do
	  -- nada
	end
end


frame = 1;

function LuaExportStart()

 	package.path  = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua"
 	package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
 
	local socket = require("socket")

	timestart = socket.gettime()

	udp = socket.udp()
	udp:setsockname("*", 9000)
	udp:setoption('broadcast',true)
	udp:settimeout(.001)
  
	local startwait = true

	udp:sendto("DCS Active",ArdIP,ArdPort)
	
	time = socket.gettime() - timestart
	default_output_file:write(string.format("Time = %6f",time))
	default_output_file:write("  Lua Started\n")

end

function LuaExportBeforeNextFrame()

	--
	-- This part of the code is transported!!!
	-- 
	time = socket.gettime() - timestart
	default_output_file:write(string.format("Time = %6f",time))
	default_output_file:write("  Before Frame"..frame.." - Preparing to receive stream...\n")

	frame = frame + 1

	local SwStream = udp:receive()
	

	if SwStream then
		time = socket.gettime() - timestart
		default_output_file:write(string.format("Time = %6f",time))
		default_output_file:write(string.format("  Stream = %s\n",SwStream))
	
		if string.match(SwStream,'Sw(%d+),(%d+)/') then
		  	switch,val = string.match(SwStream,'Sw(%d+),(%d+)/')
		end
	  
		SwTbl[switch] = val	

	else
		SwStatus = "switches bad"
	end
	
	--Gear
	if SwTbl["001"] == "0" then 
		LoSetCommand(431)
		default_output_file:write(string.format("%s\n","LoSetCommand(431) Sent"))
	elseif  SwTbl["001"] == "1" then
		LoSetCommand(430)
	end

	--Flaps
		if SwTbl["002"] == "1" then
			LoSetCommand(145)
		else
			LoSetCommand(146)
		end


		--Speedbrake
		if SwTbl["003"] == "1" then
			LoSetCommand(147)
		else
			LoSetCommand(148)
		end


		--Fire
		if SwTbl["006"] == "0" then
			--LoSetCommand(350)
		else
			--LoSetCommand(85)
		end

		--Master Arm
		if SwTbl["007"] == "0" then
			LoSetCommand(283)
		else
			LoSetCommand(283)
		end

		--Radar Mode
		if SwTbl["008"] == "0" then
			LoSetCommand(106)
			LoSetCommand(86)
		end
	
end

function LuaExportAfterNextFrame()

	time = socket.gettime() - timestart
	default_output_file:write(string.format("Time = %6f",time))
	default_output_file:write("  After Frame\n")
	
end

function LuaExportStop()

end


function LuaExportActivityNextEvent(t)
	t = t + ExportInterval

	time = socket.gettime() - timestart
	default_output_file:write(string.format("Time = %6f",time))
	default_output_file:write("  Activity of Next Event Call\n")
	

	dataStream = {}
	-- Indicated airspeed
	--
	local KIAS = LoGetIndicatedAirSpeed()
	KIAS = KIAS * 1.94384
	value = string.format("KIAS:%.0f",KIAS) 
	udp:sendto(value,ArdIP,ArdPort)
	--table.insert(dataStream,1,value)
	
	--
	-- Baro alt
	--
	local altBar = LoGetAltitudeAboveSeaLevel()
	altBar = altBar * 3.28
	value = string.format("BarAlt:%.0f",altBar)
	udp:sendto(value,ArdIP,ArdPort)   
	--table.insert(dataStream,2,value)
	
	--
	-- Mag Hdg
	--
	local Hdg = LoGetMagneticYaw()
	Hdg = Hdg*57.2957795
	value = string.format("Heading:%.0f",Hdg)
	udp:sendto(value,ArdIP,ArdPort)
	--table.insert(dataStream,3,value)
	
	--
	-- Sensor Mode
	--
	local SenSubMode = LoGetNavigationInfo()
	value = string.format("%s",SenSubMode.SystemMode.master..":"..SenSubMode.SystemMode.submode)
	udp:sendto(value,ArdIP,ArdPort)
	
	-- 
	-- Radar On?
	--
	local SensorData = LoGetSightingSystemInfo()
	local xmit = tostring(SensorData.radar_on)
	value = string.format("Xmit:%s",xmit)
	udp:sendto(value,ArdIP,ArdPort)


	return t
end

1 thought on “Flight Simulator Interface Using Lua”

Comments are closed.