日本語 | English
本記事は「#NervesJP Advent Calendar 2020」の21日目です。
前日は@piacerexさんのRespberry Pi Zero WHにElixir IoTフレームワーク「Nerves」を入れてみたでした。
はじめに
プログラミング言語を学ぶときは、まず「Hello」と文字を表示するところから始まりますが、IoTの世界ではLチカがその役目をしているようです。僕がLチカ後に興味を持ったのは、11日目に話をしたパルス幅変調 (PWM)でのLチカでした。
しばらくLチカプラスαで遊んだあと、その次にやりたくなったことは、何らかの方法で実際に「Hello」表示することでした。その話をします。
どういう手法で「Hello」?
Nerves JPの@takasehidekiさんからのアドバイスでどーんとまとめて入手した部品が多数手元にあったので、それぞれの使い方をザクッと把握しながら、どれにしようかと検討をはじめました。以下のものを検討しました。
- LEDをたくさんならべる
- 赤色7セグメントLED表示器(1文字)
- 赤色7セグメントLED表示器(4文字)
- 赤色ドットマトリクスLED(8×8)
- LCDキャラクタディスプレイモジュール(16×2行)
- Web
- Mobile
色々悩んでLCDにI2Cインターフェースを取り付け、シリアル通信することに決めました。理由は、下記のとおりです。
- WebとMobileは実用的かもしれないが、今は電子工作をしたい
- 他の選択肢が物理的な配線が多くてめんどくさそう
- LCDに興味をもった
- I2Cで接続すると少ない配線で通信できるのがカッコいい
調査
まずは、ひたすらググり、Youtubeのビデオも片っ端から見ました。いくつか役に立ったものを挙げます。
- Hitachi HD44780 LCD controller datasheet
- Hitachi HD44780 LCD controller
| Wikipedia - How a Character LCD works Part 1 by The 8-Bit Guy | Youtube
- How to Use Character LCD Module | elm-chan.org
- Difference between interfacing character 16×2 lcd in 4-bit and 8-bit mode with microcontroller | engineersgarage.com
- Character LCDs | adafruit
- I2C Serial Interface 1602 LCD Module User Guide
配線に関しては、パラレル通信でもシリアル通信でも特に何も難しいことはありませんでした。
プログラミングに関しては、ほとんどがC、C++やPythonで書かれたLCDドライバを使用する場合の説明が多く、Elixirプログラミングする上であまり参考にはなりませんでした。
Elixirで使えそうなライブラリを探しました。I2Cシリアル通信にはElixir Circuits - I2Cが使えるのは、知っていたのですが、肝心のLCD操作のライブラリに良いのがありません。ExLCDがありますが、(2020年12月現在)長い間メンテされてなくI2Cにも対応していません。ExLCDをフォークして改善を試みましたが、既存の実装に納得行かない部分が色々あったので、それを参考にしつつ自分で実装することにしました。
しばらくの間、他言語で書かれたLCDドライバーのソースコードをいくつか読んでElixirで同様のことができるのかを探りました。ある時点で、LCD本体自体の資料(データシート)に出くわし、それらのLCDドライバーはただデータシートの通りにコマンドを実行している単純なものであると気づきました。当たり前の事だったのかもしれません。気づいてよかった。
デモアプリ
まずLCD本体自体の資料(データシート)をよく読み、各種ピンの役割、初期化の方法、4ビットモード、各種コマンドについての理解を深めました。実験用Nervesアプリで試行錯誤しながら、コードを書いていきました。
動くようになるまで、結構時間がかかりました。例えば「Hello」と入力してるのに変な文字が表示されたりしました。焦りました。
一旦動くのが確認されたら、最低限のテストを書いて回帰試験しながら、リファクタリングしていきました。LCDを動かす部分とデモアプリを切り離せたので、LCDを動かす部分はライブラリに、デモアプリはそのライブラリの使用例とすることにしました。
もし、Nervesに取り組むのが初めての方おられましたら、2日目に@kentaroさんが発表されたウェブチカでElixir/Nervesに入門する(2020年12月版)がわかりやすく説明してくれています。また、NervesJP Slackにジョインされれば、コミュニティが色々教えてくれます。僕もそのNervesJP Slackにお世話になっている一人です。
ハードウェア
- ターゲット機器 (Raspberry Pi等)
- Micro SDカード
- LCD display (16x2)
- LCD用I2Cインターフェイス
- ジャンパーワイヤ
Connect:
デモアプリをダウンロード
git clone git@github.com:mnishiguchi/lcd_display.git
cd examples/nerves_hello_lcd
ファームウェアをSDカードに焼く
必要な環境関数をセット。 ターゲット機器タグ一覧
$ export WIFI_SSID=_____ # your WIFI id
$ export WIFI_PSK=______ # your WIFI password
$ export MIX_TARGET=rpi4 # your target board
依存するライブラリをインストール。
$ mix deps.get
FYI: ファームウェア関連のコマンド一覧。
$ mix help | grep firmware
mix burn # Write a firmware image to an SDCard
mix firmware # Build a firmware bundle
mix firmware.burn # Build a firmware bundle and write it to an SDCard
mix firmware.gen.script # Generates a shell script for pushing firmware updates
mix firmware.image # Create a firmware image file
mix firmware.metadata # Print out metadata for the current firmware
mix firmware.patch # Build a firmware patch
mix firmware.unpack # Unpack a firmware bundle for inspection
mix upload # Uploads firmware to a Nerves device over SSH
ファームウェアをつくる。
$ mix firmware
SDカードをホストマシンにSDカードを挿入。
下記のコマンドでファームウェアをSDカードに焼く。
$ mix firmware.burn
SDカードをターゲット機器にSDカードを挿入。ターゲット機器の電源オン。
ターゲット機器にWIFI接続
WIFIが接続できているか確認。
$ ping nerves.local
SSHでターゲット機器に接続。しばらくすると、IExシェルが起動する。
$ ssh nerves.local
Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help)
Toolshed imported. Run h(Toolshed) for more info.
RingLogger is collecting log messages from Elixir and Linux. To see the
messages, either attach the current IEx session to the logger:
RingLogger.attach
or print the next messages in the log:
RingLogger.next
iex(1)> RingLogger.attach
:ok
iex(2)> NervesHelloLcd.hello_i2c
-
RingLogger.attach
関数を呼ぶと、ログが表示される。 -
NervesHelloLcd.hello_i2c
関数を呼ぶと、LCDにHello world
が表示される。
さいごに
いい経験になりました。内容によってはデータシートさえしっかり読めば、特に専用ライブラリがなくても自分でできることがわかりました。
最終的に、ラズパイのGPIOピンをフルに使ってのHelloもやってみました。見た目上、I2Cを使うと配線が少なくシンプルに見えますが、実際はIOエキスパンダが間にあるかどうかの違いでだけで、やってることは同じなのですね。
これからNervesを始める人にも手軽にLCDを操作する一助になれば幸いです。
明日は@ringo156さんです。