Raspberry PiでのRaspberry Pi PicoのMicroPython開発環境はどうなの?(2021.06)

先日のエントリではRaspberry Pi Pico(以下Pico)でLチカの次の段階ということでUSBデバイス(キーボード)を作ってみました。そのときの開発環境はWindowsPCにVisual Studio Codeをインストールして、USBストレージとして見えるPico(MicroPython環境設定済み)のファイルを編集するというようなものでした。それでも割と問題ないのですが、折角Picoを使っているので、開発環境すべてをRaspberry Pi印でそろえるっていうのはどうだろうかと考え、今回のこのようなものを書いてみました。

Raspberry PiPicoがあれば格安で開発できるんじゃね?という安易な考え方ではありますが、子どもたち向けにやるにはかなり価格的なハードルが下がるのかなという観点でもあります。

では、現時点(2021年6月)での開発環境を見てみようと思います。

過去エントリー参考

uepon.hatenadiary.com

続きを読む

Raspberry Pi Picoをカスタムキーボード化して「くぁwせdrftgyふじこlp」キーボード爆誕!

f:id:ueponx:20210610002739p:plain

(2021.06.11)コードの記述が短縮できたので追記しました

少し前からRaspberry Pi Pico(以下Pico)のネタを書いていますが、そろそろやろうとしていた、キーボード化に挑戦してみます。 んで、とりあえずはマクロキー化をする感じで考えていましたが、少しネタっぽい感じで「くぁwせdrftgyふじこlp」というフレーズを1キーで入力できる、バカキーボードを作ってみることにします。基本的なプログラミングに関しては、ほぼ同じなので、これを見ながら自分のお好みのものを作ってもらえればと思います。

早速、その過程を記載していこうと思います。

まずはLチカ

以前のエントリーではREPL環境でのインタプリタでLチカを行っていましたが、今回はファイルにMicroPythonのコードを書いて実行していこうと思います。PicoをUSB接続するとストレージとして認識されるのでその中にあるcode.pyを編集していくことになります。

※RaspberryPiで開発環境を整えるためにThonny Python IDEMU Editorを使おうかなと思ったのですが、普通にUSBストレージ内のファイルをVisual Studio Codeで編集して保存するだけで開発できたので、そのまま開発していこうと思います。RaspberryPiでの開発環境については別のエントリーで言及しようかと

USBストレージ内のcode.pyというファイルを編集するだけでファイルの中身が自動的に実行されます。ネット情報ではmain.pyというファイルでもいいのかなと思ったのですが、code.pyのほうが優先されるようです。

まずはLチカを行ってみます。本体のLEDのはGP25として定義されています。ではこのLEDを点灯させるコードを書いていこうと思います。

本体LEDを使用してLチカ

import digitalio
from board import *
import time

led = digitalio.DigitalInOut(GP25)
led.direction = digitalio.Direction.OUTPUT

while True:
    led.value = True
    time.sleep(0.1)
    led.value = False
    time.sleep(0.1)

上記のコードで本体のLチカを行うことができます。基本的にはIOピンを出力設定をして、on/offを設定するだけで点滅ができます。

本体上のLED位置

f:id:ueponx:20210610000652p:plain

Lチカの様子 youtu.be

そこまで難しくはありません。

タクトスイッチを入れる

バカデバイスとはいっても自作キーボードなのでやっぱりボタンが必要です。そこでタクトスイッチをIOに接続して、それを押したらLEDを点灯させてみます。

GP13ピンにタクトスイッチを接続して、プルダウンモードで動作をさせます。(押したときにON=Trueになる)

f:id:ueponx:20210609235610p:plain

今回は少し大きめのタクトスイッチがあったので、それを使ってみました。もちろん一般的なタクトスイッチでも動作には問題ありません。

f:id:ueponx:20210610004155j:plain

タクトスイッチを押すと本体のLEDをLチカさせる

import board
import digitalio

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.GP13)
button.switch_to_input(pull=digitalio.Pull.DOWN)

while True:
    led.value = button.value

動作の様子

youtu.be

あともう少しでキーボードが完成になります。

PicoをUSBキーボード化する

PicoをUSBキーボード化するにはライブラリが必要になります。USBストレージのlibディレクトリにAdafruit HID Libraryをコピーすることでライブラリのインストールができます。

ライブラリのダウンロード

ライブラリに関しては以下のリンクからダウンロードできます。CircuitPythonのバージョンによってファイルが異なるので、導入したバージョンをみてファイルをダウンロードして展開を行ってください。

circuitpython.org

自分は以下のuf2ファイルを使用してMicroPython環境を作成したのでBundle Version 6.x側をダウンロードしました。

f:id:ueponx:20210610220032p:plain

f:id:ueponx:20210610215924p:plain

ダウンロードが終わったら、展開をしておきましょう。ライブラリもかなり大量のファイルがあるのでかなりサイズが大きいです。

f:id:ueponx:20210610223253p:plain

Picoへライブラリーをコピー

USBのデバイス化をおこなうライブラリは先程のファイルを展開した中のadafruit_hidフォルダがあるので、USBストレージのlibフォルダにコピーします。他所の情報ではコピーするとは書いてあったのですが、ファイル単体なのかフォルダごとなのかがわからない記述も多かったのですが、試したところ「フォルダごとコピーすればOK」だったようです。

コピー後のツリー表示は以下のようになっていれば動作します。

f:id:ueponx:20210610001323p:plain

f:id:ueponx:20210610001131p:plain

USBのHIDドライバもかなり種類がありますね。

f:id:ueponx:20210610001134p:plain

「くぁwせdrftgyふじこlp」キーボードを作る!

ライブラリファイルのコピーが終わったらあとはcode.pyを以下の様に編集していきます。

先程のタクトキーを押したらLEDが点灯するというのにキー操作を行う処理を追加すればほぼ終わりです。

タクトスイッチを押すと、キーボードで「くぁwせdrftgyふじこlp」を入力する(入力中は本体のLEDを点灯させる)

import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

def keyInput(keycodeName):
    keyboard.send(keycodeName)

keyboard = Keyboard(usb_hid.devices)

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.GP13)
button.switch_to_input(pull=digitalio.Pull.DOWN)
led.value = False

while True:
    if button.value:
        led.value = True
        # 日本語変換モードに切り替える
        # keyboard.send(Keycode.ALT, Keycode.GRAVE_ACCENT)

        keyInput(Keycode.Q)
        keyInput(Keycode.A)
        keyInput(Keycode.W)
        keyInput(Keycode.S)
        keyInput(Keycode.E)
        keyInput(Keycode.D)
        keyInput(Keycode.R)
        keyInput(Keycode.F)
        keyInput(Keycode.T)
        keyInput(Keycode.G)
        keyInput(Keycode.Y)
        keyInput(Keycode.H)
        keyInput(Keycode.U)
        keyInput(Keycode.J)
        keyInput(Keycode.I)
        keyInput(Keycode.K)
        keyInput(Keycode.O)
        keyInput(Keycode.L)
        keyInput(Keycode.P)
        keyInput(Keycode.ENTER)

        # 日本語変換モードから英数モードに切り替える
        # keyboard.send(Keycode.ALT, Keycode.GRAVE_ACCENT)
        led.value = False

adafruit_hid.keyboard()の引数にキーの名前をしてすればキーモード入力ができます。以下が参考になります。

circuitpython.readthedocs.io

キーコードは以下が参考になると思います。

github.com

ちなみに今回は入力時には日本語入力モード変換にしてあるという前提で処理を記述しています。もし英数入力モードから日本語入力モードに変換する部分も入れたい場合にはコメントアウトしている部分を処理に入れてください。日本語109キーボードにある【全角/半角】キーは使えないので、USキーボード同様に【ALT】キー+ 【`】キーで日本語入力モードに変えています。この処理がトグルなので、元の状態関係なく日本語入力にして元に戻すにはWindowsの場合はIMEなどの設定を変更する必要があります。(ちょっと面倒)

あと【`】はバッククォートだと思っていたのですが、キーコードとしてはGRAVE_ACCENTを使うようです。

ja.wikipedia.org

では動作させてみます。

youtu.be

追記(2021.06.11)

先程のコードではいちいち1つのキーを押下するのにコードを書いていましたが、さすがにこれではコードが大量になってしまいます。そこで、USB_HIDにあるキーボードレイアウトというモジュールadafruit_hid.keyboard_layout_usを使用することで、キーコードの指定ではなく文字列を引数にすることで簡単に入力ができます。特殊キーの同時入力はできませんが、シフトキーなど押しながらの入力に関しては文字を判別してキーコードを判別してくれるのでかなり記述は楽になります。

adafruit_hid.keyboard_layout_usモジュールを使用して書き直す

import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS #追加部分

def keyInput(keycodeName):
    keyboard.send(keycodeName)

keyboard = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(keyboard)  #追加部分

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.GP13)
button.switch_to_input(pull=digitalio.Pull.DOWN)
led.value = False

# 「くぁwせdrftgyふじこlp」キーボード

while True:
    if button.value:
        led.value = True
        # 日本語変換モードに切り替える
        # keyboard.send(Keycode.ALT, Keycode.GRAVE_ACCENT)

        layout.write('qawsedrftgyhujikolp\n') #変更部分

        # 日本語変換モードから英数モードに切り替える
        # keyboard.send(Keycode.ALT, Keycode.GRAVE_ACCENT)
        led.value = False

これでかなりコードが短くなりました。あくまでもキーコードに関してはUS配列のキーボードのものを踏襲するので日本語109などとキーの刻印が違うときには少し挙動が変わるので注意が必要かもしれません。

おわりに

PicoをキーボードエミュレーションさせることでUSBキーボードにすることができました。タクトスイッチにキーバインドを割り当てることで目的のマクロキーボードを作る事ができます。キーボード以外にもHIDデバイスである、ゲームパッドバイスにすることやマウスとしても使用することができるので、ちょっとしたデバイスならすぐできてしまうのかも。

ゲームなどのキーボードを複数使うような操作もこれならできちゃいそうです。チート行為になる可能性があるのでその辺りは注意してください。

せっかく作った「くぁwせdrftgyふじこlp」キーボードですがそう使う機会はなさそうですけどねw

参考

uepon.hatenadiary.com

Raspberry Pi PicoをMicroPython環境(CircuitPython化)した後に元に戻す方法

前回のエントリでは、Raspberry Pi Pico(以降Picoと呼ぶ)をMicroPython環境で開発できるように設定をしました。

uepon.hatenadiary.com

このままMicroPython環境のままでもいいのですが、ArduinoIDEでも開発したいなあと思ったときに元に戻せないのは結構痛いです。そこで、元にちゃんと戻すことができるのか確認してみようと思います。あまり、そのあたりのことを書いたものがなかったので、本当に戻るのかなと不安もありましたし。

実は3枚セットで購入していたので初期状態のものも手元にあるので比較は簡単でした。 では、実際に行ってみます。

続きを読む

Raspberry Pi PicoでLチカやってみた(MicroPython版)

今更ながらRaspberry Pi Picoが手元に届いたのでちょっと触ってみたいと思います。発売当初に日本からだと入手性が悪いかな~と思って海外サイトで購入したのですが、届いたのが日本発売の2ヶ月以上後だったのは悲しい思い出でした。せっかく届いたので個人的にはこれを使用してショートカット的なキーボードを作ってみたいと思っています。近いものとしては以下のような商品になるかなと思います。

ここまでのものでなくても、遊舎工房さんでも以下のような商品があるので、こちらを使うという手もあるかなと思います。

f:id:ueponx:20210608004816p:plain

そこをあえてRaspberry Pi Picoで自作してみるという感じでしょうか。ただ、単にArduinoIDE環境をつかって開発を行っても新しい学びはなさそうなので(?)今回はMicroPythonを使用する環境でやってみたいと思います。

f:id:ueponx:20210608000651p:plain

今回は環境設定の(その1)という感じでMicroPythonのREPL環境を設定してみます。公式サイトの以下のページを参考にして設定を行いました。

https://www.raspberrypi.org/documentation/rp2040/getting-started/

f:id:ueponx:20210607221909p:plain

すでに、結構な方がRaspberry Pi Pico(以下Pico)のエントリーを書いていると思いますが、Picoの主な機能は次のようになっています。

  • RP2040 microcontroller chip designed by Raspberry Pi in the United Kingdom
  • Dual-core Arm Cortex M0+ processor, flexible clock running up to 133 MHz
  • 264KB of SRAM, and 2MB of on-board Flash memory
  • Castellated module allows soldering direct to carrier boards
  • USB 1.1 with device and host support
  • Low-power sleep and dormant modes
  • Drag-and-drop programming using mass storage over USB
  • 26 × multi-function GPIO pins
  • 2 × SPI, 2 × I2C, 2 × UART, 3 × 12-bit ADC, 16 × controllable PWM channels
  • Accurate clock and timer on-chip
  • Temperature sensor
  • Accelerated floating-point libraries on-chip
  • 8 × Programmable I/O (PIO) state machines for custom peripheral support

f:id:ueponx:20210607221929p:plain

あの値段でここまでの機能が搭載されていると思うと、本当に安いなあと思います。

www.switch-science.com

以下のリンクで機能詳細が記載されたpdfファイルがあるのでこちらもチェックです。

https://www.raspberrypi.org/documentation/rp2040/getting-started/static/64b50c4316a7aefef66290dcdecda8be/Pico-R3-SDK11-Pinout.svg

続きを読む

Dockerのコンテナからホスト側アプリへの通信を行う

Dockerコンテナ側からホストOS側のプログラムと通信をしたいなあと思うことがあったので、ちょっと調べて見ました。もちろん、Docker側のネットワークIPを指定すれば、アクセスできますけどもう少し簡単したいなあと思ってのことです。

Dockerで設定された名前を使ってアクセスを行う

Docker Desktop for WindowsDocker Desktop for Macでしか使えないらしいですが、Dockerコンテナ側のOSからhost.docker.internalを名前指定してアクセスするとDocker Desktop側のホストOSと通信を行うことができるようです。

f:id:ueponx:20210602002416p:plain

参考 docs.docker.com

これが求めていた機能だった感じですね。さすがにIPアドレスを覚えるというのは現実的ではないですし。

実験

まずはホスト側でHTTPサーバを起動したいのでpython3のワンライナーを使って起動しておきます。ローカル側からcurlコマンドでアクセスするのも確認しておきます。

ホスト側でHTTPサーバを起動

PS> python3 -m http.server 8080

f:id:ueponx:20210601232959p:plain

続いてはDockerのコンテナを起動します。今回はほとんど機能が必要ないのでalpineのイメージを使用して起動しています。

コンテナ側のOSを起動

PS> docker run -it --rm  alpine

f:id:ueponx:20210601232956p:plain

OSが起動したらcurlをインストールしてから、host.docker.internalにアクセスを行います。

PS> docker run -it --rm alpine

# apk add curl
# curl http://host.docker.internal:8080/

f:id:ueponx:20210602001752p:plain

もちろん、pingコマンドからでもちゃんとアクセスできています。

f:id:ueponx:20210601233016p:plain

コンテナ側の/etc/hostsファイルを起動オプションを使って変更し、アクセスを行う

2つ目の方法としては

dockerコマンドの起動オプションに以下のオプションスイッチを追加することで、/etc/hostsファイルlocalhostの名前でホスト側のDockerネットワークのIPアドレス追加することできます。

※ 追加するオプション --add-host=localhost:【ホスト側のDockerネットワークのIPアドレス】

Dockerホスト側のネットワークのIPアドレス172.28.224.1だった場合の実行例

PS> docker run -it --rm --add-host=localhost:172.28.224.1  alpine

あまりlocalhost固執する理由が自分にはわからないのですが、開発上の理由はあるのかなと思うのでこうしますが、もちろん別のホスト名をつけることも可能です。

Dockerホスト側の名前をtest.devとして、ネットワークのIPアドレス172.28.224.1だった場合の実行例

PS> docker run -it --rm --add-host=test.dev:172.28.224.1  alpine

実験

先程と同様にアクセスのテストを行ってみます。まずはpython3でワンライナーのサーバーを起動しておきます。

f:id:ueponx:20210601233007p:plain

あとはコンテナを先程のオプションをつけて起動します。

PS> docker run -it --rm --add-host=test.dev:172.28.224.1  alpine

# apk add curl
# curl http://test.dev:8080/

f:id:ueponx:20210601233019p:plain

アクセス後のホスト側のHTTPサーバーのログを確認するとちゃんとアクセスができています。

f:id:ueponx:20210601233003p:plain

おわりに

Dockerコンテナ側からホスト側のアプリへのアクセスは問題なくできるようになりました。やっぱり簡単なのは、ホストOS側の環境の制限はありますが、host.docker.internalを使ってのアクセスでしょうか。IPアドレスを覚えなくて良い点が利点です。 あとはコードへの埋め込みなどを考えるのであれば/etc/hostsを変更してのホスト名を変える手もいいのかなと思います。

/* -----codeの行番号----- */