ハードウェアからサーバ・アプリまでワンストップで開発

第5回 Arduinoを見直してみる

単なる「入門者」のものではなくなっていると思いますよ

仕事で組み込み開発するのは別として、世間で「マイコンのソフト開発」となるとArduinoがよく使われます。「Arduinoというハードウェア」を使わなくても「ArduinoというSDK」が使われることは多いです。マイコン開発でオープンな情報が欲しくて検索する時には、native SDKの情報が欲しくて-Arduinoをつけて検索することは結構あります。つまり、逆に言えばそれくらい使われているわけですね。

他方、仕事で組み込み開発をする人達はあまりArduinoに信用も期待もしていません。私個人もあまり好きではありませんでした。一般公開するために敢えてArduinoを使う時を除けば、自分から積極的にArduinoを使うことはなく、可能な限りnative SDKかそれに相当するものを使うことにしていました。

ただ、ここに来て

何もnative SDKにこだわることはないのではないか?

と思うようになって来ました。逆にnative SDKは面倒なだけでデメリットの方が多いのではないかとさえ思うようになりました。他方、Arduinoの世界も結構進化していて、弊社で引き受けるような比較的軽いマイコン制御であれば、Arduinoで十分じゃないかと思うようになって来ました。

事の発端

いきなり「Arduinoでいいじゃないか?」と思うようになったのには、もちろん理由があります。ちょっとその辺も書いてみようと思います。

ESP-IDFの裏切り

ESP-IDFというのは、Espressif Systemsの出しているESP32等のnative SDKです。

ESP32にはEspressif公式のArduinoも出ているのですが、Arduinoにはいろいろ微妙な点がある(と思っていた)ので敬遠していました。私は敬遠していましたが、ググってみた感じからするとArduinoの方が情報は多いようです。まぁ情報が多いとは言え玉石混交ですし、特にArduinoは初心者の「やってみました」みたいなエントリが多いということもあって「情報源」とするには心許ないものも結構あるのですが、逆にそういった情報が役に立つということもあったりして面白いです。ただまぁ敬遠してたんですね。

自分でもESP-IDF用にNeoPixel用のドライバを作って公開していたりしました。

NeoPixel driver for ESP-IDF

これは一昨年、教会のアドベントろうそくのために使っていました。多分元々はJar-Gardenの試作の時に作ったんじゃないかと思います(記憶にない)。

ろうそくの先にLEDがついてますね。詳しくはリンク先のエントリを見て下さい。

それを去年はさらにバージョンアップして(と言うか当初の計画通りに)「NTPで日付時刻を取得して自動的に点灯するろうそくを判定する」という機能をつけようと思って、「まずは再コンパイルして」と思ったのですね。ところが、ESP-IDFの内部構造が変わってしまったせいで、件のドライバはコンパイルすら通らなくなりました。

自分の書いたプログラムですから移植してしまえばいいのですが、なんとなく面倒臭くて気分が乗りませんでした。またそれ程オリジナリティがあるコードではありませんし(READMEにあるように元々はMicroPythonからパクって抽出して来たコードです)、そもそも自分のやりたいことは「NeoPixelをドライブすること」ではなくて「アドベントろうそくを作ること」ですから、ライブラリが動くことそのものに興味がありません。同じような方法でやっている他のプログラム(ドライバ)はないかと思って探したら、Arduinoには結構あることを発見しました。「NeoPixelの」と書かずに「同じような」と書いたのは、NeoPixelそのものではないので、パルスのタイミングが違うためです。秋月に売ってる「いい感じのLED」を買ったらそうだったわけです。

元々のプログラムは高々「ろうそくっぽくLEDの点灯を制御する(チラつきを表現したりとか)」だけでしかなかったので、まるっとArduinoに移植したらあっさり動いてしまいました。まぁ当たり前っちゃー当たり前ですね。ついでなので、付加しようと思っていた「NTPから日付時刻を取得して点灯を制御する」というのも書いてしまって、去年のアドベントはこれを動かしていました。教会に来る人達にとっては、「ろうそくLED」のファームが何で書いてあっても関係ないですからね。

それ以前にも、ESP-IDFは開発環境であるラズパイの上でうまく動いてくれなかったり、バージョンアップする度に非互換が発生したりと、結構泣かされていました。バージョンアップで動かなくなるなんてのは、Railsだけにして欲しい。

他方この程度のことであれば、native SDKでないと出来ないことはまずありません。と言うか「SDK」なんてものを頼る限りAPIとしての違いがあるくらいで、出来ることに違いがあるわけでもありません。それどころかArduinoの方が利用者が多い(っぽい)ことや「初心者」も使っていることもあって、ライブラリの品質も期待できます。この辺の事情は

往時のLinux

と同じようなことを感じます。素性のいいBSD系よりもタコ初心者の多いLinuxの方が、結果的に使いやすくパフォーマンスも良くなったことを思い出します。

開発対象の多様化

ちょっと前から、とあるデバイスの開発を引き受けています。これは業務なので、あまり詳しいことは書きませんが、それまで使ってなかったSoCを2種類使っています。片方はnative SDKを使い、もう片方は組み込み済みのファームを使っているのですが、「組み込み済みファーム」のある方のSoCは他のことにも使えるなぁと思ってデータシートを見ています。こちらには今回は使いませんでしたが、Arduinoがあります。

Jar-Gardenは現在ESP32で作っているのですが、これを件のSoCで作ってみたらどうなんだろうなと思っています。実際にやるかどうかは別ですけど。

また、無線関係のSoCやモジュールとして最近ちょっと注目しているものとしてRTL8720DNがあります。これは5GHz帯も使えるWi-Fi SoCで、Seeedが技適を通しています。残念なことに、Seeedが販売しているRTL8720DNのモジュール単体(BW16)では技適を通ってないのですが、Wio Terminalは技適が通っていたりするので、遠からず「来る」のではないかなぁと期待しています(通っているのは「Wio Core(RTL8720DN)」というモジュールです)。そう思って調べたりドキュメントを翻訳していたのですが、これのnative SDKは結構不親切なのでどうしたものかと思ってます。ちなみにこれもArduinoがあってそれでは単体で動くことを確認しています。

その他で注目しているのはSipeedの諸々のモジュールです。RISC-Vのベンダですが、AI向けのモジュールを作っていて入手性も結構良いです(秋月でも買える)。ちょっとした「ロボットおもちゃ」を作るには程良い感じで、YOLOを実用的な速度で動かすことが出来たりします。ここはnative SDKにはあまり力が入ってない感じで、C等でプログラムを書く場合はArduinoになってしまうようです。

その他にも気になるSoCやモジュールはいろいろあるのですが、native SDKはいろいろ微妙だったり過剰に面倒臭かったりしているので、手軽に何か作ったり試したりするにはArduinoが一番早かったり楽だったりします。

そのSoCやモジュールを使い続けるというのであれば、native SDKなりよりハードに近い部分なりをいじるようにすると思うのですが、そういった変化の激しい世界で

プロトタイプ半

みたいなものを作ったり試したりするのであれば、Arduinoに利があります。

そもそもnative SDKって必要だったのか?

いきなり卓袱台返しみたいなことを言うようですが、native SDKって必要だったのでしょうか?

ハードウェア、特にマイコンに搭載されているペリフェラルの能力を完全に使い切るためには、ハードウェアを直接操作するに限ります。動作の見通しは良くなりますし、余分なコードを含むこともない。「メモリ1バイトは血の一滴」という価値観の中ではこれは当然だと思います。なので、まさにそういった価値観の中で生きて来た人達にとっては、それが当然であって、ベンダ提供のライブラリでさえも忌避されたりします。これは「メモリ」に限った話ではなくて、「電力1マイクロワット」でも同じです。完全にコントロールに置いてこその完成度というのはあるものです。

そういった領域だとnative SDKすら不要です。ちゃんとしたtoolchainがあれば、後はデータシートを見ながらハードウェアを操作するコードを書く。うまく出来れば自分の(あるいは自社の)ライブラリとして「秘伝のタレ」にします。

native SDKが活躍するのは、そういったレイヤのものではありません。ハードウェアの動作は「ライブラリのAPI」の中に隠蔽され、より抽象度の高い操作が出来ることを求めます。I2Cで通信する時に制御レジスタやDMA、割り込みベクタ... 等を操作するのではなく、たとえば「I2Cの○番にデータを送る」というような粒度でプログラムを書くわけです。

ベンダにも依りますが、ある程度の契約をすればプロプラなnative SDKであってもソースコードにアクセスが可能なことは多いです(出来ないこともある)。最近の中華SoCだと結構オープンソースになっていたりします。そうすれば、native SDKと言えどもブラックボックスではありませんから、自分でハードウェアを直接操作するライブラリを作ることと同等のことが可能になります。ですから、かつてはこのレイヤでプログラムを書くことが現実的でした。

でも実は同じことはArduinoでも出来ます。多くのArduino SDKはオープンソースであったりそうでないライセンスであってもソースにアクセスすることが可能であることは多いです。必要であれば、改変してしまうこともできます。もちろんArduinoの枠組みを崩すような改変をしてしまえば後々厄介なことになったりしますが、そうでなければ「やろうと思えば出来る」程度には改変することが出来ます。

そもそも、少量多品種の時代に「メモリ1バイトは血の一滴」という価値観が必要なんでしょうかね? 100K以上の規模で量産するようなものならいざ知らず、多くても10Kくらいしか量産しない何なら1Kも作らないようなもののマイコンが100円だろうと1000円だろうと、そんなに製品価格が変わったりはしません。そんなことよりも開発費を抑えられる方がずっと製品価格を下げられるでしょう。1Kしか作らない場合、工数1人月はBOM価1000円(以上)に相当しますからね。

そういったことを考えると、何もnative SDKにこだわる理由もないのではないかと考えられます。

Arduinoの嫌な点

そんなわけでArduinoは結構楽にいろいろ出来るのですが、今まで使わなかったのにはもちろんそれなりの理由があります。そして、多分これらは私以外の「Arduino嫌い」に共通している部分でもあると思います。

私が個人的に嫌だと思っている(た)ことは、

  • IDEの使用が前提である
  • ボードにある程度の仮定をしていてライブラリもそれが前提になっていることが多い
  • マルチスレッドへの対応が悪い
  • ハードウェアの持つ機能が活かせない(ような気がする)
  • 品質がよくわからない

というあたりですね。その他の心理的な障壁としては

素人臭い

というのもありますね。正直、このエントリも「WASPは組み込みの開発にArduinoなんか使っている」みたいに言われるのではないかと警戒しながらだったりします。もちろんまだ使っていませんよw

そんなわけで、以下にこの嫌な点だと思っていたことと、その現状について書いてみようと思います。これらがどう解決されたかを見て、それでもなお「あんな素人臭いものを」と批判されるのであれば、まぁ御自由にと。

以下個別に嫌な点についての解説を書きますが、ごく大雑把にまとめてしまうと

たいていは過去のことか気にする必要のないこと

だと言ってしまって良いと思います。つまり、今となっては「先入観」に基づくものであると言っても良いかも知れません。

IDEの使用が前提である

正直これが一番嫌です。

いや、IDEというのであれば普段VS Codeとか使っているわけですし、それ以前にもEclipseやNetBeansを使ったりしていて、それらには抵抗はありませんでした。でもあのIDEの使い辛くダサいことよ。他のcoolなIDEと比較すると、一段落ちるという感は否めませんでした。IDEをあれしか知らない人にとっては快適なのかも知れませんが(そうなの?)、他のエディタやIDEを使い慣れていると結構嫌なものです。そもそも、普段使っているエディタやIDEとは異なるIDEを要求するという点で嫌ですね。エディタやIDEは「普段使い」のものを使いたいですよね(今はVS Codeのプラグインにあったりします)。

さらにIDEを前提としているものに共通する嫌なこととして、「そのIDEの上でないとbuildできない」ということがあります。全てが全てそうではないのですが、そこで読めるソースファイル以外の何か環境設定ファイル的なものにbuildの環境が入っていて... つまり、ソースアーカイブが全てではないという嫌らしさがあったりしました。要するにIDEが単なる開発のための環境ではなくて、ビルドツールを兼ねていたりしたわけです。ソースアーカイブを手に入れても、IDEがないとビルドが出来ない。もちろんMakefileなんてものはありません。それゆえに、ある程度の規模のものだと出来上がったものをソースでリリースするのは結構厄介でした。単一のソースで何とかなるものなら問題もないのですけど。

そういったことを問題視してはいましたが、実はArduinoにはPlatformIOという抜け道がありました。抜け道というと語弊があると思うのですが、

Arduinoのライブラリを使うコマンドラインツールでの開発環境

がありました。これを使えば、「だいたいArduino」という感じで開発出来ました。ライブラリはそのままArduinoのものが使えます。どうしてもAndroid IDEを使いたくないとか、コマンドラインツールで完結させたいとか、そういった需要を満足させてくれるツール群です。これであればソースを編集することやデバッガは使い慣れたものが使えます。そういった意味では、Arduinoの一番「嫌」なところが解決されていたと言って良いと思います。

今回はPlatformIOとArduinoの関係やPlatformIOについて深く触れることはしませんが、ある種の発展形であることは事実です。普通の状況であればIDE抜きでArduinoが開発できるという点で悪いものではありません。また、最近ではArduino以外のことにも対応している汎用開発プラットフォームです。

とは言え、ごく特殊な条件の時には、PlatformIOはArduinoと完全上位互換ではありません。理由はよくわからないのですが、ArduinoにあってPlatformIOにはないものがあったりします(多分逆もある)。単なる「コマンドライン版Arduino」とは言えないようです。

ところが比較的最近になって、Arduinoにも「Arduino CLI」というものが使えるようになりました(逆にPlatformIOにはIDEが出来ました)。これはArduino本家が出している公式のコマンドライン環境です。これはまさに本物で、Arduinoにあるものは全てあります... だけではなくて、どうやら最新のArduino IDE(2.0)のバックエンドのようです。つまり互換環境や移植環境ではなくて、本家直系の純正品です。

と言えば、最新のArduino IDEはあの微妙なものではなくなり、VS Code派生のEclipse Theiaベースのものになりました。「Eclipse」という言葉に一瞬怯みますが、TheiaはEclipse財団のものであるだけでコードは別物です。Theiaは「Monaco」を使ってTypeScriptで書かれたもので、Javaで書かれたいわゆるEclipseとは違います。

そんなこともあって、ArduinoもIDEを前提としたものではなくなりましたし、そのIDEもあの独自のものではなくなりました。ArduinoにはMakefileみたいなものがなくて、楽とは言え不便な側面があったりしましたが、Makefileみたいなもの(CMakefileとか)も書こうと思えば書ける程度にはなりました。build条件を設定ファイルで操作するといったことも、やれば出来る程度にはなっています。

そんなわけで、一番嫌であったことは既に解決済みです。

他方、native SDKは結構ガチガチのMakefileを要求していたりして、「やりたいこと」をするには相当調べないと出来なかったりします。しょうがないので言われるままにお手軽設定で使ったりしてしまうことになって「せっかくあるのにないも同然」だったり「面倒だけある」みたいなことになっていたりするので、殊更にArduinoだけがダメだったわけでもないと思います。ESP-IDFのidf.pyのような「万能コマンド」とか見るとArduino(CLI)と大差ないように感じます。

ハードウェアに何らかの「仮定」が存在している

元々ArduinoはArduinoというハードウェアのものです。

Arduino UNO

これはピンの用途が決まっていて、ライブラリもそのピンの機能を実装するというものでした。今でも、この形状のピンがついているものは、そういった構成になっていたりします。

Arduino(というライブラリ)がArduino(というハードウェア)の上のものであった時代、あるいはCPUやSoCが異なるものであってもピンが同じ構成なものである場合、ライブラリもそのような実装になっていました(す)。CPUやSoCによって同じピンが提供できない場合は、bit bangを行うコードで無理やりの実装がされているものもありました。おそらく気持ちとしては「どんなマイコンを使ってもArduinoはArduinoとして互換性がある」みたいな感じだったんだろうと思います。

MaixDuino(SipeedがMaixで作っているArduino)やPiunora(Raspberry Pi CM4を使ったArduino)の回路とか見ると、随分と無理やりの実装がされているのを見ます。ライブラリも結構頑張っている感じです。

Maixduino
Maixduino
Piunora

MaixDuinoの「アナログピン」にはWi-Fi用に載っているESP32のアナログピンがつながっています。とは言え、MaixDuinoの本体SoC(K210)上のArduinoはそのピンを直接使うことができません。Piunoraが使っているCM4にはアナログピンは存在していないので、ベースボードの上にADCが載っています(右下のチップです)。

これらはいわゆる「シールド」を使うためにそうやっているのだろうと思いますが、結構な無理をしているなと思います。ライブラリも大変ですし、その実装が成功しているかどうかは... それに、「Arduinoを使う」という時に「シールド」がセットである必要性は、あったりなかったりします。

そういったある種「必要な人には必要だけど、不要な人にとってはどうでもいい」ことのために、ハードウェアやライブラリが苦労していたり、プロトタイプや製品にそういったものが含まれているというのは、なんかこう

よけいなもの

のために苦労しているだけじゃなくて、邪魔な存在だったりします。いかに「お手軽なものでマイクロコントローラを実装したい」と思っていても、その代償として「よけいなもの」があったりするのは、ちょっとムダなような気がします。ただでさえメモリの少ないマイコンでには、「よけいなもの」のために死蔵させるメモリなんてないのです。ピンを制限すればレジスタの設定だけで使えるI2Cをどのピンでも使えるようにするためにbit bangのコードを持つ必要はないですし、本気で使うには低速低解像度のADCのために余計な回路が載っている必要もそれをドライブするコードも不要です。機種別のArduinoのコードを見るとしばしばそんなものを見掛けたりして、「ちょっとなぁ」と思ったりします。それが理由でESP32のArduinoを敬遠していた時代もあります。

とは言え、「Arduinoというハードウェア」から離れてArduinoは単なるAPIでありSDKであると考えてしまえば、そういった「無理やりのコード」が存在していても結局リンクされなかったりします。つまり、

気にしなければ邪魔にもならない

ものだったりするわけです。本来GPIOしか使えないピンを無理やりI2Cで使ったりしなければ、bit bangのためのコードは含まれない(かもしれない)のです。実装依存ですけど。

また、「Arduinoというライブラリ」としてのArduinoを見ることに特に障害となるようなこともなくなりました。「Arduinoというライブラリ」は「Arduinoというハードウェア」の設計とはかなり切り離されています。ピンのマッピングのこととか周辺ハードウェアとかに気をつければ、自作ハードウェアの上でのArduino(API)とかも難しいことではなくなりました。

そういったわけで、この辺のことを気にする必要は、普通に出回っているライブラリに関してはなくなったものと思って良いと思います。

マルチスレッドへの対応が悪い

ちょっと前のArduinoは基本的にシングルスレッドで動くものでした。

setup()を呼び出して初期化して、loop()で無限ループとして本体処理をして。元々の「マイクロコントローラ」という考え方には必要にして十分だったと思います。今でも、たいていのものはこれで済んでしまいます。

他方、ちょっと頑張って「組み込みシステムの環境」として使うには、何らかのRTOSがあった方が楽です。単一のスレッドでいろんなことをやるのは、結構なテクニックが必要ですが、マルチスレッドに出来るのであれば、かなり見通しが良くなります。また今時のCPUは結構高速高機能なので、マイコンと言えども頑張ればいろんなことが出来ます。無理して高度なテクニックを使って頑張る必要もありませんが、いくつもマイコンを並べるというのはあまりスマートではないですよね。

そういったことを考えると、今時のマイコンを「ちょうどいい感じ」に使うためには、マルチスレッドが出来る方が嬉しいものです。

ちょっと前まではArduinoではそういったことは出来ませんでした。「出来ませんでした」というのは語弊がありますが、あまりそういった使い方は一般的ではありませんでした。また、それ用のライブラリ等もないわけではありませんが特殊なものという扱いでした。つまり、マルチスレッドは「どうせライブラリのすることなんでないってわけではないのだけど方向としては傍流」みたいな存在でした。古典的なArduinoはメモリが少なかったこともあって、あまりそういった話題はなかったように思います。

最近はFreeRTOSのライブラリは普通に存在しています。もちろん全ての環境で動くわけではないですが、「動かせる程度の規模のプロセッサにはある」程度にはあるので、使えないとか特殊な使い方だとかということはなくなったようです。

ハードウェアの持つ機能が活かせない(ような気がする)

ArduinoはAPIが標準化されていますから、マイコンやSoCの固有な機能が直接見えなくなっています。

この「固有な機能」はマイコンやSoCの特徴と言えるもので、特にこの種のマイコンやSoCはそういった部分をいい感じにサポートすることをセールスポイントとしています。ですから、ある意味「APIの標準化」と「特徴あるデバイス」は背反するものだとも言えます。

一般にAPIを標準化した場合、実装はそのAPIに合わせることになります。なので、「ハードウェアに固有な機能」もそのAPIに合わせて使われることになります。「ハードウェアに固有な機能」がごくプリミティブなものであれば、そういった機能を組み合わせてAPIを実装することになりますから、特に問題となることはありません。しかし「高機能な便利機能」であれば、標準化されたAPIではその機能を十分に生かせないかも知れません。

たとえば、Raspberry Pi picoやNXPの比較的最近のチップ(LPC-8xxとか)には、非常に高機能なタイマーブロックがあります。これらは「設定だけでコンポジットビデオ信号を発生」させることが出来る程度に高機能です。タイマと言うより、そこだけ独立したプロセッサがあるようなものです。

残念ながら、こういったものの機能を100%使えるようなArduino APIは存在しません。どうしても使いたければ、そういったものを直接叩くようなプログラムを書く必要があります。

また、多くの無線を内蔵しているSoCのnative APIには「イベントループ」というものがあって、その中で発生するイベント(突然回線が切れたとか)にきめ細かく対応した処理を書くことが出来ます。きめ細かく書けるのはいいんですが、結構面倒臭かったりします。ArduinoのAPIだと、そういった面倒臭いことは不要な代わりに、細かい対応は出来ません。

というように、マイコンやSoCが高機能になったこととArduinoのライブラリの機能は、必ずしも一致していません。そういった意味だと、Arduinoに頼ることは「もったいない」のかも知れません。

ただ、この辺は「考えよう」の問題であるとも言えます。

Arduinoになければ、自分で勝手に書いてしまえば良いだけです。つまり、

ほとんどArduinoだけど、部分的にnativeで書く

ようにすればいいわけです。その「native」としてnative SDKがArduinoと混ぜて使えるかどうかは実装依存の話ですが、ArduinoはいわゆるOSではないのでレジスタのリソース管理まではしていませんから、Arduinoの動作に影響を与えないレジスタは勝手にいじることが出来ます。つまり、「高機能タイマ」が使いたければ直接レジスタを操作してしまえば良いわけです。

また、多くのArduinoのライブラリはオープンソースなので、「イベントループ」に小細工したければライブラリの中に手を入れてしまえば良いわけです。固有に実装したコンポーネントとして扱ってしまえば、配布の問題も起きないでしょう。

他方、「Arduinoというフレームワーク」はとても便利でよく考えられています。同様なものを作ろうとした人ならわかると思いますが、自分で実装してからArduinoのコードを見ると、「よく考えられているな」と思うことがしばしばあります。つまり、

Arduinoという考え方

はいろいろ学ぶべきところがあるということです。なので、Arduinoの標準的なライブラリが気に入らなければ、Arduinoというフレームワークを使って自分で再実装してしまえば都合が良いです。この辺はCSSフレームワークBootstrapが、ライブラリとしてはダサくてもフレームワークとしては結構便利であるということに似ています。実装は勝手にやってもいいんだけど、フレームワークには乗っておくのが良いわけです。

最初の方で「いくつか注目しているマイコンがある」という話をしていますが、それらを全く同じものとして使いたいわけではありません。と言うか、仮にそうであるなら異なるマイコンを使う必要なんてありません。でも、「マイコン」という範疇であれば、「マイコンとして共通なこと」と「そのマイコンの特徴的なこと」とがあって、前者を扱う時であればArduinoライブラリを使えばいいし、後者をその環境で使いたいのであればArduinoをフレームワークとして使えばいいわけです。

もちろん全部をnative SDKで書くとかレジスタレベルで直接叩くとかの方法はありますし、「メモリ1バイトは血の一滴」のような環境であればそういった方向で頑張ることも意味があるでしょう。しかし、現代のマイコンの高性能化高機能化とか多品種少量生産という環境を考えれば、

ほとんどArduinoだけど、部分的にnativeで書く

ことで楽をしても良いんじゃないかと思います。

品質がよくわからない

シビアな組み込み開発、特にハードコアな部分での開発をしている人とか、OTAが一般的でない世界にいる人達にしてみると「品質」というのは全てに優先すると言っても過言ではないでしょう。個人的にはこの考え方にはいろいろ思うところもあるのですが、品質は低いよりは高い方がいいということには、まぁ間違いはないでしょう。そうなると気になるのが「Arduinoライブラリの品質」だと思います。これを理由に「Arduinoなんて」と言う人(たいていは老害年齢なんですが)は少なくありません。

ごく雑に調査した範囲では、Arduinoライブラリの品質は

まちまち

と言っていいと思います。品質のいいものもあれば悪いものもある。ソースを見ても「なんじゃこりゃ?」と思うものもあれば感動するレベルのものもある。なので「Arduinoだから」ということで何かあるかと言えば、

と思います。最近だと、「チップメーカ純正Arduinoライブラリ」なんてものがあって、結構ちゃんとしたものを使うことが出来るものもあります。

他方、同じことはnative SDKでも言えます。品質の良いものもあれば微妙なものもある。ソフトウェアとして当たり前のことです。私の経験でもプロプラなnative SDKのコード見ていて「なんじゃこりゃ?」と思ったことは何度かあります。

自分で書いてテストを充実させればという話もありますが、正直なことを言えば「それが一番信用できない」と思っています。お陰で自分で頑張る系のSTM32は気持ちが重いです。むしろ、他人の手垢がついてるライブラリの方がずっと信用できます。

ただ幸いなことに、たいていのArduinoライブラリはライセンスがどうであれ(と言ってもたいていはLGPLだと思いますが)、たいていはソースを参照することが可能です。つまり、本当にライブラリが信用できるかどうか判断したければ、ソースを読めばいいわけです。中にはオープンソースライセンスでないものもあるかも知れませんが、それでも読むことが可能であることがほとんどです。品質が気になるようであれば、あるいは実装の限界が気になるようであれば、ソースを読めば何とかなります。

Arduinoのいいところ

Arduinoの嫌な点とされているものを挙げて、「今はそんなことないよ」ということを説明して来ましたが、最初からある良い点もあります。私が思うことだと、

  • フレームワークがちゃんとしていてAPIが統一されている
  • コンポーネントが豊富にあって流通している
  • 情報源が多い

以下ではこれらに軽く触れておきます。

フレームワークがちゃんとしていてAPIが統一されている

Arduinoで何が一番嬉しいと言って、これが一番ではないでしょうか?

Arduinoはマイコンに依らずボードに依らず、基本的に共通のAPIの中で動きます。たとえば「I2Cを操作」したければ、Wire.hをincludeしてWireというクラス(正確にはインスタンスなんですが)を操作すれば使えます。これはマイコンが何であっても同じです。ATMEGAであろうとSTM32であろうとESP32であろうと同じです。native SDKだと名前が異なったりAPIの粒度が異なったりするのですが、Arduinoであれば同じです。

また、上述のWire.hをincludeしてWireというクラスみたいなインスタンスを操作するという操作方法は、他のもの(SPIやSerial)でもだいたい同じです。なんで素直にクラスにしてないのだろうとツッコムことは可能ですが、これも使っていると「ああ、そーゆーことなのね」としょうがなくはありますが納得します。多分最初の作者は「cppじゃなくてinoだよ」と言いたいんでしょうね。こういった「変なこと」があってもそれは統一されていますから、妙な混乱はありません。「うるさい技術者」だと、「なんだこれは」と言って直してしまって非互換のあるAPIが複数... みたいなことをやらかすと思うんですが、そんなことにはなっていません。

おそらくこれは、Arduinoが「マイコンのソフトウェア開発」というころから出発したのではなくて、「マイクロコントローラの制御」というところから出発したからでしょう。つまり、

わかりやすくてちゃんと動かせればそれでいい

ということです。「ソフトウェア工学的な正しさ」は犬に食わせてしまい、「ちゃんと制御するものが簡単に書けるでしょう?」ということを優先したのではないかと思います。ちなみに、ここで言う「コントローラ」とは、

こんな奴のことです。これについては、

PLC(1) - PLCとの出会い

にちょっと書いています。プログラムの書き方は大きく異なりますが、根底の思想はこういったものなのです。Arduinoは「シールド」でI/Oが増やせたりしますが、PLCも連結してI/Oを増やすようになっているものが多いです。ちなみに近頃はArduinoにもIEC-61131-3に対応した処理系があったりします。

「Arduino言語」は本質的にはC++と同じものであるにも関わらず、あまりC++臭いことをしないでC++でいい感じに隠蔽して便利にしたものを使うという感じになっているというのも、わかりやすくてちゃんと動くことを優先しているということなのだろうと思います。

もちろんそれで飽き足らない人はC++やCで書いてしまえば良いですしそれでも通ってしまいますから、そっちの方が慣れている人はそうすれば良いのです。そういった目線で見れば、「ちょっとクセがあるな」と思うことはありますが、わかりやすさは維持されていると思います。

実は私も何度か「ArduinoっぽいけどArduinoでないもの」を作ろうとしたことがあります。ArduinoのAPIそのものには好感が持てても、Arduino.hの中身がどうにも好きになれなかったのです。でも、書けば書くほど、完成度を上げようとすれば上げようとするほど、オレオレフレームワーク.hArduino.hに近付いてしまいました。それだけArduinoは良く出来ているのですね。仮に今から「Arduinoよりマシなもの」を作ろうとするなら、きっとArduinoの延長上にあるものになってしまうでしょう。

また実も蓋もない当たり前のことを言いますが、こういったところがどれだけ素晴しくなっていても、出来上がったソフトウェア(制御プログラム)のパフォーマンスやコードサイズは違いません。もちろんAPIの差異や粒度の違いで多少違ってしまうことはあるかも知れませんが、「どっちがどう」ということはありません。であれば、「わかりやすくてちゃんと動く」ことに勝るものはありません。

またこれに付随して「環境構築」も統一性があります。

マイコンのソフトウェア開発では、まず「Lチカ」をします。これは最低限のハードウェアでも動くということと共に、

開発環境が正しく構築されている

ということの確認でもあります。逆に言えば、マイコンの開発環境の構築には、これくらいのハードルがあったという意味でもあります。

実際、ESP32でもSTM32でも、使用に耐える開発環境を構築するのは結構厄介です。ESPは32になって随分マシになりましたが、ESP8266の頃はいろんな環境があって下手するとハマったりしていました。STM32もライブラリの流儀Makefileの流儀ファーム書き込みの流儀が複数あって、ちょっと変なことをしようとするとわけがわからなくなったりしていました。高々「Lチカ」結構高いハードルだったんですね。

その点Arduinoは簡単です。IDEを使うのであれば「ボードマネージャ」を動かすだけです。そうすれば、toolchainもライブラリも書き込みも全部出来てしまいます。そして、基本的には同じ操作感で扱うことができます。

コンポーネントが豊富にあって流通している

ささっとプログラムを開発したい時、コンポーネントが充実していると嬉しいですよね。

気合い入れて細かいことまで頑張りたい時、そこに気合いを入れることは良いことです。でも、「とりあえず動かしたい」ということは結構あります。PoCを作りたい時、ちょっとデモしたい時、「細かいことはどうでもいいんでちゃんと動かしたい」と思うことはよくあります。そういった時に既成のコンポーネントが使えれば、「とりあえず」の用は足せます。そして必要なら後でそこを何とかすればいいし、必要なければ「いずれね」ということにしてしまえばいい。

Arduinoにはそういった便利コンポーネントがたくさんあります。

液晶ディスプレイをつないだ時、SPIのコマンドレベルであれやこれややらなくても、素敵なグラフィックライブラリやそれを利用したUIライブラリがあります。

インターネットにつないでしまえば、NTPライブラリを使うだけで正確な時計を手に入れることができます。

NeoPixelなんてありがちですけどESP-IDFにライブラリはありませんでした。Arduinoには何種類かあります。

その辺で買って来たセンサーも、I2Cのコマンドレベルであれこれやらなくても、センサー値を得ることができます。BMP-280のデータ処理は結構面倒臭い数式ですが、Adafruitにライブラリが置いてあります。

個々のコンポーネントの品質や機能は微妙かも知れません。それでも、「とりあえず動く」ものであれば割と簡単に入手できます。足りないなと思えば、自分で追加してやればいいし、余裕があれば直せばいいのです。

情報源が多い

ググってみるとわかりますが、これは本当にnative SDKとは比較にならない程情報源は多いです。

もちろん前述のように、初心者の「やってみた」的エントリや勘違い思い込み、あるいは「やってみたら動いた」のような、直接的には役に立たない情報も少なくありません。とは言え、そういった質の低い情報であっても「事例」ということでは意味がありますね。

この情報の多さは入門のしやすさだけではなくて、互換性の高さによるものもあります。ありがちのペリフェラルであれば、マイコンそのものが異なっていてもAPIから見れば同じですから、ハードウェア固有の問題を除けば情報は流用できます。

同じことは自分の知識でも言えますね。違うマイコンを使う時でも以前使っていたマイコンの知識が流用できるわけですから、知的資産は増える一方です。

まとめ

Arduinoはしばしば「入門」として語られます。

もちろん「入門」として悪いものではありませんし、その側面も重要だろうと思います。

しかし、今や「そこそこちゃんとした開発」にも使えるものになっています。特に少量多品種、あるいは「早いがごっつぉ(ご馳走という意味です)」的な応用、さらには極端にシビアな条件下でない応用の場合、既に十分使えるものになっていると感じています。プロのエンジニアであっても「組み込みごっこ用おもちゃ」として見るのではなくて、「開発環境の選択肢の一つ」と捉えて良いように思います。特に最近増えて来た「変なマイコン」を試してみるには良い選択肢だと思います。

開発環境も(プロ目線でも)使いやすくなって来たので、より広く使われると良いなと思います。

特に最終的にオープンソースにしてしまうものであれば、他のものを使うメリットはなくなっていると思っても良いと思います。箱に入って出荷されてしまうものであっても、少量多品種なものではれば有効活用するべきでしょう。この辺もいわゆるOSSと同じです。

PS. ライセンスについて

私はほぼ気にしてなかったのですが、ライセンスの問題を心配されるかも知れないので追記しておきます。

Arduinoのコードのライセンスは、だいたい

  • ツール群(IDEやtoolchainなど)はGPL
  • ライブラリはLGPL

だと思っておけば良いです。特にライブラリに関してはコアライブラリがLGPLなので、「Arduino」を謳う限りはLGPLを継承していると考えて良いです。

もう少し厳密に言えば、ライブラリはLGPL 2.1CLIはGPL 3.0IDE 2.0はAGPL 3.0となっています。IDEがAGPLというのは面白いですね。

ただし、「Arduino」であっても「Arduino互換」とだけあった場合、もしかしたら元のコアライブラリから派生したものではなくて独自に開発されたものであるとか、ダウンロードして取って来たコードは異なるライセンスであるとかする可能性も0ではありません(そういったものがあるかどうかは知りません)。まぁこの辺は他の組み込み関係のライブラリでも考慮するべきことなので、「Arduinoだから」ということで殊更に考慮すべき事項が増えるわけではありません。配布物にGPLなものを含む必要がないので、Linuxを使う時よりは楽ですね。

調べていると「ブートローダのライセンス」に言及している人がいるのですが、これは「Arduinoというハードウェアとその互換品」の時に問題になることなので、「ArduinoというSDK」を使う時にはあまり気にする必要はないと思います。ESP32のArduinoとかは、「ブートローダ」はArduinoのものではありません。

native SDKであっても、「ネットにあるのはオープンソースだけど商用の面倒が嫌ならプロプラの契約でね」というものがあったりもしますし、組み込み関係のライセンスは正しく運用するのは結構面倒臭いことが多かったりしますので、「Arduinoはそうなんだ」という程度には理解しておいた方が良いでしょう。いくらコンポーネントが豊富にあると言っても、ライセンスの問題だけではなくてセキュリティ上の問題とか、考慮するべきことは沢山ありますからね。もっともこの辺は現代においては、

開発やメンテナンスと同等に工数を意識するべきこと

だと言って良いと思います。ことさらに「Arduinoだから」というものではありません。

最近のエントリー

会計システム「Hieronymus」の現状

OrangePi5にZabbixをインストールする

レビュー等の依頼について

オープンソースのノートアプリ「SiYuan」 - CasaOS AppStoreレビュー

お気に入りの色さがし1

創立記念日

現在の営業品目(2)

現在の営業品目(1)

SPDX License Listをデータ化した

Orange Pi5でC3TR-Adapterを試す

CasaOS上で会計システム「Hieronymus」を動かす

会計システム「Hieronymus」v1.0.0 リリースしました

CasaOSでファイル同期アプリSyncthingをセットアップする

第11回 Freshmeat

オープンソースノーコード「Activepieces」でワークフローを作る

RaspberryPiにパーソナルクラウドOS「CasaOS」を導入する

sequelize-cliでdb:migrateすると「SyntaxError: Unexpected token ':'」が出る

LED行燈の試作(2)

CMSの社内向けサービスのリニューアル

LED行燈の試作(1)