せっかく、ロータリエンコード(I2C)を試したので、同じくI2Cで動く128x32のOLED液晶のssd1306を連動してみる。

それぞれの記事はこれ。

I2C 接続

I2C は、同じバス上に複数のデバイスを接続することができる。

試しに、I2Cのテストプログラムでデバイスを検出してみる。

i2c_test.py

python
from board import *
import busio
import displayio
import adafruit_ssd1306


sda = GP2
scl = GP3

i2c = busio.I2C(scl, sda)

while not i2c.try_lock():
    pass

print(i2c.scan())

実行

bash
$ ampy -p /dev/tty.usbmodem14123301 run i2c_test.py
[54, 60]

あらかじめ資料でみていたので、正しく検出できたことがわかった。

  • ssd1306 60=0x3C
  • Adafruit I2C QT Rotary Encoder with NeoPixel - STEMMA QT / Qwiic 54=0x36

表示の仕様

ロータリーエンコーダーのドライバは、初期値 0 で時計回りで+ 、 逆統計まわりで - に変化した値を返す。

ということで、Volumeとして棒グラフ的なものを表示してみる。 ローターリーエンコーダの押し込みボタンは、押したら付属のLEDが赤く光るようにする。

program

  • SDA = GP2
  • SCL = GP3
volume.py · Gistpython
import board
import busio
import digitalio
import time

from adafruit_seesaw import seesaw
from adafruit_seesaw.neopixel import NeoPixel
from adafruit_seesaw.digitalio import DigitalIO
from adafruit_seesaw.rotaryio import IncrementalEncoder
import adafruit_ssd1306

import usb_midi
import adafruit_midi
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn

try:
    import _pixelbuf
except ImportError:
    import adafruit_pypixelbuf as _pixelbuf

class RotaryAndSD1306:

    def __init__(self, sda=board.GP2, scl=board.GP3):
        i2c = busio.I2C(scl, sda)

        #
        # rotary encoder
        # https://shop.pimoroni.com/products/adafruit-i2c-qt-rotary-encoder-with-neopixel-stemma-qt-qwiic
        #
        self.seesaw = seesaw.Seesaw(i2c, 0x36)
        self.encoder_ = IncrementalEncoder(self.seesaw)
        self.switch_ = DigitalIO(self.seesaw, 24)

        self.pixel_ = NeoPixel(self.seesaw, 6, 1)
        self.pixel_.fill(_pixelbuf.colorwheel(0))
        self.pixel_.brightness = 0.0

        #
        # ssd1306 display
        #
        width = 128
        height = 32
        self.disp_ = adafruit_ssd1306.SSD1306_I2C(width, height, i2c)
        self.display_init()

    def set_led(self, bright):
        self.pixel_.brightness = bright

    def display_init(self):
        self.disp_.fill(0)
        self.disp_.rect(0, 0, 128, 32, 1)

        self.disp_.text("Volume", 4, 4, 1)
        self.disp_.show()

    def display(self, position):
        self.disp_.fill_rect(4, 18, 120, 12, 0)
        self.disp_.fill_rect(4, 18, position, 10, 1)
        self.disp_.line(4 + position + 4, 18, 4 + position + 4, 28, 1)
        self.disp_.show()

    def get_switch(self):
        # press=False or release=True button
        return self.switch_.value

    def get_position(self):
        # rotary left/right
        return self.encoder_.position

if __name__ == "__main__":

    mk = RotaryAndSD1306()

    last_position = -1
    while True:
        position = mk.get_position()
        button_released = mk.get_switch()

        if button_released:
            # released button and light off
            mk.set_led(0.0)
        else:
            # pressed button and light on
            mk.set_led(0.5)

        if position != last_position:
            mk.display(position)

        last_position = position

実行

bash
ampy -p /dev/tty.usbmodem14123301 run volume.py

ローターリーエンコードがグルグル回すと、Volume 表示も動く。