search
LoginSignup
1

More than 1 year has passed since last update.

posted at

updated at

WindowsからElixir IoT端末を作ってみた:「Raspberry Pi OS」を入れた後、Elixir IoTフレームワーク「Nerves」へ

この記事は、「NervesJP Advent Calendar 2020」の20日目です

昨日は、@nishiuchikazuma さんの「NervesとPhonenix(Gigalixir)とGCP Cloud PubSubを使ってBBG CapeのLEDをチカした話〜NervesでSub編〜(2/2)」でした


Elixir Digitalization Implementors/fukuoka.ex/kokura.exのpiacereです
ご覧いただいて、ありがとうございます :bow:

無線LANとGPIOが標準装備のIoTデバイス「Raspberry Pi Zero WH」に、ElixirのIoTエンジン「Nerves」をインストールして動かす入門コラムです

普段のElixir IoT構築では、Nervesでは無く、Raspberry Pi OS上にElixir/Phoenixをインストール(少し古いElixirだけど)して、ごく普通のPCと同じ使い方をしていますが、今後、Nervesでの構築/運用も試していくことも視野に入れて、トライしてみます

内容が、面白かったり、役に立ったら、「いいね」よろしくお願いします :wink:

:ocean::ocean::ocean: Advent Calendar、fukuoka.ex1位、Elixir2位達成ヽ(=´▽`=)ノ :ocean::ocean::ocean:

fukuoka.ex Advent Calendar、Webテクノロジーカテゴリで堂々1位 … 各コラムぜひお読みください
https://qiita.com/advent-calendar/2020/fukuokaex
image.png

そして、プログラミング言語カテゴリは、1位がRust、2位がElixir、3位がGoとモダン言語揃い踏みでのトップ3、熱いネー:laughing:
https://qiita.com/advent-calendar/2020/elixir
image.png

Raspberry Pi Zero WHを組み立てる

ケースに入れる前/ケーブルを接続する前の状態はこんな感じです
image.png

組み立てると、こんな感じです(まぁ、この後、コラム内の操作中は、ケース外して作業ですが)
image.png

ケーブル周りは、ノートPCやデスクトップPCとだいぶ異なるので、以下に注意です

  • USBハブの接続は「Type-B」なので、「Type-Aメス→Type-Bオス」変換ケーブルが必要
  • USBハブは、「USB 3.0」だと動かない
  • ディスプレイの接続は「ミニHDMI」なので、「HDMIメス→ミニHDMIオス」変換ケーブルが必要
  • 本体のUSB Type-Bは、外側が電源用、内側がUSBハブ用(逆にするとキーボード等が動かない)

また、下記もちょっとした注意点です

  • Bluetoothキーボード/マウスは、Raspberry Pi OSはOKでもNervesで苦労するっぽいので、USB接続で
  • microSDカードは、64GByte以上はNGらしいので、64GByteのもので 128GByte、OKでした
  • 各OSのインストールで、microSDの着脱を繰り返すため、ケースは完了するまで付けない

Raspberry Pi Zero WHと周辺デバイスの事前動作確認

下記コラム等を参考に、microSDにRaspberry Pi OSを焼きます(以前よりずいぶんラクになりました)

USB 1本とSDカードライタだけでできるUSB OTGを用いたRapsberry Pi Zero WH のセットアップ
https://qiita.com/Liesegang/items/dcdc669f80d1bf721c21#112-os%E3%81%AE%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%81%BF

それから、Raspberry Pi Zero WHにRaspberry Pi OSを焼いたmicroSDを差し、ミニHDMIからディスプレイに繋ぎ、Raspberry Pi OSが無事ブートすることを確認しておきます(キーボードやマウス、無線LANなどが動くことも確認します)
image.png

CPUは、こんな感じらしい(Intel性能比で言うと、どんなもんなのか、さっぱりイメージが付かない…)
image.png

無線LANを設定後、Raspberry Pi Zero WHで、ifconfigでIPアドレスを調べ、同一セグメント内(≒同じWifiに接続)の別PCからpingを打って到達することが確認できたら、無線LANの動作確認も完了です

ここまでを事前にやっておくと、Nervesを入れた後にmicroSDやディスプレイ、キーボード等が、実は壊れてて動かなかった … なんて事態を切り分けることができるので、使い慣れたセッティングで無い限り、やっておくと安心です

(… が、このコラムのオチは、これらのほとんどをNervesで使うところまで行けなかった:sweat_smile:

Nervesを動かすまでのステップ

さて、ここからは、下記5ステップで進めます

①Nervesのインストール
②fwupのインストール
③Nerves開発
④NervesファームウェアをmicroSDに焼く
⑤NervesファームウェアをRaspberry Pi Zero WHで実行

①~④は、母艦PC上での操作で、⑤のみRaspberry Pi Zero WHをいじります

①Nervesをインストール

方法a)Docker+VSCodeを使う ※オススメ

最も手軽にNervesを試すには、Docker+VSCodeでの構築を、下記 @matsujirushi さんコラムの内容に沿って行います

WindowsでNervesやるならWSL2+Docker+VSCode
https://qiita.com/matsujirushi/items/f0bde41400e45e309df2

基本、手順にある通りにやるだけで出来てしまうので、あまり悩むこともありませんでした、凄い(そして、書くことが無くなってしまったw):laughing:

方法b)WSL2上でUbuntu 18.04 LTSを使う

1年ちょい前、はじめてNervesを触ったとき、Windows開発ではVirtualBox+Ubuntuしか使えませんでしたが、現在は、WSL2(≒Windows上でLinuxディストリビューションを動かすサブシステム)でもできるようになっています

WSL2のインストール

下記手順でWSL2をインストールしてください(PC再起動があります)

Windows 10 用 Windows Subsystem for Linux のインストール ガイド
https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#manual-installation-steps

なお手順中に「Ubuntu」をWindows Storeでインストールする手順がありますが、ココは不要です … この手順で入る「Ubuntu 20.04」は、ビルドツールのインストールや、Elixirビルドが上手くいきませんので、この後インストールするUbuntu-18.04の利用を推奨します

WSL2上にUbuntu 18.04 LTSのインストール

Windows Storeで「Ubuntu-18.04」と検索し、インストールした後、「起動」ボタンをクリックします
image.png

ユーザ作成を求めてくるので、ユーザ名(下記ではpiacereという名前で入れてますがココは変えてOK)/パスワード/パスワード確認を入力します

Enter new UNIX username: piacere
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

piacere@XXXXXXXXXXXXXXX:~$

OSバージョンを確認します

cat /etc/issue
Ubuntu 18.04.2 LTS \n \l

なお、次回以降は、以下コマンドでUbuntu 18.04 LTSが起動できます

wsl -d Ubuntu-18.04

もしくは、以下コマンドでも起動できます

ubuntu1804

ビルドツールをインストール

さて、Ubuntuが起動したのでビルドツールをインストールします

まず、aptを最新化します(ここを忘れると後続でエラー出て進めなくなります)

sudo apt update -y

それから、コラム通りに各種コマンドをインストールしていきます

sudo apt install build-essential automake autoconf git squashfs-tools ssh-askpass pkg-config curl -y
sudo apt install git libssl-dev libncurses5-dev bc m4 make unzip cmake python libwxgtk3.0-dev libgl1-mesa-dev libglu1-mesa-dev libglfw3 libglfw3-dev libglew2.0 libglew-dev -y
sudo apt install default-jdk unixodbc-dev -y
sudo apt install fop xsltproc libxml2-utils -y

sshの設定

ssh公開鍵を作ります

mkdir ~/.ssh
ssh-keygen -t rsa -f ~/.ssh/id_rsa

ssh接続設定ファイルを作ります

vi ~/.ssh/config

ファイル内容は、以下の通りです

~/.ssh/config
Host nerves.local
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  IdentityFile ~/.ssh/id_rsa

Elixirをインストール

Elixirを、Ubuntuの手順でインストールします(少し前に、Ubuntuはちゃんと最新版が入る手順へとElixir公式サイトがアップデートされたんです)

wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb && sudo dpkg -i erlang-solutions_2.0_all.deb
sudo apt update
sudo apt install esl-erlang -y
sudo apt install elixir -y

Hex、Rebarを最新化します

mix local.hex
mix local.rebar

Nervesをインストール

Nervesをインストールします

mix archive.install hex nerves_bootstrap

②fwupのインストール

microSDにNervesファームウェアを焼くための「fwup」コマンドをインストールします

なおfwupは、Windows側だけで無く、Ubuntu側にもインストールする必要があります

Windows側にfwup.exeをインストール

下記URLからダウンロードし、pathを通してください

fwup executable
https://github.com/fhunleth/fwup/releases/download/v1.8.3/fwup.exe

それから、立ち上げたままのUbuntuでは、このfwup.exeを認識できないため、一度Ubuntuのターミナルを落とし、それから「ファイル名を指定して実行」かコマンドプロンプトで下記コマンドを打ち、fwup.exeのpathが反映されたUbuntuを起動し直します

> ubuntu1804

Ubuntu側にfwupをインストール

Ubuntu上で、下記コマンドにてインストールします

wget https://github.com/fhunleth/fwup/releases/download/v1.8.3/fwup_1.8.3_amd64.deb
sudo dpkg -i fwup_1.8.3_amd64.deb

③Nerves開発

Ubuntu上で、mix nerves.new コマンドを使い、Nerves PJを作ります

mix nerves.new hello_nerves
* creating hello_nerves/config/config.exs
* creating hello_nerves/config/host.exs
* creating hello_nerves/config/target.exs
* creating hello_nerves/lib/hello_nerves.ex
* creating hello_nerves/lib/hello_nerves/application.ex
* creating hello_nerves/test/test_helper.exs
* creating hello_nerves/test/hello_nerves_test.exs
* creating hello_nerves/rel/vm.args.eex
* creating hello_nerves/rootfs_overlay/etc/iex.exs
* creating hello_nerves/.gitignore
* creating hello_nerves/.formatter.exs
* creating hello_nerves/mix.exs
* creating hello_nerves/README.md

Fetch and install dependencies? [Yn] Y
* running mix deps.get
Your Nerves project was created successfully.

You should now pick a target. See https://hexdocs.pm/nerves/targets.html#content
for supported targets. If your target is on the list, set `MIX_TARGET`
to its tag name:

For example, for the Raspberry Pi 3 you can either
  $ export MIX_TARGET=rpi3
Or prefix `mix` commands like the following:
  $ MIX_TARGET=rpi3 mix firmware

If you will be using a custom system, update the `mix.exs`
dependencies to point to desired system's package.

Now download the dependencies and build a firmware archive:
  $ cd hello_nerves
  $ mix deps.get
  $ mix firmware

If your target boots up using an SDCard (like the Raspberry Pi 3),
then insert an SDCard into a reader on your computer and run:
  $ mix firmware.burn

Plug the SDCard into the target and power it up. See target documentation
above for more information and other targets.

ビルドターゲットの設定として、「Raspberry Pi Zero and Zero W」向けの設定である rpi0 を設定します(なお、ターゲット自体は、Targetsページに記載されています)

export MIX_TARGET=rpi0

作成したNerves PJをビルドして、Raspberry Pi Zero WH向けのイメージファイルを生成します

cd hello_nerves
mix deps.get
mix firmware
==> nerves
==> hello_nerves

Nerves environment
  MIX_TARGET:   rpi0
  MIX_ENV:      dev

Compiling 2 files (.ex)
Generated hello_nerves app
|nerves_bootstrap| Building OTP Release...

* skipping runtime configuration (config/runtime.exs not found)
* creating _build/rpi0_dev/rel/hello_nerves/releases/0.1.0/vm.args
Updating base firmware image with Erlang release...
Copying rootfs_overlay: /tmp/hello_nerves/_build/rpi0_dev/nerves/rootfs_overlay
Copying rootfs_overlay: /tmp/hello_nerves/rootfs_overlay
Pseudo modify file "/lib/firmware/brcm/brcmfmac43430a0-sdio.ONDA-V80" does not exist in source filesystem.  Ignoring.
Parallel mksquashfs: Using 4 processors
Creating 4.0 filesystem on /tmp/hello_nerves/_build/_nerves-tmp/combined.squashfs, block size 131072.

Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
        compressed data, compressed metadata, compressed fragments, compressed xattrs
        duplicates are removed
Filesystem size 37931.65 Kbytes (37.04 Mbytes)
        57.99% of uncompressed filesystem size (65405.32 Kbytes)
Inode table size 19786 bytes (19.32 Kbytes)
        28.29% of uncompressed inode table size (69930 bytes)
Directory table size 23000 bytes (22.46 Kbytes)
        41.50% of uncompressed directory table size (55421 bytes)
Number of duplicate files found 13
Number of inodes 2106
Number of files 1725
Number of fragments 218
Number of symbolic links  165
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 216
Number of ids (unique uids + gids) 3
Number of uids 3
        root (0)
        piacere (1000)
        www-data (33)
Number of gids 3
        root (0)
        piacere (1000)
        www-data (33)
Building /tmp/hello_nerves/_build/rpi0_dev/nerves/images/hello_nerves.fw...

なお、fwupのインストールやpath設定が上手くいっていないときは、下記のエラーが出るので、fwupのインストールを見直してください

mix firmware
==> nerves
==> hello_nerves

Nerves environment
  MIX_TARGET:   rpi0
  MIX_ENV:      dev

** (Mix) fwup.exe is required by the Nerves tooling.

Please see https://hexdocs.pm/nerves/installation.html for installation
instructions.

④NervesファームウェアをmicroSDに焼く

ナント、以前はWindowsでは出来なかった mix burn が出来るようになってます、これは嬉しい:wink:

mix burn
==> nerves
==> hello_nerves

Nerves environment
  MIX_TARGET:   rpi0
  MIX_ENV:      dev

'\\wsl\Ubuntu-18.04\tmp\hello_nerves'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported.  Defaulting to Windows directory.
Use 59.48 GiB memory card found at \\.\PhysicalDrive1? [Yn] y

ちなみに、手動でfwupしたい方は、UbuntuがWindows側ディスクを /mnt/ 配下にマウントしているので、Windows側にコピーしてから、fwup.exeコマンドで実施できます

⑤NervesファームウェアをRaspberry Pi Zero WHで実行

microSDを、PCから抜き、Raspberry Pi Zero WHに差し、母艦PCのUSBとRaspberry Pi Zero WHの内側のUSBポートを繋ぐことで起動します(外側のUSBポートで繋ぐと動かないので要注意)

その後、Windows側で「USB Ethernet/RNDIS Gadget」が認識されるので、デバイスマネージャで「ポート(COMとLPT)」を開き、「USBシリアルデバイス(COMx)」の「ドライバーの更新」を行ってください
image.png

下記でドライバーをダウンロードし、解凍し、検索フォルダに指定してください

RPI Driver OTG
https://caron.ws/wp-content/uploads/telechargement/RPI%20Driver%20OTG.zip

無事、ドライバーがインストールされると、「ポート(COMとLPT)」から減り、「ネットワークアダプター」に「USB Ethernet/RNDIS Gadget」が追加されます
image.png

ここまでの設定が終わったら、一度、USBを抜き、差し直し、10秒ほど待ってから ssh nerves.local でssh接続します

ssh nerves.local
Warning: Permanently added 'nerves.local,172.31.195.153' (RSA) to the list of known hosts.
Enter passphrase for key '/home/piacere/.ssh/id_rsa':
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)>

やった、ssh経由で、Raspberry Pi Zero WH上のiexが動いたっ:confetti_ball:

早速、焼いたファームウェア上のアプリを実行してみると … おぉ、上手く動いてる

iex> HelloNerves.hello
:world

このiex上でモジュール定義をしてみても … よしよし、ちゃんと動いてる

iex> defmodule A do
...>   def a(), do: "I'm a in A"
...> end
{:module, A,
 <<70, 79, 82, 49, 0, 0, 4, 164, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 129,
   0, 0, 0, 14, 8, 69, 108, 105, 120, 105, 114, 46, 65, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 10, 97, 116, 116, 114, ...>>, {:a, 0}}
iex> A.a
"I'm a in A"

これでようやく、WindowsでのNerves開発にマトモに踏み込んでいけそうです

最後に

Docker+VSCodeでの手順は、実にお手軽で、WindowsにおけるNerves利用のメインストリームになりそうです

WSL2+Ubuntuでの手順も、VirtualBoxのものと比べたら、キビキビと動くことから、かなり快適で、コチラも有力な開発環境として使えます

相変わらずWindowsは、fwupが必要なものの、以前との大きな違いは、mix burn でSDカードに焼けるようになっており、手順がLinux版/macOS版と同じになっていた点は、とてもグッドでした

そして最大の感激ポイントは、sshが動くようになったこと … これは本当に嬉しかった

今回は、時間が無くて、NervesHubや、本体接続のディスプレイやキーボードを試すことは出来ませんでしたが、これらを調べつつ、Raspberry Pi OS上のElixir/Phoenixだけで無いプロダクション採用も検討できたらいいなぁって思います

あと、PhoenixやNeosVR接続を試すことも出来なかったので、これらも追々やっていきたいと思います

ひとまず、Windowsでも、エッジ/エッジサーバ/クラウドの全てをElixirで開発可能になった … やったね:tada:

p.s.このコラムが、面白かったり、役に立ったら…

image.pngimage.png にて、どうぞ応援よろしくお願いします:bow:


明日の記事は、@mnishiguchi さんの「[Elixir/Nerves] I2CでLCDに「Hello」」です

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1