はじめに
以前からずっと氣になっていた AtomVM に挑戦してみました。
きっかけは、IoT に詳しい @kurokouji 氏との出会い。とある勉強会で Elixir や Nerves の話で盛り上がり、AtomVM の魅力を教えてもらいました。
なんと、Seeed Studio XIAO ESP32-S3 も貸していただき、これはもう試すしかないという流れに。
ちょうど最近のカンファレンスでも AtomVM が話題になっていたところでした。参考までに以下のようなセッションも参考になりました。
- The AtomVM and New Horizons for Elixir
- La Machine: The Useless Box reloaded with Erlang and AtomVM
- Erlang and Elixir on IoT devices using AtomVM
少し前に、AtomVMの使いどころについて頭の整理をして軽くメモをまとめました。
本記事では、ESP32-S3 デバイス上で AtomVM をビルド・書き込みし、Elixir で書いた Blinky アプリケーションを動かすところまでの過程を記録します。
だれもがAIを使える時代です。
- 「AI があれば何でもできる。」
- 「元氣があれば何でもできる。」
- 「踏み出せば、その一足が道となる。」
そんな精神で迷わず手を動かしてみました。
この記事の内容は SWEST27 の LT でも共有予定です。
対象環境・機材
今回の開発環境・使用機材は以下の通りです。
ハードウェア
- ボード: Seeed Studio XIAO ESP32-S3
※オンボードLED(GPIO 21)が使えます。
ホスト環境(開発用PC)
- Debian 系 Linux(LMDE6)
- Elixir 1.17(Erlang/OTP 27)
- AtomVM v0.6.6
- ESP-IDF v5.5(Espressif 公式SDK)
- esptool 5.0.1(Flash 書き込み用)
生成AI
- ChatGPT(
o4-mini-high)を活用
まずは資料
IoTのことも、ESP32のことも、AtomVMのこともほとんど知らなかったので、まずは基本的な情報収集から始めました。
公式ドキュメント・リポジトリ
AtomVM は公式ドキュメントが充実していて、とても好印象でした。
-
公式サイト
→ インストール手順、ビルド方法、サンプルの使い方など -
GitHub リポジトリ
→ ソースコード本体と、ESP32向けファームウェアのビルド環境など -
GitHub Releases
→ ビルド済みファームウェアや過去バージョンの情報もここから確認できます
サンプルコード集
AtomVM には Elixir や Erlang で書かれたサンプルが複数あります。
2025年8月時点では、以下の2つのリポジトリで若干異なるサンプルが管理されています。
バージョン依存情報
以下に、必要なソフトウェアのバージョン要件がまとまっています。
AtomVM のインストール
今回の目的は、ESP32-S3 デバイス上で AtomVM を動かし、Elixir で書いたコードを実行することです。
まずは公式が紹介している「ビルド済みイメージ」を試してみましたが、うまくいかず……。
結局、ソースからビルドして書き込む方法で無事成功しました。
ビルド済みイメージ(試したけど断念)
公式 Getting Started ガイド によると、Releases ページ からビルド済みの AtomVM ファームウェアをダウンロードできるとのこと。
試してみましたが、うまく動かず…!
(何も理解していない段階だったので、どこが原因かも分からず。)
後日もう一度試したいですが、今回は潔くあきらめて、ソースコードからビルドする方針に切り替えました。
ソースコードからビルド(こちらは成功)
こちらの公式ドキュメント に従って、ESP32-S3 用ファームウェアを自分でビルドします。
以下の3ステップで進めました:
- ESP-IDF のインストール(ESP32-S3 向け)
- AtomVM のソースコードを取得してビルド
- ESP32-S3 用ファームウェアをビルド
ESP-IDF をインストール(ESP32-S3 向け)
AtomVM のビルドには、Espressif の公式 SDK である ESP-IDF が必要です。
参考リンク:
# 必要なツールをインストール
sudo apt install git wget flex bison gperf cmake ninja-build \
ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
# esp-idfの保存場所は任意
mkdir -p $HOME/esp && cd $_
# ソース取得&セットアップ
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
# 安定版に切り替え
git checkout v5.5
git submodule update --init --recursive
# esp32s3 向けツール群をインストール
./install.sh esp32s3
# 現在のシェルに IDF 環境を読み込む
source ./export.sh
AtomVM をビルド(ホスト環境)
# AtomVMの保存場所は任意
mkdir -p $HOME/Projects/atomvm && cd $_
# ソースを取得
git clone https://github.com/atomvm/AtomVM.git
cd AtomVM
# 安定版に切り替え
git checkout v0.6.6
# ホスト環境向け VM のビルド
mkdir -p build && cd build
cmake ..
make -j$(nproc)
ESP32-S3 向けファームウェアをビルド
# ESP32用のAtomVMファームウェアをビルドするための CMake プロジェクトのルート
cd $HOME/Projects/atomvm/AtomVM/src/platforms/esp32
# 現在のシェルに IDF 環境を読み込む
source $HOME/esp/esp-idf/export.sh
# ターゲットを設定
idf.py set-target esp32s3
# 再構成とビルド
idf.py reconfigure
idf.py build
AtomVM を ESP32 に書き込み
前のファームウエアが残っていると不安定になることがあるので、ESP32デバイスから消去することが推奨されています。
esptool --chip auto --port /dev/ttyACM0 --baud 115200 erase-flash
以下のコマンドでESP32-S3 上に AtomVM を書き込みます。
cd $HOME/Projects/atomvm/AtomVM/src/platforms/esp32
# 現在のシェルに IDF 環境を読み込む
source $HOME/esp/esp-idf/export.sh
idf.py -p /dev/ttyACM0 flash
Blinky を Elixir で作って実行する
AtomVM のビルドと書き込みが無事終わったら、いよいよ Elixir アプリケーション側を準備します。
最初の目標は、オンボードLED(GPIO 21)を 1秒ごとに点滅させる Blinky を作って動かすことです。
サンプルコードを取得
AtomVM 公式の Elixir サンプル集から Blinky プロジェクトを取得します。
# サンプルプロジェクトの保存場所は任意
cd $HOME/Projects/atomvm
git clone https://github.com/atomvm/atomvm_examples.git
cd atomvm_examples/elixir/Blinky
依存ライブラリ(ex_atomvm)を取得:
mix deps.get
GPIO ピン番号を変更(XIAO ESP32-S3 用)
Seeed Studio XIAO ESP32-S3 のオンボード LED は GPIO 21 に接続されています。
デフォルトのサンプルは GPIO 2 なので、以下のように修正します。
defmodule Blinky do
@pin 21
def start() do
:gpio.set_pin_mode(@pin, :output)
loop(@pin, :low)
end
defp loop(pin, level) do
:io.format(~c"Setting pin ~p ~p~n", [pin, level])
:gpio.digital_write(pin, level)
Process.sleep(1000)
loop(pin, toggle(level))
end
defp toggle(:high), do: :low
defp toggle(:low), do: :high
end
AVM ファイルを生成
mix atomvm.packbeam
成功すると、以下のような .avm ファイルが生成されます。
ls -l *.avm
#=> -rw-r--r-- 1 user user XXXX年XX月XX日 Blinky.avm
この .avm ファイルが、ESP32-S3 上で実行可能な AtomVM アプリケーションになります。
アプリケーションの書き込み
以下のコマンドで、先ほど生成した .avm ファイルをESP32-S3 に転送します。
mix atomvm.esp32.flash --port /dev/ttyACM0 --baud 115200
これだけでアプリケーションの更新ができます。
AtomVM 本体は再書き込み不要です。.avm アプリケーションだけを何度でも差し替え可能です。
シリアルログの確認
LED がチカチカするのと同時に、ログも出力されているはずです。
以下いずれかで確認できます。
方法1: idf.py monitorを使う
cd $HOME/Projects/atomvm/AtomVM/src/platforms/esp32
source $HOME/esp/esp-idf/export.sh
idf.py --port /dev/ttyACM0 monitor
- 終了方法:
Ctrl+]
方法2: picocom等を使う
picocom /dev/ttyACM0 --baud 115200
- 終了方法:
Ctrl+A→Ctrl+X
どちらを使うべきか
idf.py monitor がログの内容が見やすくて個人的には好みです。
とはいえ、実行前に2つの準備作業が必要で、毎回はちょっと手間です。
- ESP-IDF の環境をロードする必要がある(
source $HOME/esp/esp-idf/export.sh) - AtomVMのESP32プロジェクトディレクトリ(
AtomVM/src/platforms/esp32)に移動してから実行する必要がある
これらを毎回手作業でやるのはちょっと大変そうだったので、以下のような専用スクリプトを作って運用しています。
$HOME/Projects/atomvm/scripts/esp32-monitor.sh
このスクリプトは、以下の処理を自動でやってくれます:
- ESP-IDF の
export.shをsource - AtomVM の ESP32 プラットフォームディレクトリへ
cd -
idf.py --port /dev/ttyACM0 monitorを起動
monitor用スクリプト紹介
AtomVM 関連のプロジェクトは $HOME/Projects/atomvm/ 以下にまとめて管理しています。
そのため、各アプリケーションプロジェクトからは、以下のように一行でモニタを起動できます:
../scripts/esp32-monitor.sh
開発サイクル
Elixirコード編集後はElixir アプリケーションを更新・転送するだけです。AtomVMファームの書き直しは不要です。
まるでスクリプトのような軽快さで、組み込み開発が楽しめます。
# .avm を再生成
mix atomvm.packbeam
# デバイスに再書き込み
mix atomvm.esp32.flash --port /dev/ttyACM0
AIをどう活用したか?
AtomVMについて学ぶ際には、ChatGPT(o4-mini-high)を活用しました。特に助けられた場面は以下の通りです。
-
Elixirでまだ未実装の関数
→ AtomVMに対応していない関数でも、Erlang 標準ライブラリや AtomVM API で代替できることが多い -
似た処理をする C/C++ の既存ライブラリを AI に読ませる
→ AtomVM 上で使えるように Elixir で書き直す際のヒントになった -
とはいえ、AIだけでは解決できない部分も多く、組込み経験のある仲間からの情報が突破口になる場面も
今回の学びは、AIの活用と、人との交流(コミュニティ)の両方があってこそ前に進めるということでした。
おわりに
AtomVM を使うことで、Elixir や Erlang の強みを、リソース制限のある組み込みデバイス上でも活かせることがわかりました。
AIによるヒントと、経験豊富な仲間の一言が組み合わさることで、次の一手が見える瞬間が何度もありました。
今回の Blinky は最小構成の第一歩ですが、今後はより複雑なサンプルにもどんどん挑戦していきたいと思います。
image credit: piyopiyo.ex and nako-san

