Up to now when you’ve wanted CodeBot to do something that takes time, you’ve used this pattern:
do_something() time.sleep(delay) do_something_else() time.sleep(delay) ... etc.
That works okay for doing one thing at a time, but it’s not a good plan for multitasking.
botservices module keeps track of time and monitors all of CodeBot’s sensors.
- You can define callback functions to react to events such as timeouts and sensor changes.
- After that, just turn control over to the event loop and it will call your functions when needed.
Event-Driven code looks different than the sequential code you’ve written so far. But really your code is still
being run one-step-at-a-time just like always. It’s just that the code that calls your callback functions is down
botservices.BotServices.loop, so it seems a bit like magic as your program runs!
2. Turn LED off after a scheduled time¶
botservices to flash an LED on and off.
- The code below shows the basic structure of an event-driven program:
- Define callback functions.
- Register callbacks on events of interest.
- Run the event loop.
Enter the following in CodeSpace and run it on your ‘bot:
from botcore import * from botservices import BotServices bot = BotServices() # ---- Define functions ---- def led_on(): leds.user_num(0, True) def led_off(): leds.user_num(0, False) # ---- Setup events ---- # Call 'led_on' after 1 second timeout bot.on_timeout(led_on, 1000) # Call 'led_off' after 5 second timeout bot.on_timeout(led_off, 5000) # Light LED 7 when about to enter event-loop. leds.user_num(7, True) # Start the event-loop, which will call our "callback functions" bot.loop()
Here’s a timeline of how this program runs:
Define the functions, call
Enter the event loop
|1 sec||BotServices calls
|5 sec||BotServices calls
The program quickly runs through defining the functions and the
Then it then enters the event loop, and never returns! After that,
BotServices is in charge
of “calling back” those functions at the requested times.
4. Sweep LEDs¶
Our experiments with timed events conclude with a cool display on the User LEDs.
- Often you’ll want a repeating timer to call a function over and over while the robot runs.
- This could be to check a sensor,
- or to blink some LEDs,
- or to play the next tone in a musical sequence…
To create a repeating timer, just define a function that registers itself with an
on_timeout() call before it ends.
Try the following code, that sets it up so
next_led() is continuously called on a 100ms time tick:
from botcore import * from botservices import BotServices bot = BotServices() # Global variable to hold current LED number led_num = 0 # Callback function to light up next LED in sequence def next_led(): global led_num # Turn off current LED leds.user_num(led_num, False) # Move to next LED led_num = led_num + 1 if led_num > 7: led_num = 0 # Turn on next LED leds.user_num(led_num, True) # Schedule this event to happen again in 0.1 seconds! bot.on_timeout(next_led, 100) # Turn on first LED and schedule next one! next_led() # Start the event-loop, which will call our "callbacks" bot.loop()
5. Bonus Challenge¶
Can you modify the last program to make the LED move back and forth?
It’s a cool effect adored by movie cyborgs and AI cars!
- Define a new global variable
led_dir = 1
- In your
ifstatement, change direction to
led_dir = -1
- Rather than always adding +1 to your
- Define a new global variable