Step 2: Buttons, buttons who's got the button

Goal: Get a skeleton of a program going that demonstrates the basic code flow.

So, when I’m talking about documentation, here’s one example of what I ran up against. The OLED FeatherWing tells you how to use the buttons in the Arduino world, but not in the CircuitPython world, which meant that I had to do some digging because the only tutorial I found with a quick google search was for a different device and didn’t at all apply to my wing.

It looks something like this:

import board
import digitalio

button_a = digitalio.DigitalInOut(board.D9)
button_a.direction = digitalio.Direction.INPUT
button_a.pull = digitalio.Pull.UP

while True:
    if not button_a.value:
        print("fffff")

And then, what I really wanted is:

import board
import digitalio
from adafruit_debouncer import Debouncer

raw_button_a = digitalio.DigitalInOut(board.D9)
raw_button_a.direction = digitalio.Direction.INPUT
raw_button_a.pull = digitalio.Pull.UP
button_a = Debouncer(raw_button_a)

while True:
    button_a.update()
    if button_a.fell:
        print('Just pressed')
    if button_a.rose:
        print('Just released')
    if button_a.value:
        print('not pressed')
    else:
        print('pressed')

Because then you get a debouncer library that’s really a fundamental requirement for doing any sort of real input from a button.

Now, the idea here is that I’m going to use the OLED display to tell me which program I’m in when the light-show is “muted”, but when the light-show is going on, I want the OLED to be off so it doesn’t disturb my painting.

So, my completed user-interface code looks something like this:

import board
import digitalio
import displayio
import time
import neopixel
import adafruit_dotstar
import terminalio
from adafruit_display_text import label
import adafruit_displayio_ssd1306
from adafruit_debouncer import Debouncer

program = 0
mute = True

num_pixels = 3
pixels = adafruit_dotstar.DotStar(board.SCK, board.MOSI, num_pixels, brightness=0.1, auto_write=False)

displayio.release_displays()

red_led = digitalio.DigitalInOut(board.D13)
red_led.direction = digitalio.Direction.OUTPUT

board_led = neopixel.NeoPixel(board.NEOPIXEL, 1)

i2c = board.I2C()
display_bus = displayio.I2CDisplay(i2c, device_address=0x3C)
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32)

def show_screen():
	# Make the display context
	splash = displayio.Group(max_size=10)
	display.show(splash)

	if mute:
		text = "Program: {0}".format(program)
		text_area = label.Label(terminalio.FONT, text=text, color=0xFFFF00, x=0, y=10)
		splash.append(text_area)

def setup_oled_buttons():
	raw_button_a = digitalio.DigitalInOut(board.D9)
	raw_button_a.direction = digitalio.Direction.INPUT
	raw_button_a.pull = digitalio.Pull.UP
	button_a = Debouncer(raw_button_a)
	 
	raw_button_b = digitalio.DigitalInOut(board.D6)
	raw_button_b.direction = digitalio.Direction.INPUT
	raw_button_b.pull = digitalio.Pull.UP
	button_b = Debouncer(raw_button_b)
	 
	raw_button_c = digitalio.DigitalInOut(board.D5)
	raw_button_c.direction = digitalio.Direction.INPUT
	raw_button_c.pull = digitalio.Pull.UP
	button_c = Debouncer(raw_button_c)

	return (button_a, button_b, button_c);

def setup_program():
	show_screen()

button_a, button_b, button_c = setup_oled_buttons()

print("Hello, CircuitPython!")
show_screen()

red_led.value = False
board_led[0] = (0,0,0)
pixels[0] = (0,0,0)
pixels[1] = (0,0,0)
pixels[2] = (0,0,0)
pixels.show()

while True:
    if mute:
    	pixels[0] = (0,0,0)
    	pixels[1] = (0,0,0)
    	pixels[2] = (0,0,0)
    	pixels.show()
    else:
	    pixels[0] = (0,255,255)
	    pixels[1] = (0,255,0)
	    pixels[2] = (255,255,0)
	    pixels.show()

    button_a.update()
    button_b.update()
    button_c.update()
    if button_a.fell:
        print('Mute Toggle - {0} {1}'.format(mute, program))
        mute = not mute
        setup_program()

    if button_b.fell:
        print('Program + - {0} {1}'.format(mute, program))
        program = program + 1
        program = program % 8
        setup_program()

    if button_c.fell:
        print('Program - {0} {1}'.format(mute, program))
        program = program - 1
       	if program < 0:
       		program = 7
       	setup_program()

Advantages of CircuitPython over Arduino so far:

  • Improved develop-test cycle time.
  • Better feedback.

Disadvantages of CircuitPython over Arduino:

  • I keep running into issues with the reference-style docs. It’s probably worse given that I’ve worked as a professional programmer doing Python.

Posted:

Updated: