Arduinoの言語は何?C言語・C++との違いを現役組み込みエンジニアが解説
Arduinoで使用可能な言語や、Arduinoはどうやってプログラムを書きこむのだろう?などといった疑問を持つ方も多いのではないでしょうか?
この記事では、Arduinoで書いているコードが何の言語なのかを、実際のソースコードを確認しながら解説します。
- Arduinoで書いているのはC++。専用の別言語ではない
- Arduinoでのプログラムコードの書き方について
- Arduinoの学習はなにに役立つか?
目次
Arduinoの言語はC++|「Arduino言語」という別の言語ではない
そのため「Arduino専用の言語を勉強する」ということはしなくても大丈夫です。勉強するのはC++と、そのもとになっているC言語のみを勉強しておけば大丈夫です。
公式記載の「Arduino programming language」について
Arduino公式のリファレンス(Language Reference)では、冒頭でこう説明されています。
Arduino programming language can be divided in three main parts: functions, values (variables and constants), and structure.
出典:Arduino Docs「Language Reference」(docs.arduino.cc/language-reference/)
訳すと「Arduinoのプログラミング言語は、関数・値(変数と定数)・構造の3つに大きく分けられる」となります。実際にページを開くと、この3つが見出しになっていて、Functions の下に Digital I/O・Analog I/O・Time・Communication といった分類が並び、そこに digitalWrite() や delay() が載っています。この分類のまま日本語で引けるようにしたものがArduino日本語リファレンス|UNO R3/R4で使用する関数の解説で、各関数が1回あたり何マイクロ秒かかるかを実機で測って併記しています。
注目したいのは、このページにC++という単語が一度も出てこないことです。使える部品だけが並んでいるので、読んだ側が独立した言語だと受け取るのは無理もありません。
実際には、この呼び名が指しているのはC++に、電子部品を扱うための関数をひとまとめに足したものです。
足されているのは、たとえばこういう関数です。
- ピンの入出力に使う
pinMode()やdigitalWrite()、digitalRead() - アナログの読み書きに使う
analogRead()とanalogWrite() - 時間を扱う
delay()とmillis() - パソコンとの通信に使う
Serial
これらはC++の標準機能ではなく、Arduinoが別途用意したライブラリ関数です。内容はC++で書かれているのみです。
Arduinoのプログラムは4つの層でできている
Arduinoプログラムは以下4つの階層構造で作られています。
コードを書く場所は「.ino」の中でコードを直接書くことができます。
「.ino」でArduinoのライブラリ関数などすべてを参照できる作りとなっているので別途「.c」「.h」のファイルを作成する必要はありません。
ここから下はArduinoが用意している
ティール=あなたが書く範囲。グレーの3つは、書かなくても最初から動く。
初心者向けと言われる理由は、この積み上がりのうち一番上だけ書けば動くようにしてあることです。下の3つは、知らなくてもコードを書いてArduinoを操作できます。
Arduinoのコードにmain()が無いのはなぜか
main()はArduino側に用意されていて、IDEから見えないだけです。C言語やC++を少しでも勉強したことがあると、Arduinoのスケッチには見慣れない点があります。main()がありません。C++やC言語のプログラムはmain()から始まる決まりなので、ここに違和感を感じる人も多いと思います。
setup()とloop()を呼んでいるmain()の中身
そのmain()は、Arduinoをインストールすると一緒に入ってきます。実物を見てみます。
int main(void)
{
init();
initVariant();
setup();
for (;;) {
loop();
if (serialEventRun) {
serialEventRun();
}
}
return 0;
}
Arduino AVR Core の
cores/arduino/main.cpp(LGPL)より引用。#if defined(USBCON) の分岐など、話に関係しない行は省いています。手元のファイルは、Windowsなら次の場所にあります((ユーザー名) はご自身のものに読み替えてください)。
- Arduino IDE:
C:\Users\(ユーザー名)\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\main.cpp(1.8.6はボードパッケージのバージョンなので、入れた時期で変わります) - PlatformIO:
C:\Users\(ユーザー名)\.platformio\packages\framework-arduino-avr\cores\arduino\main.cpp
読むとそのままです。init()でマイコンの初期設定をして、setup()を1回呼び、あとはfor (;;)の中でloop()を延々と呼び続けているだけです。
「loop()に書いた処理が繰り返される」という説明は比喩ではなく、本当に無限ループの中から呼ばれているということでした。
Arduinoは
main()が無いのではなく、main()を書かせない作りになっています。初心者がつまずきやすい「プログラムの入口」を、あらかじめ固定しているのみであり、実際にはC言語のルールに則りコードを書いている。Arduinoを始める前に、C言語を勉強しないとダメなのか?
ただし「まったく要らない」わけでもないので、どこまで要るのかの線を引いておきます。
どこまで知っていれば動かせるか
なぜ基本構文だけで足りるのか。Arduinoの基板と合わせて説明します。
Arduinoの基板のふちには、金属の端子がずらりと並んでいます。これがピンで、マイコンから外に電気を出したり、外から電圧を読んだりする出入り口です。1本ずつに番号がふってあり、13番ピン、7番ピンというように番号で指定します。
そしてArduinoには、「何番ピンをどうするか」を指定するだけの関数があらかじめ用意されています。digitalWrite(13, HIGH)と書けば、13番ピンから電圧が出ます。そこにLEDをつないでおけば、LEDが光ります。

マイコン本体には、ピンの状態を決めるためのスイッチのような設定項目(レジスタ)があり、本来はそこを直接書き換える必要があります。その手続きをまとめて肩代わりしてくれるのが、Arduinoのライブラリ関数です。そのため裏側を知らなくても、番号を指定するだけで動かせます。
先に動かして、詰まったところで都度調べていく方が早いと考えています。
ポインタを理解しないとダメか?
Arduinoで電子工作をしたいだけなら、ポインタは要りません。ここまで見てきたとおり、ピンの操作は digitalWrite() のような関数が用意されていて、番号を指定するだけで動きます。センサーもモーターもライブラリが揃っているので、ポインタを知らないまま作品を完成させられます。
一方、組み込みエンジニアを目指すなら避けて通れません。理由は、マイコンの機能を決めているレジスタが、メモリ上の決まった番地(アドレス)に割り当てられているからです。たとえば「0x40000010番地がスイッチの状態を表す」といった対応がハードウェア側で決まっていて、そこを直接読み書きしないと機能を制御できません。
C言語でこれを書くと、次の形になります。番地を数値で指定し、それをポインタとして扱い、* で中身を読み書きします。
unsigned int *reg = (unsigned int*)0x40000010;
while (*reg == 0) {
/* スイッチが押されるのを待つ */
}
つまり組み込みの世界では、ポインタは「便利な機能」ではなく、ハードウェアを触るための唯一の入口です。Arduinoのライブラリは、この手続きを関数の中に隠してくれているだけで、無くなったわけではありません。
目的別|Arduinoを触るにあたり必要な知識のまとめ
Arduinoはプログラムと電子回路の両方を扱うので、必要な知識も言語だけではありません。目的別に整理します。
| 目的 | 身につける知識 | ポインタ・レジスタ |
|---|---|---|
| Arduinoで電子工作をしたい LED・センサー・モーターを動かす |
・C言語の基本構文(変数・分岐・ループ) ・電子回路の基礎(電流・電圧・抵抗、オームの法則) ・デジタルとアナログの違い ・部品の仕様の読み方 |
不要 ライブラリの関数で動かせる |
| 組み込みエンジニアレベルのC言語を身につけたい | ・上に加えてポインタ ・データシートの読み方(ピンとレジスタの対応) |
必要 関数を使わず自分で操作するのが、いちばん学習になる |
見落としやすいのが電子回路のほうです。LEDを1個光らせるだけでも、電流を抑える抵抗を選ぶのにオームの法則を使います。プログラムが正しくても、配線や部品の選び方を間違えると動きません。
特にポインタはレジスタ操作の必須知識です。ただしArduinoは公式ライブラリがレジスタ操作を関数化してくれているので、レジスタを触らず、マイコンを制御できます。なのでポインタを理解せずともLチカや簡単なマイコン制御は可能となっています。
組み込みエンジニアレベルのC言語を身につけたい場合は、そのための練習問題を用意しています。次の順に進めてください。
- C言語 基礎ドリル(8テーマまとめ)で、変数・分岐・ループから順に固める
- C言語 ポインタの練習問題7問で、番地を指して読み書きする感覚をつかむ
- Arduino 基礎ドリル|レジスタから学ぶ組み込みマイコン入門で、実際にレジスタを操作する
Arduinoの学習は何に役立つか
実際に作られているものには、こんな例があります。
- 土の水分を測って自動で水をやる植物育成デバイス
- 赤外線でエアコンを操作するリモコン
- 超音波で距離を測る装置
- モーターを制御するラジコンカーやロボット
さらに、表の2行目にあるレジスタを自分で操作するところまで進むと、もうひとつ得られるものがあります。
Arduinoでレジスタ操作をやったことが、実務に入ってから一番役立ちました。ただし役立ったのは操作そのものより、「ポインタがなぜ必要なのか」を理解できたことです。本を読んでポインタの文法を覚えるのと、「この番地を指して書き込まないとピンが動かない」という場面に自分で当たるのとでは、納得の仕方が違いました。
入門書のポインタは「変数のアドレスを入れる箱」と説明されることが多く、文法としては正しいのですが、なぜそんなものが要るのかまでは分かりません。レジスタを触ると、番地を指す以外に方法がない場面が出てくるので、そこがつながります。
Arduinoでレジスタを直接読み書きしてみたい場合は、Arduino Lチカのやり方|digitalWriteからレジスタ操作まで練習問題9問で、同じLチカをdigitalWrite()とレジスタの両方で書く練習ができます。
まとめ
Arduinoで書いているのはC++です。「Arduino言語」という別の言語があるわけではなく、C++に電子部品を扱うための関数を足したものを、公式がそう呼んでいるだけでした。
main()が見当たらないのも、無いのではなくArduino側が用意していて書かせない作りのためです。実物のmain.cppを開けば、setup()を1回呼んでfor (;;)でloop()を回しているだけだと分かります。
勉強の順番としては、レジスタを触らないうちは変数・分岐・ループで足ります。ポインタが必要になるのはレジスタを直接読み書きするときで、そこが境目です。
もうひとつ忘れやすいのが電子回路のほう。Arduinoはプログラムと回路の両方を扱うので、抵抗の選び方やデジタルとアナログの違いも一緒に必要になります。裏を返せば、その2つを同時に覚えられるということです。まずは動かしてみて、詰まったところで戻ってください。