Example Code¶
Feel free to read through, import, and use any of the below sample code:
XRPExamples/drive_examples.py¶
1from XRPLib.defaults import *
2import time
3
4"""
5 By the end of this file students will learn how to control the drivetrain,
6 both by setting effort values directly to the motors and by using go_straight and go_turn
7"""
8
9# drive straight for a set time period (defualt 1 second)
10def drive_straight(drive_time: float = 1):
11 drivetrain.set_effort(0.8, 0.8)
12 time.sleep(drive_time)
13 drivetrain.stop()
14
15# drive at a slight counter clockwise arc for a set time period (default 1 second)
16def arc_turn(turn_time: float = 1):
17 drivetrain.set_effort(0.5, 0.8)
18 time.sleep(turn_time)
19 drivetrain.stop()
20
21# turn CCW at a point for a set time period (default 1 second)
22def point_turn(turn_time: float = 1):
23 drivetrain.set_effort(-0.8, 0.8)
24 time.sleep(turn_time)
25 drivetrain.stop()
26
27# pivot turn around the left wheel for a set time period (default 1 second)
28def swing_turn(turn_time: float = 1):
29 drivetrain.set_effort(0, 0.8)
30 time.sleep(turn_time)
31 drivetrain.stop()
32
33# Driving in a circle by setting a difference in motor efforts
34def circle():
35 while True:
36 drivetrain.set_effort(0.8, 1)
37
38# Follow the perimeter of a square with variable sidelength
39def square(sidelength):
40 for sides in range(4):
41 drivetrain.straight(sidelength, 0.8)
42 drivetrain.turn(90)
43 # Alternatively:
44 # polygon(sidelength, 4)
45
46# Follow the perimeter of an arbitrary polygon with variable side length and number of sides
47# Side length in centimeters
48def polygon(side_length, number_of_sides):
49 for s in range(number_of_sides):
50 drivetrain.straight(side_length)
51 drivetrain.turn(360/number_of_sides)
52
53# A slightly longer example program showing how a robot may follow a simple path
54def test_drive():
55 print("Driving forward 25cm")
56 drivetrain.straight(25, 0.8)
57
58 time.sleep(1)
59
60 print("turn 90 degrees right")
61 drivetrain.turn(90,0.8)
62
63 time.sleep(1)
64
65 print("turn 90 degrees left by setting speed negative")
66 drivetrain.turn(90, -0.8)
67
68 time.sleep(1)
69
70 print("drive backwards 25 cm by setting distance negative")
71 # There is no difference between setting speed or distance negative, both work
72 drivetrain.straight(-25,0.8)
XRPExamples/sensor_examples.py¶
1from XRPLib.defaults import *
2import time
3
4"""
5 By the end of this file students will learn how to read and use data from
6 both the ultrasonic sensors and the line followers.
7 They will also have a chance to learn the basics of proportional control.
8"""
9
10# Polling data from the ultrasonic sensor
11def ultrasonic_test():
12 while True:
13 print(rangefinder.distance())
14 time.sleep(0.1)
15
16# Approaches a wall at a set speed and then stops
17def drive_till_close(target_distance: float = 10.0):
18 speed = 0.6
19 while rangefinder.distance() > target_distance:
20 drivetrain.set_effort(speed, speed)
21 time.sleep(0.01)
22 drivetrain.set_effort(0, 0)
23
24# Maintains a certain distance from the wall using proportional control
25def standoff(target_distance: float = 10.0):
26 KP = 0.2
27 while True:
28 distance = rangefinder.distance()
29 error = distance - target_distance
30 drivetrain.set_effort(error * KP, error*KP)
31 time.sleep(0.01)
32
33# Maintains a certain distance from the wall while driving
34# using proportional control (sensor on right side of robot this time)
35def wall_follow(target_distance: float = 10.0):
36 KP = 0.1
37 base_speed = 0.5
38 while True:
39 distance = rangefinder.distance()
40 error = distance - target_distance
41 print(error)
42 drivetrain.set_effort(base_speed + error * KP, base_speed - error*KP)
43 time.sleep(0.01)
44
45# Follows a line using the line followers
46def line_track():
47 base_effort = 0.6
48 KP = 0.6
49 while True:
50 # You always want to take the difference of the sensors because the raw value isn't always consistent.
51 error = reflectance.get_left() - reflectance.get_right()
52 print(error)
53 drivetrain.set_effort(base_effort - error * KP, base_effort + error * KP)
54 time.sleep(0.01)
55
56# Polling data from the IMU
57def imu_test():
58 while True:
59 print(f"Pitch: {imu.get_pitch()}, Heading: {imu.get_heading()}, Roll: {imu.get_yaw()}, Accelerometer output: {imu.get_acc_rates()}")
60 time.sleep(0.1)
61
62def climb_ramp(ramp_angle, angle_tolerance=3.5):
63 speed = 0.6
64 # Find ramp by driving forward
65 while imu.get_pitch() < ramp_angle-angle_tolerance:
66 drivetrain.set_effort(speed, speed)
67 time.sleep(0.05)
68 # Drive up ramp until angle levels out again
69 while imu.get_pitch() >= ramp_angle-angle_tolerance:
70 drivetrain.set_effort(speed, speed)
71 time.sleep(0.05)
72 # Then stop
73 drivetrain.set_effort(0, 0)
74
75ultrasonic_test()
XRPExamples/led_example.py¶
1from XRPLib.board import Board
2from machine import Timer, Pin
3import time
4
5# Get a reference to the board
6board = Board.get_default_board()
7
8# Create a timer for the RGB LED, assuming it's present on this board
9rgb_led_timer = Timer(-1)
10
11# Conversion from hue to RGB
12def hue_to_rgb(hue):
13 # Initialize RGB values
14 r = 0
15 g = 0
16 b = 0
17
18 # Ensure hue is in range of [0,360)
19 hue %= 360
20
21 if(hue < 120):
22 # Red to green region
23 r = (120 - hue) / 120 * 255
24 g = (hue - 0) / 120 * 255
25 b = 0
26 elif(hue < 240):
27 # Green to blue region
28 hue -= 120
29 r = 0
30 g = (120 - hue) / 120 * 255
31 b = (hue - 0) / 120 * 255
32 else:
33 # Blue to red region
34 hue -= 240
35 r = (hue - 0) / 120 * 255
36 g = 0
37 b = (120 - hue) / 120 * 255
38
39 # Return RGB as tuple of integers in range of [0,255]
40 return (int(r), int(g), int(b))
41
42def update_rgb_led_rainbow(timer):
43 # Set hue based on current time. Hue is an angle up to 360 degrees,
44 # so using the milliseconds divided by 10 creates a rainbow that
45 # repeats every 3.6 seconds
46 hue = time.ticks_ms() / 10
47
48 # Compute RGB values
49 rgb = hue_to_rgb(hue)
50
51 # Max brightness is blinding, so recompute RGB values with 10% brightness
52 brightness = 0.1
53 r = int(rgb[0] * brightness)
54 g = int(rgb[1] * brightness)
55 b = int(rgb[2] * brightness)
56
57 # Set the RGB LED color
58 board.set_rgb_led(r, g, b)
59
60def start_led_demo():
61 # Make the monochrome LED start blinking
62 board.led_blink(1)
63
64 # If this board has an RGB LED, make it start changing colors
65 if hasattr(Pin.board, "BOARD_NEOPIXEL"):
66 # Set up timer to update the RGB LED at 100Hz for smooth color changes
67 rgb_led_timer.init(freq = 100, callback = update_rgb_led_rainbow)
68
69def stop_led_demo():
70 # Make the monochrome LED stop blinking and turn off the LED
71 board.led_blink(0)
72 board.led_off()
73
74 # If this board has an RGB LED, stop the timer and turn off the LED
75 if hasattr(Pin.board, "BOARD_NEOPIXEL"):
76 rgb_led_timer.deinit()
77 board.set_rgb_led(0, 0, 0)
78
79start_led_demo()
XRPExamples/webserver_example.py¶
1from XRPLib.defaults import *
2import time
3from machine import Timer
4
5# Binding functions to the arrow buttons
6webserver.registerForwardButton(lambda: drivetrain.set_effort(0.5, 0.5))
7webserver.registerLeftButton(lambda: drivetrain.set_effort(-0.5, 0.5))
8webserver.registerRightButton(lambda: drivetrain.set_effort(0.5, -0.5))
9webserver.registerBackwardButton(lambda: drivetrain.set_effort(-0.5, -0.5))
10webserver.registerStopButton(lambda: drivetrain.set_effort(0, 0))
11
12# Binding functions to custom buttons
13webserver.add_button("Close Server", lambda: webserver.stop_server())
14webserver.add_button("Blink", lambda: board.led_blink(2))
15webserver.add_button("LED Off", lambda: board.led_off())
16webserver.add_button("Servo Up", lambda: servo_one.set_angle(90))
17webserver.add_button("Servo Down", lambda: servo_one.set_angle(0))
18
19# Logging static data to the webserver
20# webserver.log_data("test", "test")
21# webserver.log_data("List", [1,2,3])
22# webserver.log_data("Dict", {"a":1,"b":2,"c":3})
23# webserver.log_data("Tuple", (1,2,3))
24
25def log_time_and_range():
26 # This function is called every second to update the data on the webserver
27 webserver.log_data("Time", time.time())
28 webserver.log_data("Range", rangefinder.distance())
29 webserver.log_data("Left Motor", left_motor.get_position())
30 webserver.log_data("Right Motor", right_motor.get_position())
31 webserver.log_data("Button State", board.is_button_pressed())
32
33timer = Timer(-1)
34timer.init(freq=4, mode=Timer.PERIODIC, callback=lambda t: log_time_and_range())
35
36def connect_and_start_webserver():
37 # Connect to the network and start the webserver in bridge mode
38 # Network ssid and password are stored in root/secrets.json
39 webserver.connect_to_network()
40 webserver.start_server()
41
42def start_network_and_webserver():
43 # Start the webserver in access point mode
44 # Network ssid and password are stored in root/secrets.json
45 webserver.start_network()
46 webserver.start_server()
47
48start_network_and_webserver()