• I understand most watch faces do something like

    setInterval(drawSeconds, 1E3);
    

    to show the seconds and there is a queueDraw in some.

    I still don't get how to syncronize seconds and minutes - and using setInterval is a bit laggy.
    Example:
    When I set the interval to 1 second it will be executed sometime between the beginning and ending of the second. How can I execute just at the beginning of the second of the internal clock? Is there some kind of trigger for that?

  • Several clock use something like 1000 - (Date.now() % 1000) to calculate the time to wait for the next full second.
    You should be able to do something like

    setTimeout(()=>{
      setInterval(draw, 1000);
    }, 1000 - (Date.now() % 1000));
    

    to get somewhat precise second long intervals starting on the next full second according to internal Bangle time.

  • You could use the new ClockFace library and avoid low-level boilerplate :)

  • That's only accurate for first draw. It's better to use this at end of each draw so that every draw will be accurate:

    setTimeout(()=>{
      draw();
    }, 1000 - (Date.now() % 1000));
    
  • That's only accurate for first draw

    ... is it though? Because setInterval should be pretty reliable irrespective of how long the function takes to execute

  • Well,

    I usually prefer a construction like

    var Interval = 1000;
    setTimeout(()=>{
      draw();
    }, Interval - (Date.now() % Interval));
    

    if

    • (calculation and) drawing may take longer than 1000ms (should be
      rare) or
    • the Interval may change dynamically (e.g. depending on screen lock)

    But, most often, a simple setInterval should be sufficient.

  • hmm, how setInterval works if watch time is changed with setTime while setInterval is going?

  • No,

    do not mix both approaches! Either use setTimeout as shown above or start a new setInterval whenever your drawing period changes:

    var TimerId = setInterval(draw,1000)
    ...
    clearInterval(TimerId)
    TimerId = setInterval(draw,60000)
    
  • Is there any difference regarding battery consumption in these approaches?

  • I don't think so

    If you change intervals seldomly, setInterval may consume a little less power - but compared to what you need for drawing your screen contents, you should never be able to recognize the difference.

  • I've experimented with that the past days and looking at examples using timeout came up with the dynamically reconfigurable timeout that has been working fine for me, logging draw calls in the console and comparing with a stopwatch it's always triggering at the right time.

    https://github.com/espruino/BangleApps/blob/master/apps/2ofthemclk/app.js

  • Some experiments on timeouts and intervals:
    https://gist.github.com/halemmerich/c375d51646ee0a1036d76be810acfe6f

    This does the timeout and the interval method and calculates some metrics. The most important for me is the sum, which is the summed up errors against the expected triggering time.

    This results in

    setTimeout
    Min -0.11596679687
    Max 0.1708984375
    Mean -1.98157337024
    Sum 18.408203125
    SD 1.73718663338
    setInterval
    Min -0.0244140625
    Max -0.31127929687
    Mean -2.17123413085
    Sum -171.23413085937
    SD 1.73305703021
    

    This seems to hint to the timeout method accumulating only a tenth of the error the interval does with 100ms waiting time and 1000 tries.

    I would expect the error to get smaller over time with the timeout method.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Understanding how to show seconds and minutes properly

Posted by Avatar for Hank @Hank

Actions