Testing Accuracy of micro:bit Internal Clock

At REUK.co.uk we make a lot of timers for a wide range of different applications. Most projects only call for a timer to be accurate to within around 10 seconds per hour. For those that require greater accuracy, we sometimes use a real time clock such as the DS3231, and other times (when the microcontroller we are using is inaccurate but CONSISTENTLY inaccurate) we just calibrate the timer against a previously tested and known accurate timer.

While having a first play around with MicroPython on the micro:bit, we ran a few one minute tests of the accuracy of the internal clock. When hand timing with a stopwatch we consistently found that one micro:bit minute was actually around 59.85 seconds. That is of course very close to the 60.00 seconds of a true minute and the error could well have been due to human error with the stopwatch, but it did appear that our micro:bit was running a little fast (since its ‘minute’ was finishing quicker than a true minute). Being 0.15 seconds fast every minute may not sound a lot, but it equates to the internal clock being minutes fast per day. Had the timing appeared to be a tiny bit slow, it could just have been that there was a delay due to the time taken for the micro:bit to do internal processing etc, but as the timings appeared to be fast, they must actually be fast.

In order to test this properly, we connected a relay via a transistor to one of the digital output pins of the micro:bit. The NO and COM terminals of this relay were in turn connected in parallel across the contacts of the start/stop button on a previously cannibalised stopwatch. We then wrote a small MicroPython script to briefly set the output pin to digital HIGH to start the stop watch, and then after 10 minutes sleep(600000) – i.e. sleep for 600,000 milliseconds, 600 seconds, 10 minutes – again briefly set the pin high to stop the stopwatch.

testing the micro:bit internal clock accuracy

Running this test ten times and averaging the results we found that the micro:bit ten minutes was actually 9 minutes, 58.51 seconds (598.51 seconds instead of 600.00). The timings were very consistent with the shortest and longest measured times both being just 0.03 seconds away from the average – a tight range of 9m58.48s to 9m58.54s measured over the ten ten minute periods.

Looking at the average time, 9 minutes 58.51 seconds is 0.248% faster than 10 minutes. Being 0.248% fast is not a big deal when timing events lasting seconds or a couple of minutes, but over the course of a 24 hour period, our micro:bit would gain 215 seconds, or over 3.5 minutes which is not insignificant.

The consistency we had found in the inaccuracy was a very good sign. It made manual calibration of our micro:bit a possibility so that we would forever know (at least if timing accuracy is not significantly affected by changes in ambient temperature or input voltage) that this particular micro:bit’s clock could be trusted without the need for an external real time clock (RTC).

The Python command we used to get the micro:bit to sleep for one second was sleep(1000). Apparently with our micro:bit this resulted in it sleeping for a little less than one true second, therefore we needed to increase the sleep time by the 0.248% that the internal clock was now known to be fast. It would be nice to use the command sleep(1002.4833), but unfortunately it is only possible to use a whole number (integer) value – i.e. sleep(1002) or sleep(1003). Either of these approximations would make times measured by our micro:bit 5 times more accurate, but that is still around 45 seconds too fast per 24 hours – not good enough.

Therefore, when we want to time long intervals – hours and days – we need to sleep for longer intervals such as sleep(601489.98) corresponding to 10 minutes to increase the accuracy possible. Luckily enough 601489.98 is almost exactly 601490 micro:bit measured milliseconds. So, in any projects which require us to measure long time periods with our micro:bit, we will count the number of our pre-calibrated 10 minute intervals have passed measured with sleep(601490). Now calibrated, our micro:bit should certainly be accurate enough for a wide range of future long duration projects.

The timing accuracy we found for our micro:bit before calibration was 25 ppm (parts per million) which compares favourably with the typical 50 ppm found with Arduino boards, and we found the consistency in timing inaccuracy to be better with micro:bit than we have previously found with Arduino. However, we could have been lucky or unlucky with our particular micro:bit board. We will need to repeat our experimentation with multiple micro:bits to find the typical timing accuracy of micro:bits in general in the future.


Leave a Reply