#### Housekeeping
# Libraries
from sense_hat import SenseHat
sense = SenseHat()
from time import sleep
from datetime import datetime
from csv import writer
# Timer and team name
team_name = "Whale_Demo"
timer = 1
increment = 0.1
Next, we will write some code to create and name our data file. This is where your team name becomes useful and will be how we get your GIF back to you after your code runs. Add the following code right before your while
loop:
# Starting orientation values
starting_position = roll * 0.1 + pitch * 0.6 + yaw * 0.3
movement = starting_position
direction = "starboard"
rotation = 0
# Starting color values
previous_colors = b
modifier = 40 # governs how much the sensor values will be accentuated
# Starting color values
previous_colors = b
modifier = 40 # governs how much the sensor values will be accentuated
# Starting time
starting_time = datetime.now().strftime("%m-%d-%Y_%H:%M:%S")
# Create data file and record original creature
with open(team_name+"_"+starting_time+".csv", "w", buffering=1, newline='') as datafile:
data_writer = writer(datafile)
data_writer.writerow(image)
data_writer.writerow([timer, direction, rotation, d, f, g, b])
You will also notice that we created a variable called rotation
. Can you guess the purpose of this variable from where we added it in the code? Where else in our code might we have to add some updates to rotation
?
If you thought about the three if
statements in our while
loop that analyze relative_heel
then you are correct. We do not actually use the variable rotation
in our code, we just use it to store information that we record to our data recorder.
Be sure to replace d, f, g, b
with the names of whatever color variables you used in creating your creature. We used four colors in our whale, so there are only four variables listed. If you used just two colors, there should only be two variables. If you used 64 different colors, there should be 64 variables listed here.
What we are doing in this code is using the time that your file is run and your team name to create the file name. Then we are recording your creature to the first line of the file followed by the color values, direction, and rotation values. These are all set to their defaults because we have not started the while
loop yet. Well…almost. If you scroll up a few lines in your program, you will notice that we poll the color sensor once and change the color of the whale’s eye. If you want the original design of your creature to show up in your GIF, then you can delete these lines of code. We have deleted them, since we do want our original image to show first. Here is all of our code before the while
loop.
#### Housekeeping
# Libraries
from sense_hat import SenseHat
sense = SenseHat()
from time import sleep
from datetime import datetime
from csv import writer
# Timer and team name
team_name = "Whale_Demo"
timer = 1
increment = 0.1
#### 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
# 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"
rotation = 0
# Starting color values
previous_colors = b
modifier = 40 # governs how much the sensor values will be accentuated
# Starting time
starting_time = datetime.now().strftime("%m-%d-%Y_%H:%M:%S")
# Create data file and record original creature
with open(team_name+"_"+starting_time+".csv", "w", buffering=1, newline='') as datafile:
data_writer = writer(datafile)
data_writer.writerow(image)
data_writer.writerow([timer, direction, rotation, d, f, g, b])
Notice that the lines after with
are indented just like the code inside of the while
loop. This is a very important detail. Our last step is to indent all of the code inside of the while
loop so that it is included in the with
statement.
Once our while
loop is indented, we need to record the data from each lap of the loop. We can add the following lines to the start of our loop:
#### Create the GIF animation
while timer < 30:
timer = timer + increment
sleep(increment)
data_writer.writerow([timer, direction, rotation, d, f, g, b])
Finally, we need to make sure that we update the rotation
variable every time we call set_orientation
due to heel_angle
. Update each if
statement to include an update to rotation
.
# Rotate our creature
if relative_heel > 4:
sense.set_rotation(270)
rotation = 270
if relative_heel < -4:
sense.set_rotation(90)
rotation = 90
if -4 <= relative_heel <= 4:
sense.set_rotation(0)
rotation = 0
That’s it—you did it!! 🥳 🎉 🪩 🙌 🐋
You should run your code a few times in Trinket or on your Raspberry Pi to make sure it works, then you are ready to submit. Below is the full code of the completed demo. You can also access it on Github.
#### Housekeeping
# Libraries
from sense_hat import SenseHat
sense = SenseHat()
from time import sleep
from datetime import datetime
from csv import writer
# Timer and team name
team_name = "Whale_Demo"
timer = 1
increment = 0.1
#### 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
# 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"
rotation = 0
# Starting color values
previous_colors = b
modifier = 40 # governs how much the sensor values will be accentuated
# Starting time
starting_time = datetime.now().strftime("%m-%d-%Y_%H:%M:%S")
# Create data file and record original creature
with open(team_name+"_"+starting_time+".csv", "w", buffering=1, newline='') as datafile:
data_writer = writer(datafile)
data_writer.writerow(image)
data_writer.writerow([timer, direction, rotation, d, f, g, b])
#### Create the GIF animation
while timer < 30:
timer = timer + increment
sleep(increment)
data_writer.writerow([timer, direction, rotation, d, f, g, b])
### 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)
rotation = 270
if relative_heel < -4:
sense.set_rotation(90)
rotation = 90
if -4 <= relative_heel <= 4:
sense.set_rotation(0)
rotation = 0
# Store this lap's movement value for comparison on the next iteration of the loop
movement = new_movement
sense.clear()
quit()
Now that you have written all of your code to animate your ocean creature, you need to add some code to record the data that is animating your creature. If we don’t record it, then your creature will run on Wonder for all of the crew to enjoy but none of it will be saved—we won’t be able to send back an animated GIF to you.
We will save your data in a format called “CSV” which stands for “comma separated values” and is a common data format used in spreadsheets. We will need to record the color information of each of your pixels, the original layout of your creature, and the timing of any animations created by the sensors. While there have been opportunities to make your own edits to previous parts of this project, it is important that you add the following code to your project just as we describe. Here we go.
First, we will need to import some additional code libraries. Add the following lines to the start of your program: