We have all of the ingredients to complete the animation of your creature using data from the SenseHat sensors. Let’s return to our color code that we had commented out earlier. Go ahead and uncomment it (delete both triple quotation marks) and run your code. What happens?
You might notice that your color sensor animation starts working again but your direction and rotation stops working. The reason is that your program stays in the first while
loop about color and never exits this loop—it never makes it to the second while
loop where your movement animation is contained. Therefore, we need to combine these two sections into a single while
loop. Here is a single loop with all of our animation code. Run it and read through it and see if you notice anything odd
#### Create the GIF animation
while True:
### Color
# Arrange colors with updated color variable values on 8x8 matrix
image = [
f, f, f, g, g, g, g, g,
f, f, g, g, f, g, g, f,
f, f, f, f, f, f, g, g,
f, g, g, g, g, g, g, g,
g, g, g, g, g, g, d, d,
g, b, g, g, g, d, d, f,
g, g, g, g, d, d, f, f,
f, g, g, d, d, f, f, f]
# Code telling the pixels to light up with sensor-based colors
sense.set_pixels(image)
# Get the color from the sensor
rgb = sense.color
# Accentuate the increases and decreases in RGB values
current_colors = (rgb.red, rgb.green, rgb.blue)
changes = [current_colors[0]-previous_colors[0], current_colors[1]-previous_colors[1],current_colors[1]-previous_colors[1]]
# Get the largest and smallest values from the color list
increase = min(changes)
decrease = max(changes)
# Determine the position in the list of the max/min values, telling us which colors they represent
increase_position = changes.index(increase)
decrease_position = changes.index(decrease)
# Apply the accentuation
current_colors_modified = list(current_colors)
current_colors_modified[increase_position] = current_colors_modified[increase_position] + modifier
current_colors_modified[decrease_position] = current_colors_modified[decrease_position] - modifier
# Check that accentuated color values are within correct RGB ranges
for i in range(3):
if current_colors_modified[i] > 255:
current_colors_modified[i] = 255
if current_colors_modified[i] < 0:
current_colors_modified[i] = 0
# Convert color values into proper (R, G, B) tuple format from [R, G, B] array format
b = tuple(current_colors_modified)
# Store this lap's color value for comparison on the next iteration of the loop
previous_colors = current_colors
### Direction and Rotation
# Poll the sensors at the start of the loop and store the values in variables
orientation = sense.get_orientation_degrees()
roll = orientation["roll"]
pitch = orientation["pitch"]
yaw = orientation["yaw"]
if pitch > 180:
pitch = pitch - 360
# Get a fresh orientation value for this lap
new_movement = roll * 0.1 + pitch * 0.6 + yaw * 0.3
# No direction change or movement if sensor difference is too small
if abs(movement-new_movement) < 1:
continue
# Change creature direction to port
if new_movement < movement and direction == "starboard":
sense.flip_h()
direction = "port"
# Change creature direction to starboard
if new_movement > movement and direction == "port":
sense.flip_h()
direction = "starboard"
# Compare current orientation to our pre-loop starting orientation
relative_heel = starting_position - new_movement
# Rotate our creature
if relative_heel > 4:
sense.set_rotation(270)
if relative_heel < -4:
sense.set_rotation(90)
if -4 <= relative_heel <= 4:
sense.set_rotation(0)
# Store this lap's movement value for comparison on the next iteration of the loop
movement = new_movement
We lost our direction animation! What happened? No matter how you turn your SenseHat, the whale stays facing the same way. Let’s walk through the loop and see if we can figure it out…
The first thing we do is declare the array image
that stores our creature data. We need to do this in order for the variable “f” to be updated with the results of the color sensor. This is where things are going wrong since our creature is coded to face the same direction every time. We need to add a line of code right after we declare this array that checks what direction it should be facing and, if it should be facing “port,” flip it around. Add this line of code right after we call set_pixels()
.
# Correct the direction if the matrix layout is backwards based on previous loop's orientation
if direction == "port":
sense.flip_h()
We can actually comment out the flip_h()
commands we used previously. The only thing that needs to be updated in those if
statements is the variable direction
. Our new if
statement checks if, on the previous loop, we changed direction
to “port” and, if we did, flips around the creature we just re-drew on this lap. If direction
is still “starboard”, we just leave the re-drawn creature as-is.
You should now be able to run your code and have all three animations working: color, direction, and rotation. Hooray!! For reference, here is the full program we have written is copied below.
You have two final tasks if you want to submit your code to Ocean Pi to be run aboard Wonder. First, we need to introduce time into our code so that it will only run for 30 seconds. Finally, we need to record and save all of the color and motion data we gather.
Here is our full program:
#### Housekeeping
# Libraries
from sense_hat import SenseHat
sense = SenseHat()
from time import sleep
#### Code that makes the original creature image on the LED matrix
# Declare colors as RGB values and store them in variables
d = (255, 255, 255) # Cyan
f = (25, 25, 112) # MidnightBlue
g = (0, 191, 255) # DeepSkyBlue
b = (0, 0, 0) # Black
# Arrange colors on an 8x8 matrix to make an image. This is a whale.
image = [
f, f, f, g, g, g, g, g,
f, f, g, g, f, g, g, f,
f, f, f, f, f, f, g, g,
f, g, g, g, g, g, g, g,
g, g, g, g, g, g, d, d,
g, b, g, g, g, d, d, f,
g, g, g, g, d, d, f, f,
f, g, g, d, d, f, f, f]
# Code telling the pixels to light up
sense.set_pixels(image)
# Hold the original image on screen for 1 second
sleep(1)
#### Prepare the sensors
# Set up and poll the color sensor
sense.color.gain = 64 # Set the sensitivity of the sensor
sense.color.integration_cycles = 64 # The interval at which the reading will be taken
rgb = sense.color
#re-assign the whale's eye color variable to the sensed color value
b = (rgb.red, rgb.green, rgb.blue)
# Set up and poll the rotation sensors
orientation = sense.get_orientation_degrees()
roll = orientation["roll"]
pitch = orientation["pitch"]
yaw = orientation["yaw"]
if pitch > 180:
pitch = pitch - 360
# Starting orientation values
starting_position = roll * 0.1 + pitch * 0.6 + yaw * 0.3
movement = starting_position
direction = "starboard"
# Starting color values
previous_colors = b
modifier = 40 # governs how much the sensor values will be accentuated
#### Create the GIF animation
while True:
### Color
# Arrange colors with updated color variable values on 8x8 matrix
image = [
f, f, f, g, g, g, g, g,
f, f, g, g, f, g, g, f,
f, f, f, f, f, f, g, g,
f, g, g, g, g, g, g, g,
g, g, g, g, g, g, d, d,
g, b, g, g, g, d, d, f,
g, g, g, g, d, d, f, f,
f, g, g, d, d, f, f, f]
# Code telling the pixels to light up with sensor-based colors
sense.set_pixels(image)
# Correct the direction if the matrix layout is backwards based on previous loop's orientation
if direction == "port":
sense.flip_h()
# Get the color from the sensor
rgb = sense.color
# Accentuate the increases and decreases in RGB values
current_colors = (rgb.red, rgb.green, rgb.blue) # store the current sensed values for comparison with the previous colors
changes = [current_colors[0]-previous_colors[0], current_colors[1]-previous_colors[1],current_colors[1]-previous_colors[1]]
# Get the largest and smallest values from the color list
increase = min(changes)
decrease = max(changes)
# Determine the position in the list of the max/min values, telling us which colors they represent
increase_position = changes.index(increase)
decrease_position = changes.index(decrease)
# Apply the accentuation
current_colors_modified = list(current_colors)
current_colors_modified[increase_position] = current_colors_modified[increase_position] + modifier
current_colors_modified[decrease_position] = current_colors_modified[decrease_position] - modifier
# Check that accentuated color values are within correct RGB ranges
for i in range(3):
if current_colors_modified[i] > 255:
current_colors_modified[i] = 255
if current_colors_modified[i] < 0:
current_colors_modified[i] = 0
# Convert color values into proper (R, G, B) tuple format from [R, G, B] array format
b = tuple(current_colors_modified)
# Store this lap's color value for comparison on the next iteration of the loop
previous_colors = current_colors
### Direction and Rotation
# Poll the sensors at the start of the loop and store the values in variables
orientation = sense.get_orientation_degrees()
roll = orientation["roll"]
pitch = orientation["pitch"]
yaw = orientation["yaw"]
if pitch > 180:
pitch = pitch - 360
# Get a fresh orientation value for this lap
new_movement = roll * 0.1 + pitch * 0.6 + yaw * 0.3
# No direction change or movement if sensor difference is too small
if abs(movement-new_movement) < 1:
continue
# Change creature direction to port
if new_movement < movement and direction == "starboard":
#sense.flip_h()
direction = "port"
# Change creature direction to starboard
if new_movement > movement and direction == "port":
#sense.flip_h()
direction = "starboard"
# Compare current orientation to our pre-loop starting orientation
relative_heel = starting_position - new_movement
# Rotate our creature
if relative_heel > 4:
sense.set_rotation(270)
if relative_heel < -4:
sense.set_rotation(90)
if -4 <= relative_heel <= 4:
sense.set_rotation(0)
# Store this lap's movement value for comparison on the next iteration of the loop
movement = new_movement