Simple control using momentary buttons

Sometimes I want a simple button to perform a specialized function. While the current onboard button is incredibly useful, the functionality that it offers cannot be customized. I had some project ideas that required one or more custom inputs, so I decided to use the available GPIO digital input pins with momentary buttons.

The following examples demonstrate how I’ve been implementing buttons in costumes and other projects lately.

Example - Basic Button

Here I connected a momentary button to the 3.3v power pin and GPIO pin 26 (1026).

To make use of this, I created the following pattern that reads the state of the pin and behaves conditionally based on buttonValue.

// Example of a momentary button connected to a GPIO pin
//
// Each time the button is pressed, the value of 'buttonValue' 
// should be 1

export var buttonValue // Use export to watch values in the PixelBlaze editor

var BUTTON_PIN = 26

pinMode(BUTTON_PIN, INPUT_PULLDOWN)

export function beforeRender(delta) {
    buttonValue = digitalRead(BUTTON_PIN);
}

export function render(index) {
    hsv(.0, 0, 0)
  
    if (buttonValue == 1) {
        hsv(.97, 1, 1) // Set color if button is pressed
    }
}

Example - Toggle Button

One step further is to create a button with toggle behavior.

The toggle behavior is achieved by using the value of buttonToggle.

// Example of how to create a logical toggle using a momentary 
// button connected to a GPIO pin.
//
// Each time the button is pressed, the value of 'buttonToggle'
// alternates between 0 and 1.
//
// 0 == OFF
// 1 == ON

export var buttonValue, buttonPressed, buttonToggle // Use export to watch values in the PixelBlaze editor

var BUTTON_PIN = 26
pinMode(BUTTON_PIN, INPUT_PULLDOWN)

var TOGGLE_OFF = 0
var TOGGLE_ON = 1

export function beforeRender(delta) {
    buttonValue = digitalRead(BUTTON_PIN)
    if (buttonValue == 1) {
        if (buttonPressed == 0) {
            buttonPressed = 1
            buttonToggle = (buttonToggle == TOGGLE_OFF) ? TOGGLE_ON : TOGGLE_OFF
        }
    } else {
        buttonPressed = 0
    }
}

export function render(index) {

    hsv(.0, 0, 0)

    if (buttonToggle == TOGGLE_ON) {
        hsv(.97, 1, 1) // Set color if button toggle is on
    }
}

Example - Multiple Buttons

Either button style can be implemented multiple times to create more inputs.

// Example of multiple momentary buttons connected to GPIO input pins
//

export var buttonOneValue, buttonTwoValue, buttonThreeValue
// Use export to watch values in the PixelBlaze editor

var BUTTON_ONE_PIN = 26
var BUTTON_TWO_PIN = 25
var BUTTON_THREE_PIN = 0

pinMode(BUTTON_ONE_PIN, INPUT_PULLDOWN)
pinMode(BUTTON_TWO_PIN, INPUT_PULLDOWN)
pinMode(BUTTON_THREE_PIN, INPUT_PULLDOWN)

export function beforeRender(delta) {
    buttonOneValue = digitalRead(BUTTON_ONE_PIN)
    buttonTwoValue = digitalRead(BUTTON_TWO_PIN)
    buttonThreeValue = digitalRead(BUTTON_THREE_PIN)
}

export function render(index) {
    hsv(.0, 0, 0)

    if (index == 0) {
        if (buttonOneValue == 1) {
            hsv(.97, 1, 1) // Red'ish
        }
    }
    if (index == 1) {
        if (buttonTwoValue == 1) {
            hsv(.15, 1, 1) // Yellow'ish
        }
    }
    if (index == 2) {
        if (buttonThreeValue == 1) {
            hsv(.3, 1, 1) // Green'ish
        }
    }
}
7 Likes

Yessssss thank you so much for this!

Would love a rotary encoder for brightness/pattern control.

I put some 10k potentiometers on pins 1033, 1034, 1035 and analogRead() returns a value between 0 and 1!

Mine are sliders but I’m pretty sure there are rotary potentiometers out there :smiley:

2 Likes

Example - Rotary Encoder

Here is a simple rotary encoder.

I connected the “CLK” pin to GPIO pin 26, and the “DT” pin to GPIO 25.

var CLK_PIN = 26
var DT_PIN = 25

export var currentA
export var currentB
export var lastA
export var counter

pinMode(CLK_PIN, INPUT) // Input A (CLK)
pinMode(DT_PIN, INPUT) // Input B (DT)

export function beforeRender(delta) {

    currentA = digitalRead(CLK_PIN)
    currentB = digitalRead(DT_PIN)

    if (currentA != lastA) {
        // Moved
        if (currentA != currentB) {
            // Clockwise
            counter++
        } else {
            // CounterClockwise
            counter--
        }

        lastA = currentA
    }
}

export function render(index) {
    hsv(.0, 0, 0)

    if (index < counter) {
        hsv(.7, 1, 1)

    }
}
4 Likes

This is perfect, thanks! I bought some rotary encoders but haven’t had the chance to sit down and debug them. Your code gives me the energy to try!

1 Like

Is this a “raw” rotary encoder or something mounted to a board which has denounce logic built in?

The encoder is attached to a breadboard friendly breakout board.

Erm, I meant “debounce” logic, obviously :joy:. (But thanks for the link!)

So, I was browsing around to see how/what people have done with with LED controllers recently, trying to decide if pixelblaze was the way to go for me, and who do I see here? @misterconnolly !

Long time no talk, Brian! Sorry to hijack your thread, but the forum bot won’t let me DM you yet, and the email address I have for you seems to be old.

-MH

I decided to max out all the IO ports. It makes for a fun analog led control board.

2 Likes