CircuitPython

To program your Circuit Playground Express board with CircuitPython code, first make sure your board is set up to use CircuitPython - check out the Quick Start guide for instructions.

Once your board is set up and attached to your computer via a micro USB cable, you should see it appear as a an attached drive named "CIRCUITPY".  (You may need to double-click the Reset button to make it appear.)

Copy the code below and save it as a file named "code.py" on the "CIRCUITPY" drive.

# Circuit Playground Express CircuitPython Morse Code Flasher
# This is meant to work with the Circuit Playground Express board:
#   https://www.adafruit.com/product/3333
# Needs the NeoPixel module installed:
#   https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel
# Author: Collin Cunningham
# License: MIT License (https://opensource.org/licenses/MIT)

import time

import board
import neopixel

# Configuration:
# Message to display (capital letters and numbers only)
message = 'SOS'
dot_length = 0.15  # Duration of one Morse dot
dash_length = (dot_length * 3.0)  # Duration of one Morse dash
symbol_gap = dot_length  # Duration of gap between dot or dash
character_gap = (dot_length * 3.0)  # Duration of gap between characters
flash_color = (255, 0, 0)  # Color of the morse display.
brightness = 0.5  # Display brightness (0.0 - 1.0)
morse = [
    ('A', '.-'),
    ('B', '-...'),
    ('C', '-.-.'),
    ('D', '-..'),
    ('E', '.'),
    ('F', '..-.'),
    ('G', '--.'),
    ('H', '....'),
    ('I', '..'),
    ('J', '.---'),
    ('K', '-.-'),
    ('L', '.-..'),
    ('M', '--'),
    ('N', '-.'),
    ('O', '---'),
    ('P', '.--.'),
    ('Q', '--.-'),
    ('R', '.-.'),
    ('S', '...'),
    ('T', '-'),
    ('U', '..-'),
    ('V', '...-'),
    ('W', '.--'),
    ('X', '-..-'),
    ('Y', '-.--'),
    ('Z', '--..'),
    ('0', '-----'),
    ('1', '.----'),
    ('2', '..---'),
    ('3', '...--'),
    ('4', '....-'),
    ('5', '.....'),
    ('6', '-....'),
    ('7', '--...'),
    ('8', '---..'),
    ('9', '----.'),
]


# Define a class that represents the morse flasher.


class MorseFlasher:
    def __init__(self, color=(255, 255, 255)):
        # set the color adjusted for brightness
        self._color = (
            int(color[0] * brightness),
            int(color[1] * brightness),
            int(color[2] * brightness)
        )

    def light(self, on=True):
        if on:
            pixels.fill(self._color)
        else:
            pixels.fill((0, 0, 0))
        pixels.show()

    def showDot(self):
        self.light(True)
        time.sleep(dot_length)
        self.light(False)
        time.sleep(symbol_gap)

    def showDash(self):
        self.light(True)
        time.sleep(dash_length)
        self.light(False)
        time.sleep(symbol_gap)

    def encode(self, string):
        output = ""
        # iterate through string's characters
        for c in string:
            # find morse code for a character
            for x in morse:
                if x[0] == c:
                    # add code to output
                    output += x[1]
            # add a space in between characters
            output += " "
        # save complete morse code output to display
        self.display(output)

    def display(self, code=".-.-.- "):
        # iterate through morse code symbols
        for c in code:
            # show a dot
            if c == ".":
                self.showDot()
            # show a dash
            elif c == "-":
                self.showDash()
            # show a gap
            elif c == " ":
                time.sleep(character_gap)


# Initialize NeoPixels
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()

# Create a morse flasher object.
flasher = MorseFlasher(flash_color)

# Main loop will run forever
while True:
    flasher.encode(message)

Once the new code.py file is saved, the board should restart and start displaying the SOS message in Morse code.

You should see flashes that correspond to the following sequence:

. . . - - - . . .

A Tour of the Code

So, what is all this CircuitPython code doing?  Let’s take a look piece by piece …

Imports

First off, we import code libraries that allow us to do complex things with simple commands …

Download: file
import time
import board
import neopixel

Variables

Next, we define the variables we’ll be using to store important values …

Download: file
message = 'SOS'                     # Message to display (capital letters and numbers only)
dot_length = 0.15                   # Duration of one Morse dot
dash_length = (dot_length * 3.0)    # Duration of one Morse dash
symbol_gap = dot_length             # Duration of gap between dot or dash
character_gap = (dot_length * 3.0)  # Duration of gap between characters
flash_color = (255, 0, 0)           # Color of the morse display.
brightness = 0.5                    # Display brightness (0.0 - 1.0)
morse = [('A', '.-'), ('B', '-...'), ('C', '-.-.'), ('D', '-..'), ('E', '.'), ('F', '..-.'), ('G', '--.'), ('H', '....'), ('I', '..'), ('J', '.---'), ('K', '-.-'), ('L', '.-..'), ('M', '--'), ('N', '-.'), ('O', '---'), ('P', '.--.'), ('Q', '--.-'), ('R', '.-.'), ('S', '...'), ('T', '-'), ('U', '..-'), ('V', '...-'), ('W', '.--'), ('X', '-..-'), ('Y', '-.--'), ('Z', '--..'), ('0', '-----'), ('1', '.----'), ('2', '..---'), ('3', '...--'), ('4', '....-'), ('5', '.....'), ('6', '-....'), ('7', '--...'), ('8', '---..'), ('9', '----.')]

message is the string of letters or numbers we want to display in Morse code.

dot_length is the length of time (in seconds) one morse dot will take to display. dot_length is also used to determine the value of all the other time variables (dash_length, symbol_gap, & character_gap) So, if you change dot_length, all the other time variables will change in relation to it.

flash_color is the color the LEDs will show when they flash.

brightness determines how bright the flashes will be.

Finally, the morse variable is an array of value pairs called “tuples”.  Each tuple contains two values - the first one is the readable character we want to display in Morse code and the second is the sequence of Morse dots and dashes we’ll use to display that readable character.

MorseFlasher Object

Next up, we define the MorseFlasher object which will translate our readable characters to Morse code and handle all the LED flashing. It looks pretty big, but it's not too complicated once you break it down …

Download: file
class MorseFlasher:

    def __init__(self, color=(255,255,255)):
        #set the color adjusted for brightness
        self._color = (int(color[0]*brightness), int(color[1]*brightness), int(color[2]*brightness))
    
    def light(self, on=True):
        if on:
            pixels.fill(self._color)
        else:
            pixels.fill((0,0,0))
        pixels.show()
        
    def showDot(self):
        self.light(True)
        time.sleep(dot_length)
        self.light(False)
        time.sleep(symbol_gap)
        
    def showDash(self):
        self.light(True)
        time.sleep(dash_length)
        self.light(False)
        time.sleep(symbol_gap)

    def encode(self, str):
        output = ""
        #iterate through string's characters
        for c in str:
            #find morse code for a character
            for x in morse:
                if x[0] == c:
                    #add code to output
                    output += x[1]
            # add a space in between characters
            output += " "
        #save complete morse code output to display
        self.display(output)
         
    def display(self, code=".-.-.- "):
        # iterate through morse code symbols
        for c in code:
            # show a dot
            if c == ".":
                self.showDot()
            # show a dash
            elif c == "-":
                self.showDash()
            # show a gap
            elif c == " ":
                time.sleep(character_gap)

Within the MorseFlasher object, there are several functions that define how it works:

The __init__ function creates the MorseFlasher object and sets the color that it will show by multiplying an initial color by the brightness variable.

The light function turns the LEDs on or off depending on a given boolean (True or False) value.

The showDot function turns the LEDs on, waits for one dot_length, then turns them off and waits for one gap_length.

The showDash function turns the LEDs on, waits for one dash_length, then turns them off and waits for one gap_length.

The encode function takes a message and translates it into morse code using the morse array variable. It takes each character from the message, finds that character’s morse code from the array of tuples, and adds that code to a variable named output. Once all the characters in the message have been translated, the display function is called and given the output variable.

Finally, the display function takes a string of morse code (dots, dashes, and spaces) and converts into LED flashes.  One by one, it checks each character in the code. If it finds a dot, it will call the show_dot function. If it finds a dash, it will call the show_dash function. And if it finds a space, it will wait for the length of one character_gap.

Let's do this!

Once all of our functions have been defined, it’s time to get the party started and use all that code we've written above …

Download: file
# Initialize NeoPixels
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()

# Create a morse flasher object.
flasher = MorseFlasher(flash_color)

# Main loop will run forever
while True:
    flasher.encode(message)

In order to easily control our LEDs, we create pixels which is a Neopixel object from the neopixel library we imported earlier.  We want to make sure the LEDs are all turned off at the start, so we set them to black (0, 0, 0) and call pixels.show() to show the colors we just set.

Next we create the MorseFlasher object named flasher and we give it the color we want the LEDs to flash.

Finally - we set all the gears in motion.  Inside the main loop (while True:) we call the flasher object’s encode function and give it our message to display.  Once the function has completed and shown the message, the main loop will begin again and our message will be displayed - FOREVER! … or at least until you disconnect power or reprogram the Circuit Playground board ;)

This guide was first published on Dec 19, 2017. It was last updated on Dec 19, 2017. This page (CircuitPython) was last updated on Oct 18, 2019.