I'm attempting to run a section of code every second, by using an interval and, at the end of the loop, copying the status of the interval to a "last scan" bit. I run a for-next loop based on if the interval status is high and the last scan bit is low.. I'm pretty sure this will work, it's how I would do it in PLC ladder logic, anyway....
I begin with a "LJ.IntervalConfig(0, 1000)" and then begin the program loop "while true do..." Immediately after I begin the program loop, I stuck a debug print line in to read the status of the interval, and the state of the last scan bit "print (LJ.CheckInterval(0), IntLS)". For the value of LJ.CheckInterval(0), it's returning "nil" -- I'm getting repetative "nil 0.000000" in the debug window. According to the site, it will "Returns: nil if no intervals have elapsed." My question is, why will no intervals elapse? I'm fairly sure I'm setting up the interval as stated in the example:
LJ.IntervalConfig(0, 1000)
while true do
if LJ.CheckInterval(0) then
--Code to run once per second here.
end
end
I pasted my code below but the area of concern I highlighted in red text. I'm fairly certain I can debug the rest of my code once I get past this.
print("Photoeye Second Counter")
-- Assign Inputs and Outputs
-- BCN1 = 2008 Beacons 1 through 5 EIO0-5
-- BCN2 = 2009
-- BCN3 = 2010
-- BCN4 = 2011
-- BCN5 = 2012
-- PBLT1 = 2013 Pushbutton lights 1 through 4 EIO6-8, C1O0
-- PBLT2 = 2014
-- PBLT3 = 2015
-- PBLT4 = 2016
-- PEC1 = 2000 Photoeyes 1 through 5 FIO0-5
-- PEC2 = 2001
-- PEC3 = 2002
-- PEC4 = 2003
-- PEC5 = 2004
-- PB1 = 2005 Pushbuttons 1 through 3 FIO6-8
-- PB2 = 2006
-- PB3 = 2007
-- Vars
local inpin = 0
local outpin = 0
local i = 0 -- For Next Index
local IntLS = 0
-- Full Timer (set full time counter, one second increments)
local time = 5
-- Initialize Counter Array
count = {}
for i=0, 10 do
count[i]=0
end
local diostatus = 0
-- Configure a 1000ms interval
LJ.IntervalConfig(0, 1000)
-- Main program loop
while true do
-- If interval is high, compare to last scan. If last scan was zero then state
-- has changed to high. If it goes high then run for-next loop
print (LJ.CheckInterval(0), IntLS) -- DEBUG PRINT
if (LJ.CheckInterval(0) and (not IntLS))
then
for i=0,4,1 do -- 0 thru 4 for-next loop for five photoeyes
inpin = 2000+i -- Align inputs and outputs to Modbus IO addresses based on FOR-NEXT index.
outpin = 2008+i
instat = (MB.R (inpin, 0)) -- This should re-invert photoeye to show blocked as high. May need to NOT in field
if instat then -- if photoeye is blocked then...
count[i] = count[i] + 1 -- increment photoeye second counter.
end
end
if (count[i] >= time) then -- if seconds is greater than time limit
MB.W(outpin, high) -- ...turn on beacon
print ("PE1 ", MB.R(2000, 0), count[i], MB.R(2008,0)) --DEBUG
end
-- Time Resets based on pushbutton
-- Mezz 1
if not MB.R(2005, 0) then
count[1] = 0
count[2] = 0
end
if not MB.R(2006, 0) then
count[3] = 0
count[4] = 0
end
if not MB.R(2007, 0) then
count[5] = 0
end
--Set Last Scan bit
IntLS = LJ.CheckInterval(0)
print (LJ.CheckInterval(0)) -- DEBUG
end
end -- end program loop
When an interval is read and one or more interval has passed, the elapsed-interval count will be reset.
In your program, either the print statement or the if statement will get the interval elapsed flag. As long as the if statement takes less than one interval to run then the CheckInterval call at the end of the loop will always return nil.
In short, it is important to read the interval only once per loop.
Thank you!
I was missing the part where the interval was reset after reading it. I thought it was fully like a square wave where the code would keep looping when it was high, and I was looking for the change of state. I didn't realize that it would one-shot itself automatically.
I got my code to work as written.
Tell me something, is doing something like this possible (based on one of your example codes)
--EXAMPLE
while true do
if inpin = 1 then
LJ.IntervalConfig(0, 1000)
end
if LJ.CheckInterval(0) then
--Code to run once per second here.
end
end
Code in Red is the change, it would run the interval if an input was true, and reset it and hold it if it goes false.
I'm probably stretching here, but I'm looking for something similar to a Timer On in a PLC. And, taking it further, using a For-Next loop and using multiple timers.
Tell me if I'm asking too much, just looking for a more efficient way then to count seconds by incrementing every second.
There are serveral ways to measure pulse width. Some options: