以前に作った midi keyboard

タクトスイッチは押しにくいので、ちょっといいキースイッチを購入

売り物はPCB基板(neopixel1個付き)。キースイッチとキーキャップは、別途用意する。

キースイッチ、最初はクリック感のある茶軸を使っていたが、クリック感なしの赤軸のほうがしっくり来た。

neopixelがついてるので、キーキャップは透明なものを利用

circuitpython driver

探したけどみつからない。

キーなので、GPIO 1個につき1KEYで、PULL UPのINPUT制御。 ここいらは、以前の記事と同じ。

neopixel は、組み込まれているので、特に追加driverはなし。

基板に IN と OUT と書いてるPINが、制御PINとして制御すればOK

IN/OUT は基板の横方向と縦方向の両方にあるが、自分はPINが5個ある方向のやつを使った。

GPIO

配線

program

キーを押すと、midi に出力するプログラム。 KEY1 を押すとC2 、 KEY2 を押すと D2 をmidi出力する。

プログラムの 以下の部分を変えれば、スキなnoteに変更できる。

python
37 # key1 and key2 note
38 CHORDS = [C2, D2]
midi_drum.py · Gistpython
import board
import busio
import digitalio
import time

import neopixel

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

# pitch class
C2 = 50
D2 = 52
E2 = 54
G2 = 55
A3 = 57
B3 = 59
C3 = 60
D3 = 62
E3 = 64
F3 = 65
F3S = 66
G3 = 67
A3 = 69
B3 = 71
C4 = 72
D4 = 74
E4 = 76

# key1 and key2 note
CHORDS = [C2, D2]

# for neopixel color
RED = (100, 0, 0)
BLUE = (0, 0, 100)
GREEN = (0, 100, 0)
BLACK = (0, 0, 0)

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

        #
        # key
        # https://shop.pimoroni.com/products/neokey-socket-breakout-for-mechanical-key-switches-with-neopixel-for-mx-compatible-switches
        #

        # KEY1=GP26, KEY2=GP27, NeoPixel=GP28
        self.keys_ = []
        for pin in (board.GP26, board.GP27):
            key = digitalio.DigitalInOut(pin)
            key.switch_to_input(pull=digitalio.Pull.UP)
            self.keys_.append(key)
        self.pixels_ = neopixel.NeoPixel(board.GP28, 2, auto_write=False)
        self.set_key_pixel([0, 0])  # init black

        #
        # USB MIDI up on channel 0
        # doc: https://circuitpython.readthedocs.io/projects/midi/en/latest/api.html
        #
        self.midi_ = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)

    def set_key_pixel(self, statuses):
        self.pixels_[0] = BLACK
        self.pixels_[1] = BLACK
        if statuses[0]:
            self.pixels_[1] = BLUE
        if statuses[1]:
            self.pixels_[0] = GREEN

        self.pixels_.show()

    def is_key_press(self):
        is_pressed = []
        for key in self.keys_:
            # press False, release True
            is_pressed.append(not key.value)
        return is_pressed

    def set_led(self, status):
        if status:
            self.pixel_.brightness = 0.3
        else:
            self.pixel_.brightness = 0.0

if __name__ == "__main__":

    mk = MidiDrum()

    current_key_statuses = [False, False]
    while True:

        # get current key press or release
        is_presses = mk.is_key_press()
        is_changes = [False, False]

        # check changed to press or release
        for no, is_press in enumerate(is_presses):
            if current_key_statuses[no] != is_press:
                is_changes[no] = True
                current_key_statuses[no] = is_press

        if is_changes[0] or is_changes[1]:
            # changed!
            mk.set_key_pixel(current_key_statuses)

            for no in range(len(CHORDS)):
                if not is_changes[no]:
                    continue
                is_pressed = current_key_statuses[no]
                print("key {}  press {} {}".format(no, is_pressed, CHORDS[no]))
                if is_pressed:
                    mk.midi_.send(NoteOn(CHORDS[no], 127))
                else:
                    mk.midi_.send(NoteOff(CHORDS[no], 0))

動作確認

Mac の GarageBand を起動して、Track に適当なDrumを設定する。 本当にデータが送られているかは、GarageBandのソフトウェアキーボードを表示する。

実際には、 Show Musical Typing メニューか command + k 。

作成したプログラムを実行し、KEYを押すと、ソフトウェアキーボード上で該当する C2 、 D2 がクリックエフェクト表示される。

音が鳴らない時は、たまたま選択したDrumの C2 , D2 に音源が割り振られていないかもしれないので、 最初は Drum Kit - East bay がお薦め。