Timers
Two things at once, remembered ticks, timeouts.
Do this lesson in the simulator"Blink the LED while driving to the zone." Two waits cannot do that: wait(0.5) for the blink stops the driving loop. In a behaviour, nothing waits except the tick. Time is counted, not waited for.
Two things at once
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
ticks = 0
on = False
while position()[1] < 70:
# drive forward at 60 (keeps going until the next command)
forward(60)
# every 5 ticks = every half second
if ticks % 5 == 0:
on = not on
led("green" if on else "off")
ticks += 1
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
# the LED: off
led("off")
print("arrived after", ticks, "ticks =", ticks / 10, "seconds")
The driving happens every tick. The blink happens on every fifth tick. on = not on flips a True to False and back: a toggle.
A timer is a remembered tick
To do something a fixed time after an event, remember the tick the event happened on:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
ticks = 0
started_turning = None
while position()[1] < 60:
if started_turning is None:
# drive forward at 60 (keeps going until the next command)
forward(60)
# after two seconds, start a turn
if ticks == 20:
started_turning = ticks
else:
# spin clockwise on the spot at 50
turn_right(50)
# turn for one second, then stop turning
if ticks - started_turning >= 10:
started_turning = None
print("turned at tick", ticks, "now facing", round(heading()))
ticks += 1
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
ticks - started_turning is the time since the event. None means "no timer running". This pattern, an event tick and a duration, is inside every "do X for N seconds" a robot ever does, without a single blocking wait.
There is also a real clock: clock() returns the seconds since the program started. clock() - started_at >= 1.0 reads better than counting ticks, and it stays right if a tick takes longer than planned. Ticks are still worth understanding, because that is what the clock is made of.
Timeouts
The most important timer is the one that gives up. A search that never finds its tag should stop searching after a while, not spin forever:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# camera: the tag detector
set_cv("apriltag")
ticks = 0
found = False
# give it three seconds
while ticks < 30:
if apriltags():
found = True
# leave the loop
break
# spin clockwise on the spot at 40
turn_right(40)
ticks += 1
# pause 0.1 s (the robot keeps doing what it was told)
wait(0.1)
# all motors off
stop()
print("found a tag" if found else "gave up after 3 seconds: no tags on this mat")
Task: blink and drive
Drive into the green zone while the LED blinks green and off every half second, at least eight changes.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
# the LED: green
led("green")
# drive forward at 60 for 70 cm, then stop
forward(60, distance=70)
# the LED: off
led("off")
Challenges
- Blink faster as the robot gets closer to the zone.
- Drive for two seconds, stop for one, repeat, using one timer variable.
- Print the total run time in seconds at the end from the tick count. Check it against the telemetry.