Impressive title - hope the content lives up to it.
I have discovered that Timers appear to be quite inaccurate in B4I - on my iPhone 4S I am observing elapsed times to timeout being of the order of 10% more than the assigned Interval.
In most situations that would not matter, however in my particular app it creates an unprofessional appearance (at least to a perfectionist).
Searching the community with "timer accuracy" reveals it is a well known phenomenon - although nearly all the hits are B4A.
In this thread:
https://www.b4x.com/android/forum/threads/timer-in-microseconds.21938/#post-158521
At post #5
This is a B4A thread and I'm assuming the same applies to B4I (someone correct me if I am wrong).
This explains the source of the inaccuracy and also implies it has some volatility.
In the same thread, at post #6, Informatix posits a solution around "busy loops" - ultimately involving DoEvents - no DoEvents in B4I so that's not going to work.
In this thread (again B4A):
https://www.b4x.com/android/forum/threads/countdown-accuracy.25771/#post-149310
Erel suggests a scheme involving a short fuse timer (100 msec) and checking against the system clock - which looks like it would give accuracies of the order of 100 msec or better but at (I suspect) a considerable amount of cycle chewing (again, correct me if I am wrong).
-------------------------------------------------------------
I have managed to come up with a class that wraps the B4I timer object and dynamically adjusts the timer interval to drive down inaccuracy to typically less than 1% (after a cycle or 2) and involves no real increase in resource consumption.
It is also essentially a drop-in replacement for the B4I timer object...
Change:
to:
and you are done.
-------------------------------------------------------------
The attached zip file has the class wrapped in a B4I test rig which allows you to test up to 3 timers simultaneously:

-------------------------------------------------------------
The class header documentation pretty well explains the intent:
And the documentation of the Initialization method of the class describes the parameters that need to be passed:
-------------------------------------------------------------
This solution seems pretty fundamental - I am a bit worried that I may be missing something basic that renders it a no-go - all comments are welcome.
I haven't tried it, but from what I can see this class should be able to be dropped in B4A without change. It may well be unnecessary - B4A may not exhibit the magnitude of errors that B4I seems to.
Happy coding...
=================================================
UPDATES - the zip in this post has been replaced on several occasions:
23 Feb 16 - improved interval adjustment algorithm - seems to correct inaccuracies better and more rapidly and added simple filter to control rare extreme corrections in short fuse timers (e.g. 500 milliseconds).
24 Feb 16 - fixed bug in Interval setting
I have discovered that Timers appear to be quite inaccurate in B4I - on my iPhone 4S I am observing elapsed times to timeout being of the order of 10% more than the assigned Interval.
In most situations that would not matter, however in my particular app it creates an unprofessional appearance (at least to a perfectionist).
Searching the community with "timer accuracy" reveals it is a well known phenomenon - although nearly all the hits are B4A.
In this thread:
https://www.b4x.com/android/forum/threads/timer-in-microseconds.21938/#post-158521
At post #5
Timers work by sending a messages to the message loop. As they are processed by the main thread they cannot be 100% accurate.
This is a B4A thread and I'm assuming the same applies to B4I (someone correct me if I am wrong).
This explains the source of the inaccuracy and also implies it has some volatility.
In the same thread, at post #6, Informatix posits a solution around "busy loops" - ultimately involving DoEvents - no DoEvents in B4I so that's not going to work.
In this thread (again B4A):
https://www.b4x.com/android/forum/threads/countdown-accuracy.25771/#post-149310
Erel suggests a scheme involving a short fuse timer (100 msec) and checking against the system clock - which looks like it would give accuracies of the order of 100 msec or better but at (I suspect) a considerable amount of cycle chewing (again, correct me if I am wrong).
-------------------------------------------------------------
I have managed to come up with a class that wraps the B4I timer object and dynamically adjusts the timer interval to drive down inaccuracy to typically less than 1% (after a cycle or 2) and involves no real increase in resource consumption.
It is also essentially a drop-in replacement for the B4I timer object...
Change:
B4X:
Private xxx as Timer
...
xxx.Initialize("Event_xxx", interval)
to:
B4X:
Private xxx as XTimer
...
xxx.Initialize(Me, "Event_xxx", interval)
and you are done.
-------------------------------------------------------------
The attached zip file has the class wrapped in a B4I test rig which allows you to test up to 3 timers simultaneously:
- Move the sliders to change the timers desired interval.
- Set desired interval to 0 if you want to disable timer.
- Toggle switch ON/OFF to Enable/Disable interval adjusting by XTimer, when OFF XTimer behaves just like B4I Timer.
- Click anywhere on screen to start testing, then click anywhere on the screen to stop.

-------------------------------------------------------------
The class header documentation pretty well explains the intent:
B4X:
'************************************************************************************
'
'This class module wraps Timer object
'
'Features:
'
' o Does a dynamic self calibrating adjustment of Timer object interval to correct
' for inaccuracies in Timer object countdown timeout
'
'Methods:
'
' Initialize
'
'Events:
'
' Tick
'
' Indicates XTimer countdown has timed out
'
'Properties:
'
' Interval - interval (measured in milliseconds)
'
' Enabled - enabled state
'
' Adjust - adjust state (True = will adjust intervals (default), False = it will
' not)
'
'Requirements:
'
' None
'
'Update history:
'
' 21 Feb 16 - 1.0
' 23 Feb 16 - 1.1
' o Improved interval adjustment algorithm - seems to correct inaccuracies
' better and more rapidly
' o Added simple filter to control rare extreme corrections in short fuse
' timers (e.g. 500 milliseconds)
' 24 Feb 16 - 1.2
' o Fixed bug in Interval setting
'
'************************************************************************************
And the documentation of the Initialization method of the class describes the parameters that need to be passed:
B4X:
'************************************************************************************
'
'This procedure gets control when Initialize method is called by parent module
'
'Input parameters are:
'
' XTimer_Parent = pointer to module creating instance of this class
' XTimer_Event_Name = event name stub
' XTimer_Interval = desired interval (milliseconds)
'
'Returns:
'
' None
'
'Notes on this procedure:
'
' o Initializes XTimer
'
'************************************************************************************
This solution seems pretty fundamental - I am a bit worried that I may be missing something basic that renders it a no-go - all comments are welcome.
I haven't tried it, but from what I can see this class should be able to be dropped in B4A without change. It may well be unnecessary - B4A may not exhibit the magnitude of errors that B4I seems to.
Happy coding...
=================================================
UPDATES - the zip in this post has been replaced on several occasions:
23 Feb 16 - improved interval adjustment algorithm - seems to correct inaccuracies better and more rapidly and added simple filter to control rare extreme corrections in short fuse timers (e.g. 500 milliseconds).
24 Feb 16 - fixed bug in Interval setting
Attachments
Last edited: