labjack/labjack-ljm-python

lua script loading fails on some file lengths

Closed this issue · 1 comments

Using the example code for loading a lua script, some scripts fail with this message (file with 1804 bytes)
lua: [string "--[[..."]:70.000000: unexpected symbol near 'char(5.000000)'

where the line number is the last line of the program, and char() changes, sometimes its a printable ascii character.

The failure is inconsistent, as it seems to depend on what bad bytes follow the loaded program in python. In all of my tests, the scripts can randomly succeed, and all lua has been verified in the kipling debugger.

The problem can be fixed two ways:

  1. Adding a null terminator to the loaded script file as in:
script = file.read()
script += '\0'
  1. By adding characters to the lua script, as in replacing MB.W(6000, 1, 0) with MB.W(6000.00, 1, 0)

It's not clear what the root cause is, but it sure looks like a string length problem. This test was performed on Win64 machine.

The loading code is:

        with open(self.filepath, mode="r", encoding="utf-8") as file:
            script = file.read()
            # script = script + '\0'
            scriptLen = len(script)

            ljm.eWriteName(self.handle, "LUA_SOURCE_SIZE", scriptLen)
            ljm.eWriteNameByteArray(self.handle, "LUA_SOURCE_WRITE", scriptLen, script)
            ljm.eWriteName(self.handle, "LUA_DEBUG_ENABLE", 1)
            ljm.eWriteName(self.handle, "LUA_DEBUG_ENABLE_DEFAULT", 1)
            print(f'Script {self.filepath} ({scriptLen} bytes) loaded')

My starting script (without any length manipulation) is

--[[
    Cystal Monitor Test Fixture Lua for Labjack
    
    DUT PS Power Regulator
--]]

MB.writeName("LUA_NO_WARN_TRUNCATION", 1)

-- print("Starting dut ps script")

local DATA_READY_REG = "USER_RAM0_U16"        -- will be 1 when the data is ready

local MV_SETTING_REG = "USER_RAM1_U16"

------------------------
-- Common I2C Configuration and Misc Utilities
------------------------

local I2C_SCL_REG = 3-- FIO4
local I2C_SDA_REG = 4 -- FIO3
local I2C_SPEED = 65516 -- 0,65536 = 450Khz, 1=40Hz, 65516=100kHz
local I2C_OPTIONS = 3 -- resetAtStart*1+noStopAtStarting*2
local I2C_SLAVE_ADDRESS_REG = 5104 -- uint16

function config_i2c_bus(address)
    -- print("Configuring i2c bus")
    I2C.config(I2C_SDA_REG, I2C_SCL_REG, I2C_SPEED, I2C_OPTIONS, address)
end

function sleep_ms(inteval_ms)
    local CheckInterval = LJ.CheckInterval
    LJ.IntervalConfig(1, inteval_ms)
    while not CheckInterval(1) do
    end
end

----------------------------
-- DUT PS
----------------------------
MB.writeName(DATA_READY_REG, 0)

function dut_ps_set_voltage()
    local DUT_PS_REGULATOR_I2C_ADDR = 0x0D
    local DUT_PS_DEFAULT_MV = 4500 -- 750 to 4800
    local DUT_MAX_MV = 4800 -- depends on jig
    local DUT_MIN_MV = 750

    local in_mv = MB.readName(MV_SETTING_REG)
    -- print(string.format("setting dut_ps to %d mv", in_mv))

    local data = (DUT_MAX_MV - in_mv)
    if data > 4095 then data = 4095
    elseif data < 0 then data = 0
    end

    b1 = bit.rshift(bit.band(data, 0xff00), 8)
    b0 = bit.band(data, 0xff)

    -- print(string.format("setting regulator to %02X %02X", b1, b0))

    config_i2c_bus(DUT_PS_REGULATOR_I2C_ADDR)
    I2C.write({b1, b0})

    -- Common Ending Code
    MB.writeName(DATA_READY_REG, 1)
end

dut_ps_set_voltage()
-- print("Stopping script")
MB.W(6000, 1, 0)

We updated our example to use solution 1 already, see 395b108. The Lua interpreter expects to parse the Lua script formatted as a C-string, so a null terminating character is required. The failure to add a null terminating character was an oversight when we initially made the Lua execution control example.