working with the adafruit circuit playground express using the raspberry pi 4, part 3

Circuit Playground Express with button B pressed, switch on, and NeoPixels emitting green light

Prerequisites

A Raspberry Pi 3B+ or 4 with Raspbian Buster installed and connected to an Adafruit Circuit Playground Express via a micro USB to USB cable and with CircuitPython installed on the Circuit Playground Express (see working with the adafruit circuit playground express using the raspberry pi 4).

Circuit Python Programming Example 5

Using the same setup with the Adafruit Circuit Playground Express (CPE) and the Raspberry Pi 4 we used in the last two posts, I’ve writen another Python application that senses and uses push buttons A and B and the slide switch on the CPE.

Using the push buttons and the small slide switch, the Python application will light up all the NeoPixels in various colors. The application will react to single button pushes as well as having both pushed simultaneously. The listing for the application is at the end of the post.

The CPE comes with a number of interesting inputs. Three of them are two push buttons, labeled A on the left and B on the right, with a small slide switch just above the JST battery connector at the bottom center of the CPE. It’s a surface mount single pole single throw (SPST) slide switch. If slid to the right, it’s off. If it’s slid to the left, then it’s on, and on means it’s detectable as such in code.

When the code in this example is saved to the CPE as main.py, then the application works as follows:

Push button APush button BSwitchNeoPixels
OpenOpenN/AOff/Black
PushedOpenOpenAll Yellow
PushedOpenClosedAll Red
OpenPushedOpenAll Blue
OpenPushedClosedAll Green
PushedPushedOpenSplit Yellow/Blue
PushedPushedClosedSplit Red/Green

The push buttons combined with the switch provide six lit NeoPixel display states as shown in the table above.

The application also illustrates another aspect of programming the CPE. If you want the application to run continuously, then you write and endless loop. Line 71 uses a ‘while True’ to keep the application running. It will only stop if you turn the power off to the CPE or it has a programming error of some type.

# Circuit Playground Express example.# Uses the NeoPixels, the A and B pushbuttons, and the switch.#import board, neopixel, timefrom digitalio import DigitalInOut, Direction, Pull# This is the small slide switch located in the center of# the circuit board, just above the JST Battery Connector.#switch = DigitalInOut(board.D7)switch.direction = Direction.INPUTswitch.pull = Pull.UP# This is the 'A' push button, the left push button on the circuit board.#buttonA = DigitalInOut(board.BUTTON_A)buttonA.direction = Direction.INPUTbuttonA.pull = Pull.DOWN# This is the 'B' push button, the right push button on the circuit board.#buttonB = DigitalInOut(board.BUTTON_B)buttonB.direction = Direction.INPUTbuttonB.pull = Pull.DOWN# Basic NeoPixel colors to play with.#RED = (31, 0,  0)YELLOW  = (31, 31, 0)GREEN   = (0,  31, 0)AQUA= (0,  31, 31)BLUE= (0,  0,  31)PURPLE  = (31, 0,  31)WHITE   = (31, 31, 31)BLACK   = (0,  0,  0)# An instance of the NeoPixels to work with programmatically.#pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.2)pixels.fill(BLACK)# To support guard logic around printing push button states.# We only want to print out when a button press is first# detected, and then we want to print out when the button is# released.#Apressed = FalseBpressed = False# A simple polling loop. The loop runs forever once it's entered# because of while True:, and it is constantly checking the state# of A and B pushbuttons, acting according to what it detects.## 1. If neither push button is pressed, the NeoPixels are dark.## 2. If Button 'A' is pressed and the switch is on,#turn on all NeoPixels as RED.# 3. If Button 'A' is pressed and the switch is off,#turn on all NeoPixels as YELLOW.# 4. If Button 'B' is simultaniously pressed, then only fill#the NeoPixels on Button A's side based on switch position.## 5. If Button 'B' is pressed and the switch in on,#turn on all NeoPixels as GREEN.# 6. If Button 'B' is pressed and the swith is off,#turn on all NeoPixels as BLUE.# 7. If Button 'A' is simultaniously pressed, then only fill#the NeoPixels on Button B's side based on switch position.#while True:if (buttonA.value):if (not Apressed):print('Button A pressed')Apressed = Trueif (switch.value):print('Switch on')if (not Bpressed):pixels.fill(RED)else:pixels[0:5] = [RED] * 5else:if (not Bpressed):pixels.fill(YELLOW)else:pixels[0:5] = [YELLOW] * 5else:if (Apressed):print('Button A released')Apressed = Falseif (not Bpressed):pixels.fill(BLACK)else:if (switch.value):pixels[0:5] = [GREEN] * 5else:pixels[0:5] = [BLUE] * 5if (buttonB.value):if (not Bpressed):print('Button B pressed')Bpressed = Trueif (switch.value):print('Switch on')if (not Apressed):pixels.fill(GREEN)else:pixels[5:10] = [GREEN] * 5else:if (not Apressed):pixels.fill(BLUE)else:pixels[5:10] = [BLUE] * 5else:if (Bpressed):print('Button B released')Bpressed = Falseif (not Apressed):pixels.fill(BLACK)else:if (switch.value):pixels[5:10] = [RED] * 5else:pixels[5:10] = [YELLOW] * 5

All the highlighted code is the logic I added to only perform an action once when either push button is pressed or released. Without that guard logic in place, those print statements would stream on the serial debug console. This makes tracking actions very difficult, if not impossible, to do. It also keeps the logic running in the loop to a bare minimum and allows it to run as fast as possible. Not only would the print statement stream without the logic, but manipulation of the NeoPixels would be non-stop. We only want actions to be performed once on a button state transition (non-pressed to pressed, and released).

The REPL

The screen command can still be used to connect to the device as shown in the earlier posts, but when it first connects nothing will be displayed unless an explicit ‘print()’ statement sends it out. To open the REPL while this application is running type [Ctrl] C and then Enter. To exit the REPL type the usual [CTRL] D and the application will start running again.

working with the adafruit circuit playground express using the raspberry pi 4, part 2

Prerequisites

A Raspberry Pi 3B+ or 4 with Raspbian Buster installed and connected to an Adafruit Circuit Playground Express via a micro USB to USB cable and with CircuitPython installed on the Circuit Playground Express (see working with the adafruit circuit playground express using the raspberry pi 4).

Setting Up and Tearing Down the REPL

Attach the Circuit Playground Express (CPE) to the Raspberry Pi. The CIRCUITPY storage device icon will appear on the desktop and a dialog will appear simultaneously asking if you want to open removable media in a file manager. You can click OK if you wish, or Cancel to remove the dialog. If you cancel the dialog but wish to open the removable media portion you can double click on the desktop icon. If you open the file manager you’ll see the following:


It’s fairly empty at the moment. Now, open an LXTerminal and type ‘screen /dev/ttyACM0 115200‘ at the prompt.

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.Press any key to enter the REPL. Use CTRL-D to reload.

Don’t type anything. Instead, using the mouse, click the up arrow that has appeared on the upper right task bar. This is the media eject control. Clicking it will produce a menu with at least the CIRCUITPY as an entry (you may have more depending on what other removable media you have plugged in. Select the CIRCUITPY entry to remove accessibility to CIRCUITPY. Then physically disconnect the CPE. Your console will now display the following:

pi@raspberrypi:~ $ screen /dev/ttyACM0 115200[screen is terminating]pi@raspberrypi:~ $

I’ve just shown how to set up and tear down the serial port into the CPE. For writing code in an editor and saving it on the CPE as main.py, it will print out any syntax errors and other data as needed to the terminal.

Circuit Python Programming Example 1

In this example I’ll show you how syntax errors will appear on the terminal. If you’ve detached the CPE, plug it back in so that it’s seen as removable media. Restart the screen utility so that you see the intro text in the terminal. Now start a text editor (VIM, gedit, text editor, whatever). Type a single line into the editor, ‘import fubar‘. Then save what you just typed as main.py onto CIRCUITPY and then look at your terminal.

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.main.py output:Traceback (most recent call last):  File "main.py", line 1, in <module>ImportError: no module named 'fubar'Press any key to enter the REPL. Use CTRL-D to reload.

There obviously is no fubar module, and Circuit Python prints out that fact as an error message on the terminal.

Circuit Python Programming Example 2

Let’s print something on the terminal. Replace the import statement with ‘print('Hello terminal')‘ and save the file. Now the terminal will show:

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.main.py output:Hello terminalPress any key to enter the REPL. Use CTRL-D to reload.

The Circuit Python is waiting for changes to main.py. Every time you save it you change it (you change the file’s timestamp, the last time the file was modified), CPE will attempt to run it. Either it’ll run, or it will stop with errors. You can use print statements to debug a program as it runs and see those print statements on the terminal.

Circuit Python Programming Example 3

Now lets code something a bit more ambitious. Let’s copy the following code into your editor and then save it out as main.py again.

import board, neopixel, timepixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.2)RED = (63, 0, 0)pixels.fill(RED)time.sleep(1)GREEN = (0, 63, 0)pixels.fill(GREEN)time.sleep(1)BLUE = (0, 0, 63)pixels.fill(BLUE)time.sleep(1)BLACK = (0, 0, 0)pixels.fill(BLACK)

If you’ll recall this is essentially the same code we typed in by hand at the end of the last post, except this time we’re going to write it into main.py and save it. When you do, you’ll see all the NeoPlixel LEDs light up in red, then green, then blue, then go dark. We’ve added three sleep commands for one second so that it doesn’t run through all the fill commands. Save this version of main.py and watch the NeoPixels light up.

What if you want to have the application repeat? You can save it again, or you can hit any key in the terminal to enter the REPL and then [Ctrl] D to exit, and the CPE will execute main.py all over again. This might be useful for simple programs, or you might want to get a bit more sophisticated for repetitive applications.

Circuit Python Programming Example 4

Let’s add to our existing application. Let’s add some looping and some print statements.

import board, neopixel, timepixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.2)for letter in "ABCDE":print(" %c loop" % letter)RED = (63, 0, 0)pixels.fill(RED)time.sleep(0.5)GREEN = (0, 63, 0)pixels.fill(GREEN)time.sleep(0.5)BLUE = (0, 0, 63)pixels.fill(BLUE)time.sleep(0.5)BLACK = (0, 0, 0)pixels.fill(BLACK)

I’ve changed the sleep time, lowering it to 1/2 second so the loop will go faster than the single pass used in example 3. I’m using simple iteration of a string of characters. In every loop I print out the letter of each loop. Save the file and watch the NeoPixels cycle through red, green, and blue five times. Here’s what the terminal looks like.

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.main.py output: A loop B loop C loop D loop E loopPress any key to enter the REPL. Use CTRL-D to reload.

You’ve now got an application that manipulates some of the CPE’s devices (the NeoPixels) as well as printing out what loop it’s in on the terminal while it’s running.

The CPE is a powerful little board, with a lot more than just NeoPixels to manipulate. Perhaps next time I’ll dive in and add both CPE input and output, and find a way to feed some of the CPE’s inputs back to the Raspberry Pi.