I have been developing a setup for DLG/F3K gliders for 2-3 years now, which I posted over on RCGroups. As I added new features to the program, memory issues became ever more prominent, and with the latest update, I finally ran out of memory for good, and had to do something radical to cut down on memory usage. I have found some general solutions that work very well, and I want to share them here.
First of all, I added a "library" of shared code and variables by adding a function script that is run one time only. I found this was a good way to share stuff between different telemetry and function scripts.
Secondly, I created a system for transparently loading code when it is needed and unloading when not needed. Here is that part of the above mentioned "library" function script:
Code: Select all
-- JF F3K Library
-- Timestamp: 2017-11-06
-- Created by Jesper Frickmann
-- Has a few shared functions and variables for telemetry and functions scripts
-- Works together with a small shell script to load and unload program and telemetry scripts.
-- Method for loading and unloading telemetry scripts was provided by Guido ter Horst "l shems"
-- For loading and unloading of programs with the small shell script
local programs = {} -- List of loaded programs
local states = {} -- Program states are used for managing loading and unloading
local locked = false -- Lock to ensure that only one program is loaded at a time
local ST_WAITING = 0 -- Wait and mark other programs before loading
local ST_STANDBY = 1 -- Marked programs are swept; standing by for loading
local ST_LOADED = 2 -- Program loaded but not yet initialized
local ST_RUNNING = 3 -- Program is loaded, initialized, and running
local ST_MARKED = 4 -- Programs are marked inactive and swept if not running
-- Load program or forward run() call to the program
function LdRun(file, event)
if states[file] == nil then
-- First, acquire the lock
if locked then
return
else
locked = true
end
-- Wait and sweep inactive programs before loading
DrawMenu(" Loading . . .", 0, 0)
-- Mark all programs as inactive
for f in pairs(states) do
states[f] = ST_MARKED
end
-- Except this one, which is waiting
states[file] = ST_WAITING
elseif states[file] == ST_WAITING then
-- Sweep inactive programs
for f, st in pairs(states) do
if st == ST_MARKED then
programs[f] = nil
states[f] = nil
end
end
states[file] = ST_STANDBY
return collectgarbage()
elseif states[file] == ST_STANDBY then
-- Load the program
local chunk, err = loadScript(file)
if chunk then
programs[file] = chunk()
states[file] = ST_LOADED
return collectgarbage()
else
err = string.gsub(err, file .. ":", "")
lcd.clear()
lcd.drawText(0, 0, "ERROR loading the script:", SMLSIZE)
lcd.drawText(0, 10, file, SMLSIZE)
lcd.drawText(0, 20, err, SMLSIZE)
end
elseif states[file] == ST_LOADED then
states[file] = ST_RUNNING
locked = false
-- Pass an init() call to the loaded program
if programs[file].init then
return programs[file].init()
end
elseif programs[file].run then
states[file] = ST_RUNNING
-- Pass on the run(event) call to the loaded program
return programs[file].run(event)
end
end -- LdRun()
return {}
Code: Select all
-- JF Autoloader
-- Timestamp: 2017-11-02
-- Created by Jesper Frickmann
-- Telemetry script for automatically loading and unloading telemetry scripts
-- Depends on library functions in FUNCTIONS/JFLib.lua
local myFile = "/SCRIPTS/TELEMETRY/JF-LDG.lua" -- Lua file to be loaded and unloaded
local function run(event)
return LdRun(myFile, event)
end
return {run = run}
Please free to comment and ask questions!
Jesper