あっきぃ日誌

鉄道ブログのような技術系ブログのようななにか

Raspberry Pi Pico WとPico Inky Packで天気予報を表示する

昨日届いたRaspberry Pi Pico Wのうち、ピンヘッダーをつけたやつを、以前買ったPico Inky Packに取り付けました。

で、こいつで天気予報を表示するやつを作るお話です。


元ネタ

元ネタは昔から動いている普通のラズパイ向けのやつです。今も現役なので、今回作ったもので置き換えるというわけではないです。

Inky pHATで天気予報を出す(常設ラズピッピがカオスになった話) - あっきぃ日誌

Inky pHATで天気を出すスクリプトを公開しました - あっきぃ日誌

akkiesoft.hatenablog.jp

Pico W向けのCircuitPythonフラッシュストレージ小さすぎ問題

去年の12月からやりたいと考えていて、事前にネットワーク以外の部分をふつうのPicoで作り込んでおこうと思っていたものの、フォントをどうしようかなと思って少し調べたまま放置していました。

CircuitPythonのフラッシュストレージ領域はそれほど大きくなく、最新のバージョン8.0.4では、ふつうのPicoは1MB、PicoW向けは500KBしか用意されていません。ご、500!?キロバイト!?過去のバージョンをたどると、8.0.0のBeta1までは1MBだったようですが、Beta2から500KBに減らされてしまったようです。おそらく一つ前の記事に書いた"便利な"Web workflowのための確保と思われますが、ちょっと代償が大きすぎますかねェ……。去年ふつうのPicoでやってても足りねえと思ってたくらいなのに、厳しい〜〜。

akkiesoft.hatenablog.jp

今回使うライブラリを一通り配置しただけで40KBも取られますし、BMP画像も切り詰めて7KB、スクリプトが7KBなので、のこりは446KBくらいとなります。あと、この調子ではMacWindowsが勝手に作る隠しファイルもファイル数によっては致命的なので、カツカツになってきたらゴリッと消してやると良さそうです。

Mac の .DS_Store や ._ から始まるファイルを自動的に消す方法 | 餃子マナー

find . \( -name '.DS_Store' -o -name '._*' -o -name '.apdisk' -o -name 'Thumbs.db' -o -name 'Desktop.ini' \) -delete -print

残り446KBあるとはいえ、おもな表示に使っているフォント2種はTTFの時点で200KBあり、CircuitPythonで使用できるBDF/PCF形式にすると結構でかくなるので、到底収まりません。漢字用のVLゴシックは4MBあるのでそもそも論外です。2種のほうは変換する前に使用しない文字をFontForgeでちまちま削っても良いですが、あまりにも手間なので、Pico W向けは思いきってアルファベットのみで対応します。

昔見つけたBIOSのフォントを再現してるところから東芝BIOSフォントを拾ってきて、BDFファイルに変換しました。Adafruitのチュートリアル曰く、さらにPCFに変換すると小さくなるとのことでしたが、小さくならなかったのでBDFのまま使いました。

int10h.org

learn.adafruit.com

インストール

ライブラリはCircuitPythonのページからバンドルをダウンロードしてきて、以下をPico W上の/libに配置します。

  • adafruit_bitmap_font
  • adafruit_display_text
  • adafruit_ntp.mpy
  • adafruit_requests.mpy
  • adafruit_uc8151d.mpy

コードはGitHubに置いたので、これらをダウンロードして、tenki-jma-for-picow.pyをcode.pyとして、settings-example.tomlの中身をいい感じに記述してsettings.tomlとしてそれぞれPico W上の/に配置します。あと、画像をディレクトリごと/に配置します。

github.com

コード

Pico Inky PackはABCの3つのボタンがあるので、それぞれを押すことで3地点まで天気予報が表示できるようにしました。元の状態では、今住んでる横浜市と地元の根室市が登録されています。また、起動時には横浜の天気を出すようにしています。コードの調べ方は各自でお願いします(雑)。

# 天気リスト(3つまで)
weather_list = [
    {
        # エリアコード: Kanagawa
        'area_code': "140000",
        # サブエリアコード: East
        'area_sub_code': "140010",
        # 市町村コード: Yokohama-shi
        'area_city_code': "46106",
        # Label
        'area_label': "Yokohama-shi"
    },
    {
        # エリアコード: Kushiro
        'area_code': "014100",
        # サブエリアコード: Nemuro
        'area_sub_code': "014010",
        # 市町村コード: Nemuro-shi
        'area_city_code': "18273",
        # Label
        'area_label': "Nemuro-shi"
    },
]
startup_weather = 0

Pico Inky Packの電子ペーパーをCircuitPythonでいじる方法については、すでにやっている人がいたので、それに習いました。

Circuitpython Raspberry pi pico w SPI Invalid pins - adafruit industries

描画周りはCircuitPythonのdisplayioに沿ってイイカンジにやります。このあたりはちょっと前に画像の用意とともに少しやっていたので、それをガッチャンコしつつ、フォントを導入して体裁を整えました。あと、CircuitPython8.0.0からdisplay.update()がdeprecateになったらしいので、新しい書き方にしてみました。

learn.adafruit.com

ネットワーク接続周りはチュートリアルを参考にして、天気予報の情報取得は自分の元のスクリプトから流用しました。

learn.adafruit.com

途中までは順調に取得できていたのですが、気づいたらSSL証明書の確認でコケるようになってしまったので、やむを得ず確認を無効化しました。やり方はIssueを漁ったら出てきたので、ひとまずこれで対処。

github.com

ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(cadata="")
requests = adafruit_requests.Session(pool, ssl_context)

NTPは、明日の予報を出すか今日の予報を出すかの判定のために時刻が欲しいので、adafruit_ntpモジュールを使って取得します。取得後はntp.datetimeをそのまま使ってもいいですが、rtcモジュールを使ってPico Wの時刻に同期しました。これをやると、timeモジュールを使っても時刻が取得できるようになります。RTCの部分は前に作ったOTP表示機からのノウハウですね。

ntp = adafruit_ntp.NTP(pool, tz_offset=9, server=os.getenv('NTP_ADDRESS'))
r = rtc.RTC()
r.datetime = ntp.datetime
rtc.set_time_source(r)

最後にループ部分。どうも電子ペーパーの連続書き換えを防止するためにdisplay.refresh()したあとは180秒のクールダウンタイムが設定されているらしく、書き換え可能かどうかがわからないので、クールダウンタイムの秒数を監視して、書き換え不可の間はPico W本体のLEDを点灯するようにしました。180秒とか意味あるのかな。どうせスクリプトがコケたらdisplayioがtraceを描画してくるし、リセットで回避もできるのに……。

まとめ

Pico Wで天気予報表示機を作るお話でした。フォントを諦めた時点で、あとは移植元のスクリプトチュートリアルのコードの組み合わせでできたのであっさりではありましたが、SSL周りでだいぶ時間を持っていかれました……。

消費電力を測ってみたら、0.06Aほどでした。現状はWi-Fiにつないだまま次のボタン操作のためにループしているので、取得時以外はWi-Fiを切ったり、ディープスリープに入っても良さそうな気がしますね。これは次回挑戦しましょう。

learn.adafruit.com

あと、Pico W向けCircuitPythonのフラッシュストレージ500KB縛りはけっこう辛いので、可能ならWeb workflowなしでストレージが1MBあるイメージファイルも用意してほしいなァと思うなどしました……。まぁ、便利なんですけど、500KB削られてまで欲しくはないかなァ〜。

Raspberry Pi Pico W日本販売開始!ついに遊べるぞー!

Raspberry Pi Pico Wがいよいよ日本でも販売を開始しました。昨年6月末にリリースされてから9ヶ月待たされましたね……。

www.raspi.jp

暗箱にぶち込んだり180日の特例申請をしたりすれば使えはしましたが、わたしはわりと律儀に待っていたので、これから色々実装です。

なお、Pico W関連の近況としては、先月上旬に公式のSDKBluetooth対応が入ったことと、同じく先月上旬にPico Wのサポートが追加されたCircuitPython8.0.0がリリースされたことが挙げられます。よって、PicoWで色々本格的に遊べる環境が整ったのもわりと最近だったりします。

github.com

github.com

ひとまず3つポチった

スイッチサイエンスさんで上限いっぱいの3つ分をポチって、2日で到着。ありがとうございます!OSCの展示に間に合わせられそう〜!技適表示はリールパッケージの上という、またなんとも微妙なところに……。パッケージが捨てられなくなるじゃん。フィルムだけ保管でも良い?

んで早速実装まつり。1つは自作のuHAT Porter Picoに実装しました。が、何に使おうとしてたんだっけ。忘れたのでちょっとOSC向けに考えます。

もう1つはピンヘッダーを実装。いつものカラーGPIOを気合で自力実装しました。

あと1つは一旦そのままとして、ひとまず全部にCircuitPythonをつっこんでおきました。


CircuitPython8ことはじめ

CircuitPython8では、settings.tomlという概念が追加されて、ここにWi-Fiの設定を入れるとosモジュールから参照できたり、Web Workflowsが有効になったりします。

https://docs.circuitpython.org/en/latest/docs/workflows.html#web

というのを知らずに、まずはチュートリアル通りに設定したら、なんか出てきてビビりました。

learn.adafruit.com

```

CIRCUITPY_WIFI_SSID="<無線AP>"
CIRCUITPY_WIFI_PASSWORD="<無線APのパスフレーズ>"

CIRCUITPY_WEB_API_PASSWORD="<Web Workflows>"
CIRCUITPY_WEB_API_PORT=8080

```

このあとcode.pyに上記チュートリアルにある無線接続テストのスクリプトを書き込んで動かすとIPアドレスが表示されます。で、http://IPアドレス:CIRCUITPY_WEB_API_PORTにアクセスすると、Web Workflowsが表示されます。

Web Workflowsには、ファイルの管理、コードエディタ、Webシリアルコンソールが搭載されており、だいぶリッチな感じになっています。シリアルコンソールもscreenコマンドとかを使えば良いと言う見方もありますが、ブラウザで見られるとやはり便利なのでアリっぽいですね。

ファイル管理。昔のFTPアップローダーみたいな感じ(ジジイ並感)

コードエディタ。こちらもファイルを開いたり保存したり実行したりできる便利ものでした。

後述のシリアルコンソールと別のコンソール機能もあります。

そしてだいぶこざっぱりしたシリアルコンソール機能。表示の折返しもカーソル移動もサポートなし。


なにやるだ?

ひとまずはWebから情報を拾ってディスプレイモノに表示したり、HTTPサーバーにしてみたりを想像しています。

learn.adafruit.com

learn.adafruit.com

あと、NTPで時刻を取得するのもわりとだいじなので、これもほぼ必須的な感じがしますね。

docs.circuitpython.org

というわけで、これからいろいろ実装ですが、まあ実は事前に普通のPicoで作れるところは作ったり下調べ済みだったりしているので、すぐにいくつかネタを発表できる予定です。おたのしみに。

(随時追記)できたよ

akkiesoft.hatenablog.jp

Raspberry Piの新しいカメラ2つまとめてレビュー

買ったのにレビューしてないのはどうなんだというアレ

Raspberry Pi Camera Module 3(広角)

Camera Module 3は、サンプルはノーマルレンズをレビューしました。

www.raspi.jp

広角の方を自分で買ったので、比較しました。左が広角バージョン。上から見ると大差ないですが、

横から見ると結構出っ張っているのがわかります。

画角の比較。同じ距離でメダカを撮影すると、ノーマルがこんな感じになるところ、

広角は全体が収まる感じになります。良いですね。

普段はメダカメラ第二カメラとして、気が向いたときに動かしています。

Raspberry Pi Global Shutter Camera

グローバルシャッターカメラは、HQカメラと同規格のカメラモジュールで、グローバルシャッターのセンサーを使用しているのが違い。グローバルシャッターは、高速なものを撮ったときにズレたりする通常のカメラ(ローリングシャッター)と違って、そう言うのが起こらないのだそうです。これのサンプルはなかったので、これも気になって買ってみました。多分これが活かせる機会は私にはないw

普通のHQCamで撮影した扇風機。左に縦に入ってる明るいやつがたぶんそう?カーテンの模様っぽい気もしますが……

こちらがグローバルシャッターカメラで撮影したもの。こちらは不自然な縞模様はないですね。

比較写真を撮るための被写体選びもそうですが、この機材一式を持ち歩いて撮るのも一苦労なので、小さいディスプレイを用意して、ボタンを押したら撮影できるプログラムを用意してみました。Picamera2ライブラリで初めて組んでみましたが、なんか微妙に苦労しました。あとドキュメントをpdfにするのやめて欲しい。面倒すぎてコード読みに行っちゃった。。

撮影できた写真はこちら。

あとはPiZeroとかで実装してやれば、外で振り回してもそこまで不審じゃななくなるかしら……??グローバルシャッターカメラの研究は要継続です。

展示します。

4/1に久しぶりのOSCオフライン開催が浅草であり、そちらで両方とも展示予定です。2つあるので、それぞれの見せ方を考えねばならないですが、来週までに間に合うかしらん……🤔!?

一般参加(出展参加も)は要事前登録のため、参加予定の方は登録をお忘れなく。

ospn.connpass.com

桜台公園で花見とホームセンター新規開拓と玄関照明IoT改良

きのうは桜台公園で花見をしてきました。ほかはまだ半分くらいといったところですが、ここはほぼ満開の桜が数本いて見頃でした。良さ。

散歩に出たのが少し遅めの時間で、そのまま長津田方面に行くには時間が微妙だったので、桜台公園からさらに北方向に突き進んでみることに。実は行ったことがなかったので。少し眺めの坂を上るとあとはほぼ平坦で、お店とかもちょいちょいあって栄えてたんですね。

こないだアキバで見つけてキャッキャしながら買って飲んだオレンジジュースのマシンがいなげやの前にあってビビったり、

さらに進むとコーナンproが現れたりしました。いや、コーナンができてたなんて知らないぞ!どうも三菱UFJモルガン・スタンレーの研修施設の跡地らしく、半分がコーナン、半分が宅地になったもののようでした。もう少し進むと、寺家から恩田方向に向かうときに使っていた道の交差点と繋がりました。なるほどなあ!

用事もなくフラッとたちよりましたが、1Fはほぼ完全に資材売り場、2Fはみっちりと建材、工具、作業着類が並んでいて、まさにプロ向けのお店。客層も完全に仕事の買い出しという感じで、私が場違いと言った雰囲気でした。

ただ、直近の仕事がHDD数十台の分解廃棄で、しかも手回しでネジを開けており、かつ最後のロットのネジ穴がやたら脆かったので、こいつに打ち勝つためのドライバービットを購入(領収書はちゃんと出してもらう)。あと、自宅の玄関の照明を切るだけの壁スイッチIoT(笑)が、元のパネルではイマイチだったのでそれをどうにかするための金属パネルも購入しました。

長津田スーパービバホームのほうがもっと普通向けのアイテムもあって良いのは確かだと思いますが、あちらは坂がまあまあきつかったり、今回のコーナンより1km遠かったりするので、これ系の部材を眺めに行くならコーナンに行くという手が増えました。これは嬉しいですねー。

壁スイッチIoT改良

というわけでこれの続き。

akkiesoft.hatenablog.jp

プラのパネルはペラペラなので、スイッチの硬さに負けてパネルが凹んでしまい結果スイッチがオフにできないことがわかっていたので、金属パネルに交換します。いつかビバホームに行ったら買おうと思って忘れていたので、コーナンで買えてよかった〜。価格は300円ほど。

元のパネルはまず外観部分をパリパリ剥がして、ベース部分はネジ2本を外して撤去します。賃貸なのでてきとうに靴箱あたりに保管して、退去時に復元します。

んで金属パネルを取り付けて、IoT(笑)を戻します。ところで、ブログに書くのを忘れていたっぽいのですが、ここに静電タッチボタンを追加しまして、ココをタッチすると部屋のメイン照明が操作できるようになりました。お出かけ帰宅、あと風呂に入ったり出たりした時にも手軽に操作できるようになって便利になりました。メイン照明の操作は、机の上にいる雑用ラズピッピ上のREST APIにGETするだけの雑仕様なのでできるワザです。

動作確認。完璧ですね。角度調整をやり直してみても良いかも。

social.mikutter.hachune.net

Raspberry Pi OSのカーネルが6.1に移行。Pi 4で32Bit版を使っている場合は少し注意

Raspberry Pi OSのカーネルが6.1に移行しました。少し前からファームウェアリポジトリでコミットされていましたが、先週末にaptコマンドでのOSアップデートで適用できるようになったようです。

6.1への移行によって、すでにアップストリームに取り込まれたRaspberry Pi関連のサポートを、古いバージョンのカーネルに取り込んでメンテナンスする必要がなくなるため、労力が減らせるとのこと。

forums.raspberrypi.com

また、MGLRUなるメモリ管理の改善オプションもデフォルトで有効にしているとのこと。メモリが限られている環境でパフォーマンス改善が期待できるようです。いいね。

gihyo.jp

ただし、冒頭のフォーラムでは、リリース後に不具合などの情報が寄せられているので、aptでのアップデートはすこし様子を見ても良いかも知れません。ZFSカーネルバージョンの互換がなくなっていたり、hwrngが動いていないかも?というやり取りがリアルタイムで流れていました。

Pi 4は32Bit版でも64Bitカーネル起動がデフォルトに

もうひとつ。Raspberry Pi 4では32Bit版のRaspberry Pi OSでも64Bitカーネルで起動するようになりました。以前から/boot/config.txtで記述できた「arm_64bit=1」がデフォルト値になった格好です。

github.com

もし引き続き32Bitカーネルで起動したい場合は、/boot/config.txtに「arm_64bit=0」を記述して再起動すればOKです。

なお、同じRaspberry Piでも3/3+については、引き続き32Bitカーネルでの起動がデフォルトとなるため、64Bitカーネルで起動したい場合は上記の設定を1で記述してあげる必要があります。

電源LEDなどのデバイス名変更も

フォーラムは全部読んでいるわけではないですが、細かい変更もある模様。電源LEDを制御している場合にはパスが変わったそうなのでこの辺も注意でしょうかね。

Moving Linux Kernel to 6.1 - Page 12 - Raspberry Pi Forums

It seems that support for changing the onboard leds using /sys/class/leds/led[01] has disappeared when using 6.1. This seems to be the case on 3B, 3B+ and 4B.

The names have changed to align with upstream, and to be more logical. They are called ACT and PWR.

確かに変わっていそうでした。あまりこんなところは全く触らないので、これが重要な人がいるような気はあまりしませんが、まあこんな変化もあるそうです。

$ ls /sys/class/leds/
ACT/        default-on/ mmc0/       mmc0::/     PWR/

# オフとオン
$ echo 0 | sudo tee /sys/class/leds/PWR/brightness
$ echo 1 | sudo tee /sys/class/leds/PWR/brightness