IoT郵便受けキットのファームウェアの書き込みと開発について
はじめに
LoRa(ISP4520)ボードは最低限のピンしかレイアウトされていません。
なのでLoRaボード側のファーム開発にはいくらかのノウハウが必要です。
LoRaボードにはArduino向けブートローダーを書き込んでありますので、USBシリアル変換があれば開発をすることができます。
ここでは、本キットに付属する「RaspberryPi Zero WH(以後RPiZero)」をUSBシリアル変換の役割にしてファームウェア開発環境を構築します。
全体構成
注意: PCはISP4520ファームウェアの開発や書き換えに必要ですが、運用時には不要です。
別途必要なもの
- マイクロSDカード(2~32GB)を1枚
- USB給電アダプターとケーブル(MicroBタイプ)を1本
- PCと同じLANにつながり、インターネットにもつながるWi-Fi環境
- USBポートに空きのあるPC
RPiZeroのイメージ作成
2~32GiBのマイクロSDカード(別売り)を用意して、そこにRaspberryPi OSのインストールを行います。
まずはPCに「Raspberry Pi Imager」というアプリをインストールしましょう。
Raspberry Pi Imager のインストール
以下のリンクからPCにあったものをダウンロードしてインストール手順に従ってください。
https://www.raspberrypi.com/software/
参考:
- Windowsの場合「winget install RaspberryPiFoundation.RaspberryPiImager」
- macOSのHomebrewなら「brew install raspberry-pi-imager」
- Ubuntuなら「sudo apt install rpi-imager」
イメージ書き込み時の手順
マイクロSDカードをリーダーライターを経由してPCに接続し、「Raspberry Pi Imager」を起動します。
イメージは「RASPBERRY PI OS LITE(32-BIT)」を指定し、ストレージには先ほどのマイクロSDカードを指定します。その後歯車マークをクリックします。
「ホスト名」、「SSHを有効化」、「ユーザー名とパスワードを設定する」、「Wi-FiのSSIDとパスフレーズ」の4点を必ず設定してください。
ホスト名は「hostname」、ユーザー名はデフォルトの「pi」という前提で解説していきます。
PC側にSSH鍵生成済みの場合、SSHは公開鍵認証設定がお勧めです(よくわからない方はパスワード認証にしてください)。
書き込みとベリファイが完了するとカードの取り外し処理の確認があってこれでマイクロSDカードは完成です。
SSH動作確認
作成したマイクロSDカードををRPiZeroのSDカードスロットに指して、USB給電(別売り)を接続して起動とSSHによるログインができることを確認しましょう。
> ssh pi@hostname.local
このあと公開鍵認証の場合、プライベートキー暗号化につかったパスワードの入力を求められる場合があります。パスワード認証では「ユーザー名とパスワードを設定する」にて指定したパスワードを入力します。
scpやsshで公開鍵認証方式を利用している場合、PC上の秘密鍵のパスフレーズを聞かれる場合があります(ssh-keygenしたときに設定したパスフレーズ)
公開鍵認証方式でパスフレーズの確認を初回のみとする手法にssh-agentやssh-addなどを活用するやり方があります。ここではそのセッティングについては解説しません。
パスワード認証を選んだ場合は毎回パスワードを入力しましょう。
ファームウェア開発環境
STEP.1
RPiZeroにUSBガジェットモードでシリアルポートデバイスになってもらいます。
また、raspi-configを使ってttyS0を有効にします。
STEP.2
RPiZeroをPCにつないで起動するとPC側でUSBシリアルデバイスとして見えるようになります。この時のデバイス名を確認しておきましょう。仮に「COM5」とします。
(macOSの場合は「/dev/tty.usbmodemDEADBEEF」などのようなデバイス名)
STEP.3
RPiZeroにてtty中継アプリを実行して「/dev/ttyS0」と「/dev/ttyGS0(USBシリアルデバイス)」をパススルー接続します。
STEP.4
LoRaボードの3.3V、GND、TX、RXの4pinをRPiZeroのヘッダーとジャンパワイヤでつなぎます。
LoRaボード外観
SW1: リセットボタン
写真左側の縦列 | 写真右側の縦列 |
---|---|
SWCLK | P0_04(DFUモード時ソフトブリンク) |
SWDIO | P0_05 |
GND | P0_06(GNDショート&リセットで強制DFUモード) |
3.3V | P0_13 |
RST | P0_08 |
J1 | (10pins) |
---|---|
1 | GND |
2 | TX(ISP4520側は入力ピン) |
3 | RX(ISP4520側は出力ピン) |
4..9 | NC |
10 | 3.3V |
J2 | (10pins) |
---|---|
1..9 | NC |
10 | GND |
STEP.5
この状態でArduinoIDEをPC側で起動して先ほど確認した「COM5」を対象に開発を進めることで普通にArduinoファームウェア開発ができます。
一度ファームウェアが動き出したら、DFUモードにするには手動操作が必須です。
DFUモードへ移行するには、ピンセットなどでP0_06ピンを隣接するGNDに短絡した状態でボード上のRESETスイッチ(SW1)を押します。
Arduino IDEにてPC側が認識しているシリアルポートを指定してファームウェア開発と書き込みを行います。(書き込む前には都度DFUモードへの移行を忘れずに)
Arduino開発環境について
現状、まだ正式リリースされてはいませんが、ArduinoIDE2.0(RC6)がお勧めです。
- Webエディターと同じコンポーネントで作られている
- コンパイルがおおむねV1より早い(メモリ使用量が控えめ)
- 成果物バイナリを保存したりコマンドラインツール「arduino-cli」(IDE2も裏でこれを使っている)との連携が取りやすい
- つまり、コンパイルとフラッシュを別の環境で実行といったことがやりやすい
- 付属のエディタがVSCodeと同じコンポーネントで高機能
といった特徴があります。
IDE2のインストール
ダウンロードページ: https://www.arduino.cc/en/software
下にスクロールすると「Arduino IDE 2.0 RC」のダウンロードリンクが見えます。
Windowsでのインストール方法
アップデート済みのWindows10以降であれば、コマンドプロンプトにて
winget install ArduinoSA.IDE.rc
でインストールできるようになっていると思います。
macOSでのインストール方法
Homebrewを使って以下のコマンドでインストールできます。
brew install homebrew/cask-versions/arduino-ide-nightly
Linuxでのインストール方法
残念ながらまだarm向けのバイナリはまだ提供されていません。x86_64マシン前提です。
curl -LO https://github.com/arduino/arduino-ide/releases/download/2.0.0-rc6/arduino-ide_2.0.0-rc6_Linux_64bit.zip
unzip arduino-ide_2.0.0-rc6_Linux_64bit.zip
ランチャーの作成は各種ディストリビューションの慣習に合わせて作成してください。
ボードサポートとライブラリのインストール
Arduino IDE(2.0rc)を起動します。
その後、FileメニューのPreferenceをクリックして設定画面を呼び出します。
赤矢印の「Additional boards manager URLs」の編集ボタンをクリックします。
https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
を追加し、OKをクリック。
設定画面でもOKをクリックして閉じます。
次にToolsメニューのBoardにある「Board Manager...」をクリックします。
「nRF52」で検索して「Adafruit nRF52」(最新は 1.3.0)を見つけて最新のものをインストールしてください。
次にライブラリをインストールします。Toolsメニューの「Manage Libraries...」をクリックします。
「SX126x-Arduino」(最新は 2.0.11)を検索してインストールしておきます。
ファームウェアのソースコード
git clone https://github.com/SWITCHSCIENCE/IoT-Mailbox.git
cd IoT-Mailbox
各フォルダについて
- Gateway: 通知サービス
- Receiver: 受信機ファームウェア
- Transmitter: 送信機ファームウェア
- passthrough: tty中継アプリ
tty中継アプリについて
RPiZeroの中央寄りのUSBコネクタをPCにつなぐと、USBシリアルデバイスとして認識します。
その際、RPiZero側では/dev/ttyGS0
というデバイス名として認識します。
PC側はWindowsならCOM?
、macOSやLinuxなら/dev/tty.usbmodem#####
というデバイス名で認識します。
コードのビルドと書き込み
まずは送信側のファームウェア書き込みを行います。
RPiZeroとLoRaボードの一つを以下の結線になるようジャンパワイヤで接続します。
RPiZeroの40pinヘッダー | LoRaボード |
---|---|
1: 3.3V | J1-10: 3.3V |
8: TX(ttyS0) | J1-2: TX |
9: GND | J1-1: GND |
10: RX(ttyS0) | J1-3: RX |
シリアルポート名の確認
RPiZeroをPCに接続し、デバイスマネージャでUSBシリアルデバイスを確認します。COM#
の番号を覚えておきましょう。(以下の例はCOM5)
Arduino-IDEの起動
前述のgit-cloneで取得したコードのIoT-Mailbox/Transmitter/Transmitter.ino
ファイルをArduino-IDEで開きます。
Port設定を行います。
tty中継アプリをRPiZero上で起動する
コマンドプロンプトを使います。
初回のみ
> cd IoT-Mailbox/passthrough
> scp passthrough pi@hostname.local:/home/pi/
中継開始
> ssh -t pi@hostname.local ./passthrough /dev/ttyS0 /dev/ttyGS0
Ctrl+Cで中継終了です。
DFUモードへの移行
前述の「STEP.5」を実施します。
コンパイルと書き込み
SketchメニューのUploadまたは右矢印アイコンをクリックします。
Outputに以下のような表示が出れば書き込み完了です。
受信側へのファーム書き込み
もう一枚のLoRaボードをRPiZeroにつないで、IoT-Mailbox\Receiver\Receiver.ino
をArduino-IDEで開き、同様にコンパイルとDFUモードへの移行と書き込みを行います。
動作確認
- Receiverファームを書き込んだ側は書き込みしたときの結線のままでOK
- Transmitterファームを書き込んだ側には以下のような結線をしてください。
- 電池ボックスの+をLoRaボードの3.3V
- 電池ボックスの-をLoRaボードのGND
- 傾倒スイッチの一方をLoRaボードのP0_05ピン
- 傾倒スイッチのもう一方をLoRaボードのGND
以上の結線をしたうえで電池を入れ通電します。
> ssh pi@hostname.local
以下のようにシリアルポートターミナルソフトをインストールして/dev/ttyS0
を開いておきます。
$ sudo apt install screen
$ screen -l /dev/ttyS0 115200
傾倒スイッチを倒したり起こしたりするたびにscreenアプリの端末画面に以下のように受信ログが出力されます。(傾倒スイッチの状態変更からログの出力までは3~5秒程度かかります)
LTSVという形式のログで、idは送信機のシリアル番号です。
最初の2行はブート時にReceiverが出力するものです。
後ろの2行がTransmitter側の傾倒スイッチ状態変化を無線で通知してきた内容です。
boot!
SerialNumber: 4A A6 9D 77 91 05 30 0D
RX: rssi=-64 snr=7 id=################ battery=2.63 state=3
RX: rssi=-61 snr=7 id=################ battery=2.63 state=2
rssiは受信電波強度、batteryはTransmitter側の電池の残電圧です(上記はNiMH電池を使っている事例です)
stateは以下の通り
- 0:起動直後
- 3:傾倒スイッチがOFFからONになったことを検出した
- 2:傾倒スイッチがONからOFFになったことを検出した
このログを受け、スマホへの通知を行ったりするのが
RPiZero上で動作させるGatewayアプリの役割です。
必ずこのテストを行ってシリアル番号をメモっておいてください。
Gatewayアプリのコンパイル
Go言語で実装されており、PC上でRPiZero用にクロスビルドします。
以下はビルド済みバイナリを使わず、ソースからビルドするのに必要な手順です。
ビルド済みバイナリをそのままお使いになる場合は「ビルド済みバイナリのインストール」までスキップしてください。
Go言語環境のセットアップ
Windows
winget install GoLang.Go
- システムの詳細設定にて以下の環境変数を設定をします
- PATH=%USERPROFILE%.go;C:\Go\bin;%PATH%
- GOPATH=%USERPROFILE%.go
- ログインしなおして設定を反映させます
macOS
- brew install go
- echo GOPATH=~/.go >> ~/.zshrc
- echo PATH=~/.go/bin:$PATH >> ~/.zshrc
- (bashをお使いの場合はUbuntuの場合と同じように.bashrcに書き込みます)
Ubuntu 22.04
- sudo apt install golang
- echo GOPATH=~/.go >> ~/.bashrc
- echo PATH=~/.go/bin:$PATH >> ~/.bashrc
Goの確認
コマンドプロンプトまたはターミナル(以後ターミナルと表記します)を開いて以下のコマンドで確認をします。
バージョン表示の例:
> go version
go version go1.18.2 platform/arch
platform/archにはお使いのPC環境に応じた表示になります。
ソースコードフォルダ
ターミナルにて以下のフォルダパスへ。
> cd IoT-Mailbox/Gateway
以下のコマンドにてビルドします。
> go env -w GOOS=linux GOARCH=arm GOARM=6
> go build
./Gateway
というバイナリファイルが出力されます。これをRPiZero側に持って行って自動起動するようにします。
ビルド済みバイナリのインストール
> cd IoT-Mailbox/Gateway
> scp Gateway pi@hostname.local:/home/pi/
LINE通知トークンの取得
あらかじめ、スマホのLINEアプリにて"LINE Notify"というアカウントを検索して友達に加えます。
ここにアクセスしてログイン:https://notify-bot.line.me/my/
「トークンを発行する」をクリック。
トークン名を記入、トークルームには「1:1でLINE Notifyから通知を受け取る」を選択します。
以下の画面の表示にあるアルファベットを含む文字列をメモっておきましょう。
LINE通知テスト
> set LINE_NOTIFY_TOKEN=前述のLINE通知トークン文字列
> curl -X POST -H "Authorization: Bearer %LINE_NOTIFY_TOKEN%" -F "message=Hello!" https://notify-api.line.me/api/notify
$ LINE_NOTIFY_TOKEN=前述のLINE通知トークン文字列
$ curl -X POST -H 'Authorization: Bearer '${LINE_NOTIFY_TOKEN} -F "message=Hello" https://notify-api.line.me/api/notify
Gatewayを自動起動するようにする
> ssh pi@hostname.local
以下の2ファイルを作成します。
動作テストでメモしたidの値を「TRANSMITTER_ID」にセット、
前述の取得したLINE通知トークンを「LINE_NOTIFY_TOKEN」にセットしましょう。
TRANSMITTER_ID=################
LINE_NOTIFY_TOKEN=##########################
ON_MESSAGE=なにかが投函されました!
OFF_MESSAGE=なにかが投函されました!
WAIT_TIME=10s
BATTERY_WARN=2.3
ON_MESSAGEやOFF_MESSAGEは設置状況に合わせた文言に書き換えてください。
例えば郵便受け投入口のフラップに傾倒スイッチを取り付けた場合、ONになってすぐOFFになるという挙動になりますので、この場合どっちに変化しても同じメッセージにするとよいです。投函する人がゆっくり投函動作すると両方の通知が出てしまうことはありますので、その場合WAIT_TIMEを長めにするなどしてもらえればそれ以上早く通知を出さなくなります。BATTERY_WARNは送信機の電池が指定した電圧を下回っている場合にバッテリー警告を一緒に通知するようになります。NiMH電池なら2.3あたり、アルカリ電池なら2.0~2.2あたりに設定すると良いでしょう。
[Unit]
Description=IoT-Mailbox Gateway
[Service]
EnvironmentFile=/home/pi/Gateway.env
ExecStart=/home/pi/Gateway
[Install]
WantedBy=multi-user.target
RPiZero側で以下のコマンドを実行することで、Gatewayの自動起動および起動を行います。
> sudo systemctl daemon-reload
> sudo systemctl enable gateway
> sudo systemctl start gateway
設置
以上の作業にてあらかじめ必要な以下のセットアップが完了します。
- RPiOSイメージをご家庭のWi-Fiにつながる状態のイメージを書き込んだマイクロSDカード(別売り)を作成してRPiZeroに差し込みます。
- また、GatewayアプリをRPiZero側にインストールして送信機のIDやLINE通知トークンの設定、自動起動設定スクリプトを構成しておきます。
- LoRaボードのひとつを送信機としてファームウェアを書き込む
- そのボードに電池ボックス、傾倒スイッチを接続する
- LoRaボードのひとつを受信機としてファームウェアを書き込む
- そのボードをRPiZeroに接続(ファームウェア書き込み時のまま)
- RPiZeroにはUSB5Vアダプター(別売り)で給電、電池ボックスには単4電池二本(別売り)をセットします。
あとは、これらを適切な場所に設置します。RPiZeroと受信機はご家庭のWi-Fiにつながる室内に設置し、送信機側を郵便受けの中に雨天時に濡れないように設置しましょう。傾倒スイッチは反応する角度のあたりをつけて郵便受け投入口などに設置します。
投函物によって配線が外れたりしないように小箱に収め、郵便受けの天板に張り付けるなどすると良いでしょう。