The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

The New Hotness

  • Raspberry Pi Rotary Encoder: Knob Switch Key

    The rotary encoder knob I’m using for these tests has a pushbutton switch in its shaft:

    RPi rotary encoder - improved test fixture
    RPi rotary encoder – improved test fixture

    Now that I know where to look, it turns out there’s a Raspberry Pi overlay for that:

    Name:   gpio-key
    Info:   This is a generic overlay for activating GPIO keypresses using
            the gpio-keys library and this dtoverlay. Multiple keys can be
            set up using multiple calls to the overlay for configuring
            additional buttons or joysticks. You can see available keycodes
            at https://github.com/torvalds/linux/blob/v4.12/include/uapi/
            linux/input-event-codes.h#L64
    Load:   dtoverlay=gpio-key,<param>=<val>
    Params: gpio                    GPIO pin to trigger on (default 3)
            active_low              When this is 1 (active low), a falling
                                    edge generates a key down event and a
                                    rising edge generates a key up event.
                                    When this is 0 (active high), this is
                                    reversed. The default is 1 (active low)
            gpio_pull               Desired pull-up/down state (off, down, up)
                                    Default is "up". Note that the default pin
                                    (GPIO3) has an external pullup
            label                   Set a label for the key
            keycode                 Set the key code for the button
    
    

    Snuggle the button configuration next to the encoder in /boot/config.txt:

    dtoverlay=rotary-encoder,pin_a=20,pin_b=21,relative_axis=1,steps-per-period=2<br>dtoverlay=gpio-key,gpio=26,keycode=83,label="KNOB"
    

    I haven’t yet discovered where the label text appears, because I picked a keycode defining the button as the decimal point key on a numeric keypad. Perhaps one could create a unique key from whole cloth, but that’s in the nature of fine tuning. In any event, pressing / releasing the button produces key-down / key-up events just like you’d get from a real keyboard.

    The four pins required for the encoder + switch make a tidy block at the right (in this view, left as shown above) end of the RPi’s header:

    Raspberry Pi pinout
    Raspberry Pi pinout

    If you needed the SPI1 hardware, you’d pick different pins.

    Reboot that sucker and another input device appears:

    ll /dev/input/by-path/
    total 0
    lrwxrwxrwx 1 root root 9 Oct 18 10:00 platform-button@1a-event -> ../event0
    lrwxrwxrwx 1 root root 9 Oct 18 10:00 platform-rotary@14-event -> ../event2
    lrwxrwxrwx 1 root root 9 Oct 18 10:00 platform-soc:shutdown_button-event -> ../event1

    As with the encoder device, the button device name includes the hex equivalent of the pin number: 26 decimal = 0x1a.

    Run some code:

    # Keypress from Raspberry Pi GPIO pin using evdev
    # Add to /boot/config.txt
    #  dtoverlay=gpio-key,gpio=26,keycode=83,label="KNOB"
    
    import evdev
    
    b = evdev.InputDevice('/dev/input/by-path/platform-button@1a-event')
    print('Button device: {}'.format(b.name))
    
    print(' caps: {}'.format(b.capabilities(verbose=True)))
    print(' fd: {}'.format(b.fd))
    
    for e in b.read_loop():
        print('Event: {}'.format(e))
        if e.type == evdev.ecodes.EV_KEY:
            print('Key {}: {}'.format(e.code,e.value))
    
    

    Which produces this output:

    Button device: button@1a
    caps: {('EV_SYN', 0): [('SYN_REPORT', 0), ('SYN_CONFIG', 1)], ('EV_KEY', 1): [('KEY_KPDOT', 83)]}
    fd: 3
    Event: event at 1603036309.683348, code 83, type 01, val 01
    Key 83: 1
    Event: event at 1603036309.683348, code 00, type 00, val 00
    Event: event at 1603036310.003329, code 83, type 01, val 00
    Key 83: 0
    Event: event at 1603036310.003329, code 00, type 00, val 00

    All in all, that was easy …