Robotics-II-Circuit-Python

Circuit Python tutorials in Robotics II

View the Project on GitHub MrPrattASH/Robotics-II-Circuit-Python

Table of Contents

Creating a Simple Timer Using CircuitPython

This tutorial will guide you through creating a simple timer in CircuitPython using the Timer module. We will create a basic timer functionality that runs for a specific period (like 10 seconds) before notifying the user that the time has elapsed.

Libraries

Ensure you have the timer.py file on your CIRCUIT.PY lib folder.


Code

import time
from timer import Timer

# Create an instance of the Timer
timer = Timer()

# Setting a timer for 10 seconds
timer.set_timer(time.monotonic(), time.monotonic() + 10)

# Continuously checks if the timer has ended
while True:
    # Check the timer status
    timer_end = timer.check_timer()
    
    # Provide feedback based on the timer status
    if timer_end:
        print("Timer reached!")
        break
    else:
        print("Timer still running")
    
    # Wait half a second before checking again
    time.sleep(0.5)

Code Breakdown

Experiment

Try changing the timer.set_timer()’s second argument to see how the duration affects the output timing. For example, change time.monotonic() + 10 to time.monotonic() + 5 for a shorter duration. “””


Initializing Multiple Non-Breaking Timers

We can also have multiple timers created with multiple instances. Let’s assume we have a robot with x2 continuous servo actuators.

...
intake_timer = Timer()
catapult_timer = Timer()

intake_timer.set_timer(time.monotonic(), time.monotonic()+2)
catapult_timer.set_timer(time.monotonic(), time.monotonic()+4)

while True:
    intake_end = intake_timer.check_timer()
    catapult_end = catapult_timer.check_timer()

    if intake_end:
        print("Intake done!")
    else:
        print("intake still running!")
    
    if catapult_end:
        print("catapult done!")
    else:
        print("catapult still running!")


Experiment

Now you try. Create multiple timers, 1 for a door that runs for 5 seconds, and another for an elevator that runs for 8 seconds.


Restarting timers

You can also restart timers throughout the while true loop. Let’s assume you have a 2 second timer, and every time you flick the switch on your RC reciever on channel 5, you restart the timer.

feeder_timer = Timer()
feeder_timer_end = false

while True:
    now = time.monotonic() #get current time
    ch5 = rc.read_channel(5)
    feeder_timer_end = feeder_timer.check_timer()

    if ch5 == 1:
        feeder_timer.set_timer(now, now + 2) # start a 2 second timer
        print("reset timer!")
    else:
        if feeder_timer_end:
            print("Timer done!")

Experiment

Create x2 timers.


Servo Sweep Timers

Sometimes you’ll find it useful to set up a timer for a servo sweep, so as to not interupt the rest of your code. The following code below assumes we have a robot that:

Robot Goal: If an object gets within 10cm of the robot, the forklift should lift up, else, the forklift should return to rest (angle 0).

See if you can see the problem with this code:


while True:
    distance = distance_sensor.get_distance(prev_distance)
    throttle = rc.read_channel(1)
    spin = rc.read_channel(2)
    
    if distance < 10: #lift up arm if we get too close
        for i in range(0,90,5):
            forklift.angle = i
            time.sleep(0.5) 
    else: #return the arm to rest
        forklift.angle = 0

    drive.drive(spin, throttle) # call drive motors

    prev_distance = distance
    time.sleep(0.2) # small sleep to stay in time with RC flysky controller
    

This program want’s to read distance every loop. As you can see, when our distance is <10cm, the code inside our for loop activates, and this causes our code to pause for 9 full seconds! (18 steps in the loop at 0.5 seconds each). This means that our robot’s drive motors will remember their last command, and we won’t be able to drive for a full 9 seconds! Obviously not ideal. Let’s correct this using our non-breaking timer.

Experiemnt

See if you can find a solution first, then take a look at my example.

My solution is below.

hint #1

# I've used the following timers and variables to keep track of my loop

forklift_timer = Timer() # track the full sweep loop time
sweep_timer = Timer() # track individual sweep steps

forklift_sweep_end_angle = 90 # last number in our for loop
forklift_sweep_step = 5 # step value from for loop
forklift_sweep_sleep = 0.5 # sleep value in each loop iteration
forklift_sweep_full_timer = (forklift_sweep_end_angle / forklift_sweep_step) * forklift_sweep_sleep # total time needed for a sweep to complete

forklift_angle = 0 # initial angle

forklift_start = False # boolean to track if our loop has started
hint #2

# Here;s the start of my while true loop 
while True: 
    now = time.monotonic()
    distance = distance_sensor.get_distance(prev_distance)
    throttle = rc.read_channel(1)
    spin = rc.read_channel(2)

    if distance < 10 and not forklift_start: #lift up arm if we get too close
        forklift_start = True
        forklift_timer.set_timer(now, now + forklift_sweep_full_timer)
        sweep_timer.set_timer(now, now + forklift_sweep_step)
    else: #return the arm to rest
        forklift_angle = 0
        forklift_start = False
    
    if forklift_start:
        # what would you do here? 
Click to reveal my solution

# Use arithmetic operators for changing values and shorthand for assignments such as += and -=.