Hello Guest it is May 25, 2025, 07:49:58 AM

Author Topic: run function on periodic basis  (Read 3467 times)

0 Members and 1 Guest are viewing this topic.

run function on periodic basis
« on: September 16, 2024, 12:10:11 AM »
I have the following code that I am trying to run every few seconds (currently set to 1 sec). I have installed this in the PLC Script section, but does not seem to run.

Any thoughts or suggestions as to debug or were to place code to accomplish the task?

-- Define the interval for checking (in seconds)
local interval = 1
local lastExecutionTime = wx.wxGetLocalTime()

-- Function to read Modbus register (HR1)
function ReadModbusRegister()
    local inst = mc.mcGetInstance()
    local hReg = mc.mcRegGetHandle(inst, "modbus0/HR1")
   
    if hReg ~= 0 then
        local regValue = mc.mcRegGetValue(hReg)
        if regValue ~= nil then
            local hWriteReg = mc.mcRegGetHandle(inst, "modbus0/WR1")
            if hWriteReg ~= 0 then
                mc.mcRegSetValue(hWriteReg, regValue)
                mc.mcCntlSetLastError(inst, "Received Modbus HR1 Value: " .. tostring(regValue) .. " and acknowledged in WR1.")
            else
                mc.mcCntlSetLastError(inst, "Failed to get Modbus WR1 register handle.")
            end
            return tonumber(regValue)
        else
            mc.mcCntlSetLastError(inst, "Failed to read value from Modbus HR1.")
            return nil
        end
    else
        mc.mcCntlSetLastError(inst, "Failed to get Modbus HR1 register handle.")
        return nil
    end
end

-- Function to read the flat file and build the mapping
function ReadProgramMappings(filePath)
    local mappings = {}
    local file = io.open(filePath, "r")
   
    if file then
        for line in file:lines() do
            local key, value = line:match("(%d+),%s*(.+)")
            if key and value then
                mappings[tonumber(key)] = value
            end
        end
        file:close()
    else
        local inst = mc.mcGetInstance()
        mc.mcCntlSetLastError(inst, "Failed to open program mapping file: " .. filePath)
    end
   
    return mappings
end

-- Function to load CNC program based on the integer value
function LoadCNCProgram(regValue, mappings)
    local programName = mappings[regValue]
   
    if programName then
        local programDir = "C:/Mach4Hobby/GcodeFiles/"
        local programPath = programDir .. programName
       
        local file = io.open(programPath, "r")
        if file then
            file:close()
            local inst = mc.mcGetInstance()
            mc.mcCntlLoadGcodeFile(inst, programPath)
            mc.mcCntlEnable(inst, 1)
            mc.mcCntlCycleStart(inst)
            mc.mcCntlSetLastError(inst, "Loaded CNC program: " .. programPath)
        else
            local inst = mc.mcGetInstance()
            mc.mcCntlSetLastError(inst, "CNC program not found: " .. programPath)
        end
    else
        local inst = mc.mcGetInstance()
        mc.mcCntlSetLastError(inst, "No program found for register value: " .. tostring(regValue))
    end
end

-- PLC Script Function
function PLC_Script()
    local currentTime = wx.wxGetLocalTime()

    -- Run the check if enough time has passed
    if (currentTime - lastExecutionTime) >= interval then
        lastExecutionTime = currentTime
        CheckAndLoadCNCProgram()
    end
end

-- Function to be executed periodically
function CheckAndLoadCNCProgram()
    local inst = mc.mcGetInstance()
    local mappingFilePath = "C:/Mach4Hobby/GcodeFiles/program_mappings.txt"  -- Update this path to your flat file
    local programMappings = ReadProgramMappings(mappingFilePath)
    local regValue = ReadModbusRegister()
   
    if regValue then
        LoadCNCProgram(regValue, programMappings)
    else
        mc.mcCntlSetLastError(inst, "Invalid or no register value received.")
    end
end
Re: run function on periodic basis
« Reply #1 on: September 23, 2024, 08:03:56 PM »
Hi,
I see you have defined two variables as local:

Code: [Select]
local interval = 1
local lastExecutionTime = wx.wxGetLocalTime()

and yet you have not used them until much later in the script. I would have thought they need to be global variables.

When you specify local it means the variable is stored on a stack....and when the function in which that stack is valid goes out of scope then the stack is garbage collected
and any data in the stack is lost.

If you want to use these variables as globals...then set them up as registers OR use them as locals but within the PLC_Script function.

Craig
'I enjoy sex at 73.....I live at 71 so its not too far to walk.'