is is.clock real time or CPU time? I need elapsed subsecond timing

I’d like to have an event happening every 1/4 second. os.time turns over once a second. os.clock is subsecond but is described as “CPU time”. Is it that, or is it elapsed time? If it’s CPU time, is the a way to get wall clock fractional seconds?

Thanks!

@RonJeffries Use tween delay to execute a function every .25 seconds.

viewer.mode=STANDARD

function setup() 
    start=true
    count=0
end

function draw()
    background(0)
    if start then
        start=false
        count=count+1
        tween.delay(.25,run)
    end
end

function run()
    print(count)
    start=true
end

@dave1707 That’s not 1/4s on the wall clock though. That’s every 1/4s since the program started, and it will also gradually drift as it runs at it has to wait for the next frame before updating.

@RonJeffries If I’ve understood you correctly, here’s some code that I have to achieve that end. It combines os.date(), which is wall time accurate to the second, with ElapsedTime, which is millisecond accurate but counts since the start of the program.

Basically, we try to get an accurate reading on ElapsedTime when os.date() clicks over from one second to the next. This then allows us to use ElapsedTime to calculate the current millisecond reading and thus provide an accurate timestamp.

The difficulty is that we can only examine our “clocks” each frame. This makes it complicated as we can’t tell exactly when os.date() clicks over from one second to the next.

I actually wrote this up for the Big Lockdown Math-Off (scroll down half way, also ignore the results of the vote!).

Here’s the code. We want to note the exact ElapsedTime when os.date() ticks over from one second to the next. All we can actually say is that it happened between one frame and the next which gives us an upper and lower limit on the millisecond reading. By continually readjusting, we can zero in on the actual reading.

Here’s some code:

local __l = 0
local __h = 1
local __psec
local __pet

function Now()
  local t = os.date("*t")
  local et = ElapsedTime
  if __psec ~= nil and t.sec ~= __psec then
    local a,b = __pet - math.floor(__pet), et - math.floor(__pet)
    if b - a < .5 then
        if __l + 1 < b then
          a,b = a-1, b-1
        end
        __l = math.max(__l,a)
        __h = math.max(__h,b)
    end
  end
  lower = __l
  higher = __h
  __pet = et
  __psec = t.sec
  et = et - (__l + __h)/2
  local time = {}
  time.msec = (et - math.floor(et))*1000
  time.sec = t.sec
  time.min = t.min
  time.hour = t.hour
  time.yday = t.yday
  return time
end

@LoopSpace Looking at the first post, @RonJeffries didn’t say how exact he wanted it to be over a long of a period of time. That’s why I just chose tween delay. If it needs to be almost exact over a long period (according to the wall clock), I think this code will work. It uses the socket “gettime” function which I think is pretty accurate to several decimal places.

The time interval can be changed in the call to checkDuration(). This code prints the gettime every .25 seconds.

viewer.mode=STANDARD

function setup() 
    s=require("socket")
    st=s:gettime()
    c=0
end

function draw()
    background(0)
    checkDuration(.25)
end

function checkDuration(d)
    local i=s:gettime()-st
    if i>c then
        c=c+d
        xx()
    end
end

function xx()
    print(s:gettime())
end

and i completely forgot ElapsedTime, which really ought to be mentioned in the time tab of the docs. :smiley:

@LoopSpace neat … far more than i needed. and res, @dave1707, maybe tween delay will be better. thanks for reminder. i think my head was empty today.

ElapsedTime isn’t that reliable if the FPS starts to drop. Here’s an example. Slide the slider and see what happens to the ElapsedTime that’s displayed.

viewer.mode=STANDARD

function setup() 
    parameter.integer("delay",1,10000)
    
end

function draw()
    background(0)
    for z=1,delay*10000 do
        a=math.sqrt(z)
    end
    text(ElapsedTime,WIDTH/2,HEIGHT/2)
end

hm, weird. tweens are easy enough, i guess i’ll go that way.

Here’s an example of executing different functions at different time intervals.

viewer.mode=STANDARD

function setup()
    t1=checkDelay(.3)
    t2=checkDelay(.5)
    t3=checkDelay(1)
end

function draw()
    background(0)
    if t1:test() then
        print(".3   ",t1.s:gettime())
    end
    if t2:test() then
        print(".5   ",t2.s:gettime())
    end
    if t3:test() then
        print("1.0  ",t3.s:gettime())
    end
end

checkDelay=class()

function checkDelay:init(int)
    self.s=require("socket")
    self.start=self.s:gettime()
    self.val=0
    self.interval=int    
end

function checkDelay:test()
    if self.s:gettime()-self.start>self.val then
        self.val=self.val+self.interval
        return true
    end
    return false
end