2018年03月18日

Speaker pHATとButton SHIM

speakerphat.jpg

先日のInky pHATと一緒に購入した、pimoroni Speaker pHATも組み立てて動かしてみました。
後に写っているのはButton SHIMで、これも一緒に購入したものです。

Speaker pHATはラジカセっぽいデザインにやられて入手したのですが、値段もそれほど高くないですし、Zeroシリーズはオーディオ出力が無いので、手頃な音声出力として意外と良いかもしれません。

Button SHIMは5つのボタンとフルカラーLED1つから成るデバイスで、接続はI2Cです。
サンプルにはボタン入力でalsamixerのように音量調節をするものもあり、Speaker pHATと組み合わせると本当にラジカセもどきができそうです。

SHIMは0.8mmの薄い基板で、Raspberry Piのピンヘッダに直接ハンダ付けして使います。
薄いので、さらにその上からピンソケットを接続することができます。
とはいえ、一度取り付けると外せませんので、まだ試しにつないで動作を確認しただけです。
posted by boochow at 01:47| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年03月13日

Inky pHATのための画像変換ツールを作ってみた

inkyconvertertest.jpg

先日届いたpimoroni Inky pHATですが、記事にも書いたようにPythonライブラリで扱える画像ファイルは、ちょっと特殊な形式をしています。

そこで、普通のJPEG画像等から、Inky pHAT用のPNGファイルを生成するためのツールを作成してみました。

boochow/InkyConverter

バイナリファイルは以下に置いておきます。(画像のファイル名が日本語だと開けないようです。)

InkyConverter.zip

このツールですが、とりあえず白黒だけの画像なら、以前openFrameworksを使ってArduboy用に作った画像コンバータにちょっと手を加えて画像のピクセル数を変更すれば、Inky pHAT用に使えそうだと思い、作り始めました。

さらに、元画像から赤色の領域だけを切り出せれば、それをディザリングするのも白黒画像と同じやり方でできます。
単純にRGBからRチャネルだけを取り出すと、白色でも赤色領域になってしまいます。
今回は、GやBよりもRの値がある程度大きく、かつRの値そのものがそこそこ大きい、というピクセルを赤色のピクセルと解釈する・・・という比較的単純な方法で実装してみましたが、結構イメージに近い処理が行えました。

inkyconverter.png


白黒赤の画像ができたら、これをパレット形式のPNGファイルにします。パレットは先頭から白、黒、赤の順でなければなりません。このような処理はopenFrameworksには備わっていません。

しかし、調べてみるとopenFrameworksは画像の処理についてはFreeImageというライブラリが使われており、このライブラリの機能を直接使えばパレットの制御もできそうなことが分かりました。
そこで、PNGファイルの保存の部分はFreeImageのマニュアルを調べながら作りました。

簡単にInky pHAT用の画像が作れますので、お持ちの方はぜひお試しください。
posted by boochow at 21:22| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年03月11日

電子ペーパーディスプレイInky pHATを買ってみた

inkyphat2.jpg

pimoroniから販売されているRaspberry Pi用のe-inkディスプレイ「Inky pHAT」に以前から興味があったので、買ってみました。

解像度は212×104ピクセルで、白黒赤の3色表示です。ちょっと珍しいですね。
表示面積もRaspberry Pi Zeroが隠れるほど大きいです。
また、電子ペーパーなので、書き込んだ後は電源を切っても画像は表示されたままです。
価格はDigi-Keyで2683円でした。安いとは言えない、微妙な価格ではあります。
ソフトウェアはRaspberry Pi用のPythonライブラリが提供されています。

Getting Started with Inky pHAT - Pimoroni Yarr-niversity

このライブラリで、文字の描画や画像の表示などが、PILを援用して行えるようです。
ただ、書き換えはかなり遅く、以下のビデオのような感じで、25秒くらいかかります。
演出として点滅させているわけではなさそうで、何度も描画することによって高い濃度で表示されるようになるのではないかと思われます。



画像を表示させる場合は、ファイル形式が結構面倒です。

・パレット形式、8bitインデックスカラーのPNGファイル
・パレットは「白」「黒」「赤」の順であること

という条件を満たさなくてはなりません。
パレットの色の並び順まで指定されると、なかなか面倒です。
通常、パレットの並び順は画像ソフトが勝手に決めてしまいます。パレット番号を後から変更する場合、画像を復号してピクセルの値も変更しなければならなくなりますので、パレットの並び順を自由に変更できる画像ソフトは見かけません。

マニュアルでは、GIMPを使って画像を生成してくださいということで、GIMP用のパレット定義ファイルが上記のリンクから提供されています。

私はGIMPを使わずに、以下のような方法を使いました。

1)irfanview+PNGOUTプラグインで、上記の指定どおりのパレットを作成してexportする(メニューのImage→Palette)。

2)paint.netで上記の3色を使った画像を作成し、8bit PNGとして保存する。(3色以上使ってもかまいませんが、次のステップで強制的に3色化されます。)

3)保存したファイルをirfanviewで開き、先ほど保存したパレットをimportする。

作成した画像ファイルです。

miku-inky-phat.png


irfanview用のパレットファイルも置いておきます。

inkyphat.pal

さて、このe-inkディスプレイですが、ちょっと動かしてみた感想としては、OLEDやLCDなどの代替にはなりませんが、電源を切っても絵が消えないのは面白いです。
例えば天気予報のように、定期的に更新されるだけの情報であれば、定期的にCPUを起動して情報をこのディスプレイに書き込み、処理が終わったらCPUはシャットダウンすることが可能です。
このような使い方を考えると、Raspberry Piよりも組み込み系のCPUと組み合わせるほうが相性は良いかもしれないと思います。

あと、上の画像ファイルと写真を見比べると分かると思いますが、アスペクト比が微妙に横長です。
まあこの程度は許容範囲でしょう。

ちなみにこのディスプレイモジュールの製造元はこちらのようです。型番はGDEW0213Z16となっています。

2.13 inch three-color low-power electronic paper screen GDEW0213Z16,Color EPD,E Paper Display

コントローラはIL0373というもののようです。サンプルソースはSTM32F10x用のものがダウンロードできます。

白黒赤以外に、白黒黄のディスプレイモジュールもあって、waveshareの以下のページを見ると結構いろいろな製品が出ているようです。

e-Paper - OLEDs / LCDs - Modules / Expansions

posted by boochow at 01:17| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年03月10日

Raspberry Pi bare metal MicroPython+USBホストコントローラのテスト

usb-mp-repl.png

前回、あれこれと考えたMicroPythonへのUSBキーボード接続ですが、とりあえず簡単にできそうなREPL専用の実装をやってみることにしました。

基本的には、REPLのためにシリアルポートから1文字ずつ読む関数mp_hal_stdin_rx_chr()が、USBキーボードで入力された文字を返せればOKです。
その前にまず、csudライブラリがMicroPythonの上で動作するよう環境を整える必要があります。

csudライブラリはビルドオプションとしてSTANDALONE、LOWLEVEL、DRIVERの3つが用意されています。
今回はメモリ管理をMicroPython側で行いますので、DRIVERでビルドします。

csudをDRIVERとして動作させる場合は、include/platform/platform.hで定義されている関数を環境側で用意しなければなりません。
MicroPythonにはハードウェアを抽象化するレイヤ(mphal)がありますので、その中から適切な関数を選ぶことになります。

注意が必要なのはメモリの確保とGCです。
MicroPythonのドキュメントには、メモリ確保にはpy/misc.hで定義されている「m_new, m_renew, m_del (and friends)」を使え、と書かれていますが、これで確保したメモリはGCの対象になります。
GCでクリアされないためには、確保したメモリブロックがMicroPythonのrootポインタから辿れる必要があります。
このあたりのことはフォーラムの以下のスレッドで書かれていました。

help is appreciated - memory allocated by m_malloc() is automatically free'ed - MicroPython Forum

お作法としては

・GCからメモリを保護したいポインタは、普通に変数を宣言するのではなく、mpconfigport.hの中のMICROPY_PORT_ROOT_POINTERSへ変数の宣言を追加する。
・保護したいポインタを参照する場合、常にMP_STATE_PORT()マクロで囲う。

となります。

csudの変数でstaticになっていてAllocateMemory()でメモリを確保しているものは、「Core、Host、Power、Devices」の4つのようなので、これらの変数へのポインタからなる構造体を定義し、それをroot pointersへ追加しました。

他に、USBキーコードから文字コードへの変換の処理も必要になります。
今回はとりあえず、キー配列はUSキーボードに決め打ちでテーブルを参照するようにしました。

これで、どうやらUSBキーボードから入力できるMicroPythonができました。
(まだ安定しておらず、放置しているとハングアップしてしまいますが・・・)
ラベル:MicroPython USB
posted by boochow at 19:13| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする

2018年03月04日

Raspberry Pi用ベアメタルUSBデバイスドライバ「csud」の調査(4)

ベアメタルRaspberry PiのUSBドライバの続きです。
csudで、Raspberry Pi Zero Wに直接接続したキーボードを取り外すと処理が正しく行えない問題を修正しました。
root hubからデバイスを取り外した際の「変更あり」フラグが設定できていなかったのが原因でした。

Raspberry Pi Zero WにUSBハブをつないで、そこに接続したキーボードを外したときは、正常に取り外し処理が行われます。
この処理は、概ね以下のような流れで行われています。

UsbCheckForChange
→HubCheckForChange
 →HubCheckConnection
  →HubPortGetStatus
   →UsbControlMessage
    →HcdSumbitControlMessage
     HcdChannelSendWait // Setup
     HcdChannelSendWait // Data
     HcdChannelSendWait // Status
   HubPortConnectionChanged
   →HubPortGetStatus
    HubChangePortFeature

HubPortGetStatusでデバイスの接続状況を確認しています。
この処理はデバイスへUSB経由でStatusコマンドを送ることで行われています。

一方、root hubからデバイスを取り外す場合はHcdSumbitControlMessageの内部で以下のように分岐しています。
この場合は、接続処理は正しく行われますが、取り外し処理が行われません。

    if (pipe.Device == RootHubDeviceNumber) {
return HcdProcessRootHubMessage(device, pipe, buffer, bufferLength, request);
}

この結果、HcdSumbitControlMessage以降の流れは以下のようになります。

    →HcdSumbitControlMessage //ここまでは同じ
     →HcdProcessRootHubMessage
      switch (request->Request) {
      case GetStatus:
       switch (request->Type) {
       case 0xa3:
        // Statusを取得
       }
      }

root hubのポート(Zero WではオンボードのUSBコネクタに相当)の接続状況のチェックはHcdProcessRootHubMessageで行っていますが、この処理はUSBでStatusメッセージを送る代わりに、USBコントローラのレジスタ(0x0440)の値を読み出しています。

詳しく見てみると、USBコントローラのレジスタには、USBポートの状況を表す2つのフラグ

・Port.Connect(bit 0; デバイスが接続されていればtrue)
・Port.ConnectDetected(bit 1; デバイスが新たに接続されたときにtrue)

があり、後者はデバイスが「なし→あり」のときはtrueになりますが「あり→なし」のときはtrueにならないようです。
しかし、csudの実装ではPort.ConnectDetectedのレジスタ値を「ポートの接続状況に変化があった」フラグとして用いているため、デバイスの取り外しが検出できていませんでした。

このあたり、ultiboのフォーラムの以下のやりとりが参考になりました。

usb keyboards not recognized on "Raspberry PI A+" - ultibo.org

この議論に対応する、ultiboのUSBドライバのパッチは以下のコミットと思われます。

Fixes for Raspberry Pi A/A+/Zero USB handling ・ ultibohub/Core@ba3c908

csudとはだいぶ構成が違うライブラリなので、csudへそのまま適用するのは無理そうですが、コメントを読むだけでもヒントになりそうです。

csudでの上記の不具合の解決方法ですが、HubPortGetStatusを呼ぶ前と呼んだ後とでPort.Connectの値の変化をチェックするようにしました。
パッチを当てたcsudは以下のリポジトリで公開しています。

boochow/csud: Chadderz's Simple USB Driver for Raspberry Pi

なお、時間がたつとハングアップする問題は、Pollループに少しウエイトを入れるようにしたら起こらなくなったので、デバイスへの過負荷が原因だったのかもしれません。

これで、Pi Zero WにUSBキーボードを直結しても問題なく動作するようになったと思われます。
ラベル:USB
posted by boochow at 13:38| Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする
人気記事