Lego Spike Python Booklet
Lego Spike Python Booklet
Lego Spike
Python Coding
1|Page
Content
Section Content
A Introduction
B Code Required for All Projects
C Run the Motors in Set Patterns
D Obstacle Avoidance with the Ultrasonic Sensor
E Line Following with the Color Sensor
F SumoBot
Documentation
https://hubmodule.readthedocs.io/en/latest/
2|Page
A. Introduction
2. Run the software and connect the Spike using the USB cable. The Spike should be automatically recognised.
Click File > Save As to Sensor and Motor Coding help New project
save your code connections including button
(and clear the console) example code
Coding
space
3|Page
4. Click the left button to change the sensor and motor settings.
5. Create a new project. Click Home and select New Project, or click the + button on the top right of the window.
4|Page
B. Code Required for All Projects
There is a set of instructions that is required for all projects. The code below should be modified for each project. If
certain lines of code are not required (you may not be using a particular sensor or motor), just put a hash (#) in front
of the line.
It is easiest with Spike to import all libraries, whether or not they will be used.
#IMPORTS----------------------------------------
from spike import PrimeHub, LightMatrix, Button, StatusLight, ForceSensor,
MotionSensor, Speaker, ColorSensor, DistanceSensor, Motor, MotorPair
from spike.control import wait_for_seconds, wait_until, Timer
from spike.operator import *
from math import *
Don’t import the App library unless you never want to run the program disconnected from the computer. An error
will occur if you use the App library and don’t have a connection.
The connection to the Spike hub and all sensors and motors must be set up, using the correct ports. Make sure your
code matches the list on the top of the screen.
Make sure you reset the yaw (rotation) angle and set the motor stop action here as well.
#CONNECTIONS--------------------------------------
hub = PrimeHub()
hub.motion_sensor.reset_yaw_angle()
sonar_sensor = DistanceSensor('E')
color_sensor = ColorSensor('D')
motors = MotorPair('B', 'C')
motors.set_stop_action('brake') #'brake','hold','coast'
force_sensor = ForceSensor('A')
5|Page
3. Get the Sensor Readings
It is easiest in most projects to get all sensor readings at once. This code creates global variables for each sensor
value. The function get_all_values() can be called to get the current sensor values.
The line def get_sonar(): is the start of a function. See how the line has a colon (:) at the end of it and the lines
underneath are indented. Always use the tab key to create the indents for one line or many selected lines)
#SENSOR FUNCTIONS-------------------------------
def get_sonar():
d = 999
value = sonar_sensor.get_distance_cm()
if not value == None: d = value
return d
def get_all_values(output):
global reflected, distance, switch, yaw, pitch
reflected = color_sensor.get_reflected_light()
distance = get_sonar()
switch = force_sensor.is_pressed()
yaw = hub.motion_sensor.get_yaw_angle()
pitch = hub.motion_sensor.get_pitch_angle()
Spike Python has no built-in function to turn the motors until a yaw angle is reached. The functions in this section fill
that gap.
#MOTOR FUNCTIONS---------------------------------
def wait_for_yaw(angle=90):
yaw = 0
if angle > 0:
while yaw <= angle: yaw = hub.motion_sensor.get_yaw_angle()
elif angle < 0:
while yaw >= angle: yaw = hub.motion_sensor.get_yaw_angle()
6|Page
5. Delay the Start of the Code
For most projects involving motors, you don’t want the code to start running as soon as it is sent to the Spike.
Change the value of the the wait_for_seconds() command, if you also want a longer delay before it starts running.
#WAIT TO START----------------------------------
print('waiting to start')
hub.status_light.on('blue') #blue indicates program loaded and ready
hub.left_button.wait_until_pressed() #press left button to start program
wait_for_seconds(0.5)
hub.light_matrix.show_image('HAPPY') #program starting to run
hub.status_light.on('green')
Note: remove hub.left_button.wait_until_pressed() if you want the program to start immediately when you press the
middle button. However, remember that there will be a delay after the middle button is pressed for the code to be
loaded and ready to execute.
6. Main Loop
Most projects will have an endless loop. Most of your code will be written inside this loop.
#MAIN LOOP--------------------------------------
print('main loop')
while True:
get_all_values(True)
• Click the File > Save As menu item to save your code to a file (this will also clear and reset the console)
7|Page
C. Run the Motors in Set Patterns
The two driving motors are linked as a motor pair. There are two ways to run the motors:
1. Steering – where the direction of travel is controlled by a steering value (zero straight ahead, negative to the left,
positive to the right). A single power setting is given to control the speed. The commands are:
2. Tank-Drive – where the direction of travel is controlled by the amount of power given to each motor
The start() and stop() commands are used where you start the motors, then wait until a certain condition is met
before stopping the motors. For example:
• Start the motors, then drive forward until Spike is 10cm from a wall before stopping the motors
• Start the motors, then drive forward until the color sensor detects the color ‘red’
These commands are used when you want to drive or turn for a specific distance (in cm, wheel rotations or degrees
of axle turn) or time (seconds).
8|Page
Let’s start by getting the Spike moving in some basic patterns:
We will first use the move() command to do this, as we want to drive for a specific distance or time.
a. Drive forward for 30cm, then back for 30cm, at 50% speed
#MAIN LOOP--------------------------------------
while True:
motors.move(30, 'cm', steering=0, speed=50)
motors.move(30, 'cm', steering=0, speed=-50)
b. Drive forward for 2 wheel-rotations, then back for 2 wheel-rotations, at 50% speed
#MAIN LOOP--------------------------------------
while True:
motors.move(2, 'rotations', steering=0, speed=50)
motors.move(2, 'rotations', steering=0, speed=-50)
c. Drive forward for 2 seconds, then back for 2 seconds, at 50% speed
#MAIN LOOP--------------------------------------
while True:
motors.move(2, 'seconds', steering=0, speed=50)
motors.move(2, 'seconds', steering=0, speed=-50)
d. Drive forward for half a wheel turn (180o), then back for half a wheel turn, at 50% speed
#MAIN LOOP--------------------------------------
while True:
motors.move(180, 'degrees', steering=0, speed=50)
motors.move(180, 'degrees', steering=0, speed=-50)
#MAIN LOOP--------------------------------------
while True:
motors.move_tank(10, 'cm', left_speed=50, right_speed=50)
motors.move_tank(10, 'cm', left_speed=-50, right_speed=-50)
9|Page
C2. Turn to the Left or Right
In this example we use steering control to first steer to the right (positive value), then steer to the left (negative
value).
#MAIN LOOP--------------------------------------
while True:
motors.move(30, 'cm', steering=100, speed=50)
motors.move(30, 'cm', steering=-100, speed=50)
#MAIN LOOP--------------------------------------
while True:
motors.move_tank(20, 'cm', left_speed=20, right_speed=70)
motors.move_tank(20, 'cm', left_speed=70, right_speed=20)
Work out the distance for a particular speed that turns 90o using either steering or tank-drive. Which is best - using
'cm', 'rotations', or 'degrees' ?
With steering, we can use the angle_turn() function to turn until an angle is reached. To turn a right angle:
#MAIN LOOP--------------------------------------
while True:
get_all_values(False)
angle_turn(steer=100, speed=50, angle=90, stop=True)
wait_for_seconds(3)
#MAIN LOOP--------------------------------------
while True:
angle_turn_tank(left_speed=50, right_speed=0, angle=90, stop=True)
wait_for_seconds(3)
We repeat a loop four times, to drive forward and turn to the right.
#MAIN LOOP--------------------------------------
while True:
for i in range(4):
motors.move(40, 'cm', steering=0, speed=50) #straight
angle_turn(steer=100, speed=50, angle=90, stop=True) #turn
10 | P a g e
D. Obstacle Avoidance with the Ultrasonic Sensor
• Drive forward
• If an obstacle is found within 10cm then stop
• Move backward 5cm
• Turn (any angle will do)
To do this we can use the wait_for_distance() command or get and test the distance ourselves
#MAIN LOOP--------------------------------------
while True:
motors.start(steering=0, speed=50) #forward
sonar.wait_for_distance_closer_than(10, 'cm') #collision test
motors.stop() #stop
motors.move(5, 'cm', steering=0, speed=-50) #move back
motors.move(10, 'cm', steering=100, speed=50) #turn
#MAIN LOOP--------------------------------------
while True:
get_all_values(True)
if distance < 10: #collision test
motors.stop() #stop
motors.move(5, 'cm', steering=0, speed=-50) #move back
motors.move(10, 'cm', steering=100, speed=50) #turn
else:
motors.start(steering=0, speed=50) #forward
#MAIN LOOP--------------------------------------
print('main loop')
while True:
get_all_values(False)
11 | P a g e
E. Line Following with the Color Sensor
We have previously created a global variable to get the reflected light value from the color sensor. We can use that
value to test whether the color sensor is on or off a black line.
• On a line will give a low reflectance value or off a line will give a high value.
• Assume for a start that if the reflected light value is less than 60% if we are on or near a black line.
• Place the Spike with the color sensor on the left of the black line
• If the sensor is on white – turn right
• If the sensor is on black – turn left
#MAIN LOOP--------------------------------------
motors.start(steering=0, speed=50) #forward
while True:
get_all_values(True)
if reflected > 60:
motors.move(steering=30, speed=50) #turn right
else:
motors.move(steering=-30, speed=50) #turn left
12 | P a g e
F. SumoBot
SumoBots use the ultrasonic sensor to seek and destroy another robot vehicle in the Sumo ring, while using the color
sensor to sense the white border and avoid falling off the edge.
#MAIN LOOP--------------------------------------
print('main loop')
motors.move_tank(20, 'cm', left_speed=50, right_speed=50)
while True:
get_all_values(False)
F2. Enhancements
• Don’t waste time moving forward at the start before starting to find the other vehicle
• Only scan left and right up to 90 degrees the first time
• Stop every 10 degrees when scanning to make sure scan detects vehicle (moving too fast doesn’t work) by
using the movement sensor yaw and the angle-turn() function
• Use movement sensor to detect a collision or the bot lifted off the ground (pitch or roll)
• If motion is stopped for x seconds, use a series of rapid wheel movements (e.g. back and forth) to try and get
free
• Use a different strategy:
Follow white line around the outside
Drive to a random place
Drive forward until white line and turn and go somewhere else until white line
• Use two ultrasonic sensors at different angles
13 | P a g e