Candidate:
Claire Candidate
Assessed by:
Mary Mentor
Python (2023) ~ Grade 1 (Initial)
Mask emote-o-matic
Emote a smile or a frown through your COVID mask with a CircuitPlayground Express and Python.
Attached files
Filename (click to download) | Size | Uploaded by |
---|
cp_frown.jpg | 258.4 KB | claire_candidate |
Markdown code

cp_smile.jpg | 283.7 KB | claire_candidate |
Markdown code

CodeGrades_MuValueError.png | 113.9 KB | claire_candidate |
Markdown code

cp_frown_submit.jpeg | 241.0 KB | claire_candidate |
Markdown code

cp_smile_submit.jpeg | 213.5 KB | claire_candidate |
Markdown code

cp_paper_frown.jpeg | 161.7 KB | claire_candidate |
Markdown code

cp_paper_smile.jpeg | 164.6 KB | claire_candidate |
Markdown code

mask-emote-o-meter-user-guide.pdf | 32.4 KB | claire_candidate |
Markdown code
Status: Closed (results delivered). 80/100 ~ Pass with MERIT (17/03/2022).
Claire Candidate
~ 16 Mar 2022 5:49 p.m.
I'm going to make a COVID mask emote-o-matic.
During lock-down I've noticed that it's hard to tell a person's mood through their masks. Put simply, you can't see them smile or look sad, because it's sometimes hard to tell with just the person's eyes.
I'm going to sew an Adafruit Circuit Playground Express into my mask to learn how feasible an emote-o-matic is for people. As you can see from the photo, the board comes with lights and two buttons - so pressing the right button will turn the device into either a happy (the lower lights in green) or sad (the upper lights in red) look.
I think it's going to look cute and will make mask wearing something fun rather than a bit of a chore.
Claire Candidate
~ 16 Mar 2022 5:50 p.m.
(updated: 16 Mar 2022 5:51 p.m.)
I've been looking at Adafruit's CircuitPython Essentials to try to work out how to use the lights (called NEOPIXELS) and the buttons. I also found the CircuitPython examples for the NEOPIXELS. It has been hard trying to get things to work since none of it makes any sense! I just wanted to make the NEOPIXELS switch on with various colours but nothing happened. In the end I saw that my code had errors:
I wasn't sure to do, so I searched for "ValueError: NEOPIXEL is in use" and the top result was this comment somewhere. I didn't really understand much of what was going on, but I guessed that I couldn't use neopixel
AND cpx
at the same time. The example at the end gave me the hint I needed to make things work and so onto the next challenge.
Each neopixel has a number, and it's REALLY confusing that it starts counting at zero and ends at nine. Also, the order of counting is in an anti-clockwise direction, which is really confusing too. In any case I've managed to figure out how colour works: there are three numbers between 0-255 which tell the light how much red, green or blue to emit. So, (255, 0, 0)
means full on red, with no green or blue.
Now the position of the lights was worked out, and the colours too I was able to make a smile like this:
from adafruit_circuitplayground.express import cpx
cpx.pixels[0] = (0, 0, 0)
cpx.pixels[1] = (0, 0, 0)
cpx.pixels[2] = (0, 255, 0)
cpx.pixels[3] = (0, 255, 0)
cpx.pixels[4] = (0, 255, 0)
cpx.pixels[5] = (0, 255, 0)
cpx.pixels[6] = (0, 255, 0)
cpx.pixels[7] = (0, 255, 0)
cpx.pixels[8] = (0, 0, 0)
cpx.pixels[9] = (0, 0, 0)
and a frown like this:
from adafruit_circuitplayground.express import cpx
cpx.pixels[0] = (255, 0, 0)
cpx.pixels[1] = (255, 0, 0)
cpx.pixels[2] = (255, 0, 0)
cpx.pixels[3] = (0, 0, 0)
cpx.pixels[4] = (0, 0, 0)
cpx.pixels[5] = (0, 0, 0)
cpx.pixels[6] = (0, 0, 0)
cpx.pixels[7] = (255, 0, 0)
cpx.pixels[8] = (255, 0, 0)
cpx.pixels[9] = (255, 0, 0)
Here's a couple of photos to show how it looks with my mask:
I'm feeling really happy that I've made the device look happy and sad.
Next step is to make it change mood depending on which button you press.
I've already shown some friends who really like it!
Claire Candidate
~ 16 Mar 2022 5:55 p.m.
(updated: 16 Mar 2022 5:56 p.m.)
I've finally worked out how to make the buttons work so the smile changes. Here's how:
- I have to use an infinite
while
loop so my code keeps checking and updating things. - There are two variables:
smile
andfrown
. They are eitherTrue
orFalse
(boolean) and tell the code what face to emote. - First the code checks the buttons to tell which one is pressed. Button A sets
smile
toTrue
andfrown
toFalse
and button B setsfrown
toTrue
andsmile
toFalse
. - Then the code checks if either
smile
orfrown
areTrue
and displays the right pattern of pixels for that face. - If neither are
True
then the lights are switched off.
I think I have a minimal working project! Time to submit.
"""
COVID Mask emote-o-matic.
Run a CircuitPlayground Express running CircuitPython.
Put the board in a COVID mask and attach power.
Press button A for a green smile.
Press button B for a red frown.
Emote away! :-)
"""
from adafruit_circuitplayground.express import cpx
smile = False
frown = False
cpx.pixels.brightness = 1.0
while True:
if cpx.button_a == True:
if smile == True:
smile = False
else:
smile = True
frown = False
elif cpx.button_b == True:
if frown == True:
frown = False
else:
frown = True
smile = False
if smile == True:
cpx.pixels[0] = (0, 0, 0)
cpx.pixels[1] = (0, 0, 0)
cpx.pixels[2] = (0, 255, 0)
cpx.pixels[3] = (0, 255, 0)
cpx.pixels[4] = (0, 255, 0)
cpx.pixels[5] = (0, 255, 0)
cpx.pixels[6] = (0, 255, 0)
cpx.pixels[7] = (0, 255, 0)
cpx.pixels[8] = (0, 0, 0)
cpx.pixels[9] = (0, 0, 0)
elif frown == True:
cpx.pixels[0] = (255, 0, 0)
cpx.pixels[1] = (255, 0, 0)
cpx.pixels[2] = (255, 0, 0)
cpx.pixels[3] = (0, 0, 0)
cpx.pixels[4] = (0, 0, 0)
cpx.pixels[5] = (0, 0, 0)
cpx.pixels[6] = (0, 0, 0)
cpx.pixels[7] = (255, 0, 0)
cpx.pixels[8] = (255, 0, 0)
cpx.pixels[9] = (255, 0, 0)
else:
cpx.pixels.fill((0,0,0))
I've attached the code to this comment (main.py) and here's a couple of photos of it in action with my "test mask":
Mary Mentor
~ 16 Mar 2022 6:14 p.m.
Hi Claire,
I'm Mary and I'm going to be your mentor. I really like what you've been doing with this grade 1 project. Very timely and imaginative.
My job is to help you improve your project and assess how you've got on with your grade 1. One thing I won't do is contribute code, but I will ask questions, make suggestions, point out bugs and share things I think you'll find interesting to help you refine your project.
I've a few initial questions, items of feedback and observations. Please don't hesitate to ask questions or tell me where something doesn't make sense, I'm here to help.
- With conditionals (
if x:
), thex
is checked for its truth value. Sinceboolean
values are already eitherTrue
orFalse
you don't needif smile == True:
. You can just doif smile
. Can you refactor your code so it looks like this? It makes it much easier to read. - I see you already know about
cpx.pixels.fill((0, 0, 0))
to switch all the lights off. Can you rewrite your code so you only ever switch on the lights you need? - I have a CircuitPlayground Express too. When I tested the code I found a bug: I couldn't get the emote to switch off. How might you fix that?
- I notice you're using Mu. Have you tried the Serial connection to the board? Perhaps you could use it to help you with your debugging?
- You have instructions in your code, but this won't help non-technical users. Could you write something for them please?
- The photos of the device in a mask look great, but I think there's a seam of some sort that blocks out some of the lights. Have you tried it with other masks or changed the orientation of the board? (Just a thought...)
I'm looking forward to seeing how this project shapes up. Once again, congratulations for all the work you've done so far.
Claire Candidate
~ 16 Mar 2022 6:16 p.m.
(updated: 16 Mar 2022 6:17 p.m.)
Hi Mary, pleased to meet you and I'm really happy you like the project.
Thank you so much for the feedback and questions.
- I have updated the if statements so I don't use
frown == True
andsmile == False
, etc, like I did before. You're right, it makes it much easier to read. - Thanks to your pointer I figured out I only need to fill in the colours for the lights I need after using
cpx.pixels.fill((0, 0, 0))
to turn them all off! - I've tried to fix your bug but I've run into difficulties. Perhaps you could point me in the right direction? As you'll see from the new version of the code, I set both
frown
andsmile
toFalse
if bothcpx.button_a
andcpx.button_b
areTrue
(i.e. the user is pressing both buttons). This works a treat, when I press and hold both buttons the device doesn't light up. However, when I stop pressing the buttons a random smile or frown appears and I'm not sure why. Any advice would be gratefully received! - I'm really enjoying using Mu and I had already used the "Serial" connection to help me understand how the
if
statements, buttons andwhile True
loop worked (I experimented in the REPL - read, evaluate, print and loop window) to live code how it all fitted together. It also helped when things didn't work. CircuitPython prints out the result into the REPL! Very useful. - I'll produce a user guide once I'm happy I've fixed up all the code. I'll upload it as further evidence for this project when it's done.
- Finally, the seam in my cloth mask does block out some of the lights. I've got myself a standard medical mask made from paper and gauze, and the result looks a lot better. Here are some photos of the new mask with the device sewn in.
Here's the revised code:
"""
COVID Mask emote-o-matic.
Use a CircuitPlayground Express running CircuitPython.
Put the board in a COVID mask and attach power.
Press button A for a green smile.
Press button B for a red frown.
Press both buttons to turn off.
Emote away! :-)
"""
from adafruit_circuitplayground.express import cpx
smile = False
frown = False
cpx.pixels.brightness = 0.1
while True:
if cpx.button_a and cpx.button_b:
smile = False
frown = False
elif cpx.button_a:
smile = True
frown = False
elif cpx.button_b:
frown = True
smile = False
if smile:
cpx.pixels.fill((0, 0, 0))
cpx.pixels[0] = (0, 255, 0)
cpx.pixels[1] = (0, 255, 0)
cpx.pixels[2] = (0, 255, 0)
cpx.pixels[3] = (0, 255, 0)
cpx.pixels[4] = (0, 255, 0)
elif frown:
cpx.pixels.fill((0, 0, 0))
cpx.pixels[5] = (255, 0, 0)
cpx.pixels[6] = (255, 0, 0)
cpx.pixels[7] = (255, 0, 0)
cpx.pixels[8] = (255, 0, 0)
cpx.pixels[9] = (255, 0, 0)
else:
cpx.pixels.fill((0, 0, 0))
Mary Mentor
~ 16 Mar 2022 6:17 p.m.
Hi Claire,
So your bug is a common one and I can tell you what to search for online to find a solution.
Put simply, you don't remove you fingers from the buttons at exactly the same time. It means, for a fraction of a second, you have only one button pressed, thus causing the emote related to that button to display. This is because you have the while True:
loop repeating so fast that it detects these slight differences in timing when you release the buttons.
If I were you, I'd search online for ways to make the CircuitPython sleep for a fraction of a second on each iteration of the while True:
loop.
Also, I have a question about your revised code: do you need to repeat the cpx.pixels.fill((0, 0, 0))
line three times?
I look forward to your user manual!
Claire Candidate
~ 16 Mar 2022 6:18 p.m.
Hi Mary,
I fixed the bug! I'm so happy!
It took a while, but I found out about time.sleep
which pauses the program. By putting this in the if
statement relating to both buttons being pressed I was able to slow down the loop enough so the over-sensitive checking of buttons is no longer an issue. Through trial and error I found that using a float
value for fractions of a second of 0.1
was the best setting.
I was stumped for a while, but you're right... I only need to clear the lights once, and I was able to remove the final else:
as a result.
I'm putting together a user manual now and will attach it in a moment.
Here's the final version of the code.
"""
COVID Mask emote-o-matic.
Use a CircuitPlayground Express running CircuitPython.
Put the board in a COVID mask and attach power.
Press button A for a green smile.
Press button B for a red frown.
Press both buttons to turn off.
Emote away! :-) :-(
"""
import time
from adafruit_circuitplayground.express import cpx
smile = False
frown = False
cpx.pixels.brightness = 0.1
while True:
if cpx.button_a and cpx.button_b:
smile = False
frown = False
# Pause the loop to avoid over-sensitive buttons.
time.sleep(0.1)
elif cpx.button_a:
smile = True
frown = False
elif cpx.button_b:
frown = True
smile = False
# Turn off all the lights.
cpx.pixels.fill((0, 0, 0))
# Only switch on the lights that are needed.
if smile:
cpx.pixels[0] = (0, 255, 0)
cpx.pixels[1] = (0, 255, 0)
cpx.pixels[2] = (0, 255, 0)
cpx.pixels[3] = (0, 255, 0)
cpx.pixels[4] = (0, 255, 0)
elif frown:
cpx.pixels[5] = (255, 0, 0)
cpx.pixels[6] = (255, 0, 0)
cpx.pixels[7] = (255, 0, 0)
cpx.pixels[8] = (255, 0, 0)
cpx.pixels[9] = (255, 0, 0)
Claire Candidate
~ 16 Mar 2022 6:19 p.m.
OK. I've written a user guide (PDF attached). I've imagined it like the sort of gizmo you get advertised on naff shopping channels and daytime TV.
Mary Mentor
~ 16 Mar 2022 6:20 p.m.
Claire,
Thank you so much for the updates. I think I have enough evidence to assess your project. Your results should come through in the next day or two.
Claire Candidate
~ 16 Mar 2022 6:20 p.m.
Thank you so much for all your help and support. I'm nervous to find out my result.