Synchronizing with Real Time

Simple use of tclab.clock()

The tclab module includes a function clock for synchronizing calculations with real time. clock(period) is an iterator that generates a sequence of equally spaced time steps from zero to period separated by one second intervals. For each step clock returns time since start rounded to the nearest 10th of a second.

[1]:
import tclab

period = 5
for t in tclab.clock(period):
    print(t, "sec.")
0 sec.
1.0 sec.
2.0 sec.
3.0 sec.
4.0 sec.

tclab.clock() is implemented as a Python generator. A consequence of this implementation is that tclab.clock() is ‘blocking’ which limits its use for creating interactive demonstrations. See later sections of this user’s guide for non-blocking alternatives that can be used for interactive demonstrations or GUI’s.

Optional Parameters

step: Clock time step

An optional parameter step specifies a time step different from one second.

[2]:
import tclab

period = 5
step = 2.5
for t in tclab.clock(period, step):
    print(t, "sec.")
0 sec.
2.5 sec.

tol: clock tolerance

There are some considerations when using clock. First, by its nature Python is not a real-time environment. clock makes a best effort to stay in sync with the wall clock but there can be no guarantees. The default behavior of clock is to maintain long-term synchronization with the real time clock.

The tol argument specifies the allowable error on time steps. By default it is 0.5 seconds.

The following cell demonstrates the effect of an intermittent calculation that exceeds the time step specified by step. In this instance, a sleep timeout of 2 seconds occurs at t=2. The default behaviour is to raise an error when desynchronisation occurs.

[3]:
import tclab
import time

period = 5
step = 1

for t in tclab.clock(period, step):
    print(t, "sec.")
    if 1.9 < t < 2.5:
        time.sleep(2)
0 sec.
1.0 sec.
2.0 sec.
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-3-10f7d48b2c2a> in <module>()
      5 step = 1
      6
----> 7 for t in tclab.clock(period, step):
      8     print(t, "sec.")
      9     if 1.9 < t < 2.5:

~/Documents/Development/TCLab/tclab/labtime.py in clock(period, step, tol, adaptive)
    102                            'Step size was {} s, but {:.2f} s elapsed '
    103                            '({:.2f} too long). Consider increasing step.')
--> 104                 raise RuntimeError(message.format(step, elapsed, elapsed-step))
    105         labtime.sleep(step - (labtime.time() - start) % step)
    106         now = labtime.time() - start

RuntimeError: Labtime clock lost synchronization with real time. Step size was 1 s, but 2.01 s elapsed (1.01 too long). Consider increasing step.

We can avoid the error above by specifying a larger value of step as advised, or we can specify a larger value for tol. Note that now time steps are skipped.

[4]:
for t in tclab.clock(period, step, tol=2):
    print(t, "sec.")
    if 1.9 < t < 2.5:
        time.sleep(2)
0 sec.
1.0 sec.
2.0 sec.
5.0 sec.

Using tclab.clock() with TCLab

An important use of the tclab.clock() generator is to implement and test control and estimation algorithms. The following cell shows how the clock generator can be used within the context defined by the Python with statement.

[4]:
import tclab

period = 20
step = 2

with tclab.TCLab() as lab:
    lab.Q1(100)
    lab.Q2(100)

    print("\nSet Heater 1 to {0:f} %".format(lab.Q1()))
    print("Set Heater 2 to {0:f} %\n".format(lab.Q2()))

    sfmt = "   {0:5.1f} sec:   T1 = {1:0.1f} °C    T2 = {2:0.1f} °C"

    for t in tclab.clock(period, step):
        print(sfmt.format(t, lab.T1, lab.T2), flush=True)
Arduino Leonardo connected on port /dev/cu.usbmodemWUAR1 at 115200 baud.
TCLab Firmware 1.3.0 Arduino Leonardo/Micro.

Set Heater 1 to 100.000000 %
Set Heater 2 to 100.000000 %

     0.0 sec:   T1 = 30.9 °C    T2 = 33.1 °C
     2.0 sec:   T1 = 30.9 °C    T2 = 33.5 °C
     4.0 sec:   T1 = 30.9 °C    T2 = 33.1 °C
     6.0 sec:   T1 = 30.6 °C    T2 = 32.2 °C
     8.0 sec:   T1 = 30.9 °C    T2 = 33.1 °C
    10.0 sec:   T1 = 30.9 °C    T2 = 33.1 °C
    12.0 sec:   T1 = 30.9 °C    T2 = 33.5 °C
    14.0 sec:   T1 = 30.9 °C    T2 = 33.8 °C
    16.0 sec:   T1 = 31.2 °C    T2 = 32.8 °C
    18.0 sec:   T1 = 31.2 °C    T2 = 34.4 °C
    20.0 sec:   T1 = 31.5 °C    T2 = 34.8 °C
TCLab disconnected successfully.
[ ]: