前回の記事では、様々なArduinoハードウェアをMacに接続する方法について説明しました。今回は、Arduinoを使ってプログラミングを始め、独自のプロジェクトを作成する方法をご紹介します。
はじめる
Arduinoをプログラムするには、arduino.ccウェブサイトからArduino IDE(統合開発環境)をダウンロードする必要があります。前回の記事でIDEのダウンロードとインストール方法について説明しましたが、ここでも改めてご説明します。
Mac で arduino.cc にアクセスし、「ソフトウェア」をクリックして、「ダウンロード オプション」セクションで、Intel または Apple Silicon の Mac バージョンのリンクをクリックします。
現在の開発版を試用する場合を除き、「Nightly Builds」セクションのリンクは不要です。Nightly Builds は不安定でバグが含まれている可能性があります 。
ダウンロード ページには、Arduino オンライン Web エディターへのリンクもあり、これを使用してプログラムを Arduino のクラウドに保存できます。
IDEをダウンロードしたら、Mac上のArduinoをIDEに接続して設定する方法については、前の記事を参照してください。IDEからArduinoにコードをアップロードする前に、接続が必要です。
基本
Arduinoをプログラムするには、基本的なプログラミングスキルがあれば十分です。ArduinoのC言語やPythonも使用できますが、以下の例ではC言語のみを使用します。
Arduinoプログラム(スケッチと呼ばれる)では、基本的にArduinoを特定のタスク(複数可)用にセットアップするコードを記述し、スケッチをArduinoデバイスにアップロードすると、Arduinoマイクロコントローラによって繰り返し呼び出される連続ループを実行します。このループは通常、センサーやユーザーからの入力を待機し、何らかの出力を表示するためにセンサーやデバイスに制御信号を送り返します。
ループ コードはインターネットに接続して対話することもできます。
IDEのライブラリマネージャーを使用して、様々なセンサーデバイスやシールドをサポートするサードパーティ製ライブラリをインストールすることもできます。ライブラリマネージャーにアクセスするには、スケッチウィンドウを作成するか開き、左側にある本のようなアイコンをクリックします。
ペインが表示され、上部で 2 つのポップアップ メニューのいずれかをクリックして、タイプとトピック別に利用可能なライブラリを参照できます。
「タイプ:」メニューから「更新可能」を選択して、インストールされているライブラリの更新を確認することもできます。
ライブラリマネージャーペインでは、公式ライブラリとサードパーティライブラリをダウンロードできます。ライブラリは、IDEに特定の機能やデバイスサポートを追加するコードバンドルです。
たとえば、特定のブランドの非汎用センサーを使用する場合は、まずそのライブラリをダウンロードしてインストールする必要があります。
ライブラリ マネージャー ウィンドウの上部にある [トピック] ポップアップ メニューをクリックすると、さまざまなカテゴリのライブラリを表示できます。
ほとんどのArduinoスケッチはシンプルで短く、Arduino IDE設定ウィンドウで指定された「スケッチブック」フォルダに保存されます。「スケッチブックの場所」の横にある参照ボタンをクリックすると、IDEがスケッチを保存する場所を変更できます。
スケッチのファイル拡張子は .ino で、「イノベーション」を意味します。
ここでテキストエディタとコンパイラの設定も変更できます。サポートされていないArduinoをお使いの場合は、ウィンドウの右下にある小さなアイコン(ドキュメントが積み重ねられたようなアイコン)をクリックして、ボードのサポートファイルまたはURLを追加できます。
追加のボード マネージャーの URL ウィンドウにある「非公式のボード サポート URL のリストについてはクリックしてください」というテキストをクリックすると、Arduino の GitHub でサポートされているさまざまなボードが表示されます。
Arduino IDE を初めて開くと、テキスト ウィンドウに簡単なプログラムの概要を示すサンプル スケッチが表示されます。
「ファイル」->「サンプル」サブメニュー項目の下には、豊富なコードサンプルが用意されています。サンプルはメニュー内で「組み込み」と「UNOサンプル」に分類されています。カスタムインストールされたライブラリからもサンプルが提供される場合があります。
最初のサンプルスケッチ
最初の例では、組み込みのBlinkサンプルを使用します。Blinkを開くには、「ファイル」->「例」->「0.1Basics」->「Blink」サブメニュー項目を選択してください。
数秒後、Blinkのサンプルを含む新しいエディタウィンドウが開きます。IDEのエディタウィンドウ上部にある接続ポップアップメニューから、Arduinoボードとポートが選択されていることを確認してください。
Blink は Arduino に内蔵された LED を点滅させるという機能を持っています。サンプルの説明は、エディターウィンドウ上部のコメント欄とオンラインで確認できます。
コードにおいて、コメントとは、プログラマーがコードの動作を説明するために残すメモのことです。コメントはコンパイル時には無視されます。
IDEエディタウィンドウはC言語スタイルのコメントを使用します。コンパイラは/*と*/で囲まれたコメントを無視します。単一行コメントは//で始まりますが、1行のみで記述する必要があります。//以降のコメントは無視されます。
エディターの左上隅にあるチェックマーク アイコンの付いた大きな[検証]ボタンをクリックすると、IDE はそのウィンドウ内のコード をコンパイルします。
コンパイル中は、エディターウィンドウの下部に黒い出力ペインが表示され、進行状況が表示されます。エラーがなければ、次のようなメッセージが表示されます。
"Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes. Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes."
あるいは似たようなもの。
エラーがある場合は赤いテキストで表示され、エラーがなくなるまでコードを修正する必要があります。一部のエラーは重大ではなく、スケッチはそのまま実行されますが、他のエラーはスケッチの実行を全く妨げる可能性があります。
出力ペインの右上隅にある小さなアイコンをクリックすると、出力メッセージを消去できます。エディターウィンドウの右下隅にある小さな四角いアイコンをクリックすると、出力ペイン全体を非表示にできます。
「検証」ボタンの横にある「アップロード」ボタン(大きな右矢印アイコン)をクリックすると、IDEはコンパイルされたバイナリプログラムを、指定したポートのArduinoにアップロードします。その後はArduinoマイクロコントローラが処理を引き継ぎ、Arduino上でコードを実行します。
アップロード中に、Arduino に RX (受信) LED が組み込まれている場合は、スケッチ データを受信すると LED が高速で点滅します。
何らかの理由でスケッチをアップロードできなかった場合は、出力ペインに説明とその理由が表示されます。
Cベースの言語について少し
C言語は1969年にベル研究所でブライアン・カーヒニガン、デニス・リッチー、ケン・トンプソンによって発明されました。コンパイルされたC言語は非常に高速で、ほとんどのTCP/IPネットワークスタックとオペレーティングシステムカーネルはC言語で書かれています。
CのISO規格もあります: ISO/IEC 9899:2018
C言語はオペレーティングシステムの言語です。1980年代後半から1990年代にかけての初期のMacアプリの中には、C言語またはその派生言語であるC++で書かれたものもありました。
Arduino IDE プログラミング言語は C のような構文に基づいています。
ほとんどの C 系言語では、すべてのコード行は「;」で終わります。セミコロンがないと、コードはコンパイルされず、エラーが発生します。
ほとんどの C ベース言語では、ヘッダーと呼ばれる定義済みコード テキスト ファイルも使用されます。ヘッダーは通常、「.h」ファイル拡張子を持ちます。
.hファイルは、関数へのアクセス方法を記述した定義済みのコードセット(プロトタイプと呼ばれる)と考えてください。各プロトタイプは、関数名、関数に渡されるパラメータ(括弧内)、そして関数終了時に返される戻り値の型を定義します。
Sketchコード内でライブラリや組み込み関数を呼び出す(アクセスする)場合、各関数の呼び出し方法は、.hファイルで定義されているプロトタイプと一致する必要があります。ライブラリも同様に動作します。
例えば、プロトタイプで関数が2つの入力パラメータ(括弧内)と特定の型の戻り値(関数名の前に記述)を取る必要があると指定されている場合、関数呼び出しも全く同じ方法で実行する必要があります。それ以外の場合は、コンパイル時にエラーが発生します。
ヘッダー ファイルには、「define」と呼ばれる C スタイルの構成要素も含めることができます。define は、数値、テキスト (C では文字列)、計算、その他の関数など、別のコード式としてラベルを作成します。
定義を作成するには、Cプリプロセッサの#defineディレクティブを使用します。例えば、次のようになります。
#define FALLING 2
このコードは、ラベル 'FALLING' を値 2 として定義します。コード内で FALLING を使用する箇所では、コンパイル時に数値 2 が置換されます。#define は非常に複雑になる可能性がありますが、コードを短くして読みやすくすることができます。
Arduino IDE は #define を使用して、I/O ピン番号、モードなどを定義します。
独自のヘッダーと #define を作成することもできます。
ヘッダーは他のファイル(他の.hファイル、またはスケッチ自体)にインクルードできます。インクルードされた各.hファイルの内容は、コンパイル時に、インクルード先のファイルの先頭に挿入されます。
別のファイルにヘッダーを挿入するには、C言語の#includeディレクティブを使用します。例えば、Arduino.hの先頭には次のような記述があります。
#include "binary.h"
これにより、コンパイル時に「binary.h」と呼ばれる別のヘッダー ファイルが Arduino.h の先頭にインクルードされます。
上記のスクリーンショットを見ると、サンプル スケッチに 2 つの .h ファイルが含まれていることがわかります。
EEPROM.h Ethernet.h
最初は戸惑うかもしれませんが、実はとても簡単です。関数のプロトタイプと#defineを.hファイルに記述して、他の多くのファイルで使用できるようにします。そして、それらを他のファイルに#includeすると、コンパイラがコンパイル時に指定された場所に挿入します。簡単です。
定義を個別のヘッダーに整理すると、コードの再利用が可能になります。
.h ファイルを定義として、Sketch ファイルをそれを使用するプログラムとして考えてください。
Apple の Swift や Microsoft の C# などの最新のプログラミング言語では、簡潔さを優先してヘッダー ファイルが廃止されています。
Blinkの例に戻る
Blink サンプルの setup() 関数には、次の 1 行のコードがあります。
pinMode(LED_BUILTIN, OUTPUT);
LED_BUILTINとOUTPUTはどちらもArduinoヘッダーで定義された#defineです。Arduinoのメインヘッダーファイルは、前述の通りArduino.hという名前です。
MacキーボードのCommandキーを押しながらエディタウィンドウ内の任意の#defineをダブルクリックすると、対応する.hファイル内の定義にジャンプできます。同じエディタウィンドウ内に新しいタブが開き、対応する.hファイルが表示されます。
LED_BUILTIN は pins_arduino.h で "13" として定義されています。
#define LED_BUILTIN 13
これは、Arduino のピン コネクタ (ヘッダーとも呼ばれます) のデジタル ピン 13 を示します。
しかし同時に、LED_BUILTIN はArduinoにArduino基板自体に内蔵されたLEDを使用するように指示します。ArduinoヘッダーのD13ピンにジャンパー線を接続し、それをブレッドボード上のLEDに接続すると、そのLEDも点滅します。
pinModeはArduinoの組み込み関数で、Arduinoの特定のI/Oピンの動作(入力または出力)を設定します。この例では、ArduinoにLED_BUILTIN(13)ピンを出力ピンとして使用するように指示しています。
Wiring_digital.h ヘッダー内の pinMode() のプロトタイプの戻り値の型は 'void' であるため、この関数は値を返しません。'void' は C 言語のデータ型で、戻り値として「何も返さない」という意味です。戻り値の型が 'void' であるすべての C 関数は何も返しません。
コンパイルされたBlinkスケッチをArduinoで実行すると、まずsetup()を実行してハードウェアのセットアップを行い、次にloop()を無限に繰り返し実行します。Blinkの例では、loop()は単にピンのオンとオフを1秒間隔で切り替えるだけです。
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000);
電気工学用語における「高」と「低」は、単に「オン」と「オフ」を意味します。
digitalWrite() は、指定されたデジタル U/O ピン (この場合は、Arduino ピン D13 または LED_BUILTIN に接続されているもの) をオンまたはオフにするだけの Arduino の組み込み関数です。
delay() は、指定された間隔が経過するまで、それ以上の処理を停止する遅延関数です。delay() は、ミリ秒単位の単一の時間値を取ります。値 '1000' は 1 秒を表します。
先に進み、Blink Sketch IDE ウィンドウの [ アップロード]ボタンをクリックします。
これで完了です。最初のスケッチをコンパイルして実行しました。すべてがうまくいけば、Arduinoの内蔵LEDが点滅するはずです。
ほとんどのシールドには、Arduino に内蔵されているものと同じ機能を果たす LED も内蔵されています。
ブレッドボードの例
Blinkの例の動作を確認したので、同じことをしてみましょう。ただし今回は、ブレッドボード上の外部LEDを同時に点滅させます。この例に必要なものは以下です。
- ブレッドボード
- ジャンパー線2本
- 3.3V LED 1個
- 1 220オームの抵抗器
まず、2 本のジャンパー ワイヤを、対応する Arduino ヘッダーの「D13」または「13」と「GND」の穴に差し込みます。
「D13」ワイヤのもう一方の端をブレッドボードの内部の 1 列目の任意の場所に差し込みます (外端の「+」および「-」電源レール以外の任意の位置)。
次に、LED の長い (+) 脚が、先ほど取り付けた「D13」ワイヤと 同じ水平列になるように、LED をブレッドボードに取り付けます。
LED を横向きにして、短い脚をブレッドボードの長い端に向かって約 3 穴離れた穴に挿入します。
次に、220Ωの抵抗器を、短いLEDの脚と同じ列に、基板の反対側の電源レールに向けて挿入します。基板の中央に抵抗器を配置すれば完璧です。
抵抗器のもう一方の端を、同じ方向に約 3 つ離れた別の穴に挿入します。
これで、「D13」ワイヤ、LED、抵抗器が、やや引き伸ばされた「Z」の形をしたパターンになっているはずです (下の写真を参照)。
ブレッドボードの反対側、電源レールの前の最後の穴、または最後から2番目の穴に、「GND」ジャンパー線のもう一方の端を差し込みます。最終的な組み立ては次のようになります。
ブレッドボード上のすべての穴の下には金属レールの格子があることを覚えておいてください。ブレッドボード上で部品をどの向きに取り付けても、部品間、Arduino、そしてジャンパー線で接続することで回路が完成します。
BlinkサンプルをArduinoにアップロード済みであれば、LEDが点滅し始めるはずです。ArdunioのLEDとブレッドボードのLEDは同時に点滅するはずです。もし点滅しない場合は、戻って全ての接続をもう一度確認してください。
LEDなどの一部の電子部品には極性があり、電流は一方向にしか正しく流れません。一方、ほとんどの抵抗器などの他の部品は無極性であり、電流はどちらの方向にも同じように流れます。
delay() 関数に渡すタイミング値を調整することで、LED の点滅速度を速めたり遅めたりすることができます。大きな値と小さな値を試してみて、何が起こるか見てみましょう。
スケッチに digitalWrite() および delay() ステートメントを追加することで、点滅パターンを変更できます。たとえば、LED をモールス信号のように点滅させることができます。
最後の例: 信号シミュレータ
Arduino の LED を点滅させる方法を説明したので、最後にもう少し複雑な例を使用します。サードパーティ製の UNO ブレークアウト ボードと外部信号センサー ボードを使用して、3 色の信号機をシミュレートします。
実際、このような信号センサーは数多く販売されており、eBayでは5ドル以下で購入できるシンプルなものも出回っています。PCBWayのプロジェクトページでは、Jakeが4方向のセンサーを販売しているものもあります。
あるいは、PCBWay でカウントダウン タイマー LCD を備えた一時的なものも見つかります。
この例では、最も単純な 3 つの光センサーを使用し、実際の信号機と同じように短い間隔で色を変化させます。
これらの信号機ボードには通常3つまたは4つのピンがあり、各色のLEDに1つずつ、そしてGNDに1つずつあります。コードはBlinkに似ていますが、1つを除くすべてのライトを消灯し、delay()で待機してから、そのライトを消灯し、次のライトを点灯するという順番で点灯します。
まず、信号機センサーを、Arduino UNO にインストールした汎用ブレイクアウト シールドに接続します。ブレイクアウト シールドは、アナログ ピンとデジタル ピン、GND ピン、Bluetooth、シリアル ケーブル コネクタのバンクを備えたシールドです。
信号機センサーにはR、G、Y、GNDの4つのピンがあります。デジタルピン9、10、11をそれぞれR、G、Yに接続し、4番目のピンであるGNDをシールドのGNDピンに接続します。
Arduino IDEを開いて、新しいスケッチを開始してください。まず、スケッチの先頭、setup()の上に必要な項目をいくつか定義します。
まず、1 秒が何ミリ秒であるかを定義して、delay() に渡す秒数を指定できるようにします。
#define kMillisecondsInSec 1000
次に、黄色のライトを何秒間点灯させるかを定義します。
#define kSecondsForYellow ( kMillisecondsInSec * 4 )
次に、Arduinoの赤、黄、緑の3つのピンをそれぞれ定義します。defineを使用する代わりに、それぞれのピンの値をグローバル変数(この場合はC言語で定義されているint型)に代入します。
int RED = 9; int YELLOW = 10; int GREEN = 11;
変数は、いつでも中身(値)を変更できる名前付きのコンテナと考えてください。変数には型があり、どのような値を保持できるかを指定します。グローバル変数は、プログラム内のどこからでもアクセスできます。
関数内で宣言された変数はローカル変数と呼ばれ、1つの関数内でのみ使用できます。これを変数スコープと呼びます。
次に、グローバル変数を定義し、それらに計算式を割り当てて、秒とミリ秒の計算、そして青、赤、黄色の信号の遅延値を秒単位で計算する方法を簡素化します。この場合、「unsigned long int」という変数型を使用します。これはint型に似ていますが、より大きな値を保持できます。
unsigned long int millisecondsInMinute = ( kMillisecondsInSec * 12 ); // # of milliseconds in 1 min. unsigned long int minutesForGreenAndRed = ( 1 * millisecondsInMinute ); // number of minutes to leave green, red lights on. unsigned long int yellowDelay = kSecondsForYellow; // Time to leave yellow light on. Yellow delay is shorter than red/green.
ここで、setup() で、上で定義したピンのピン モードを、赤、黄、緑ごとに 1 つずつ定義します。
void setup( void ) { pinMode( RED, OUTPUT ); pinMode( YELLOW, OUTPUT ); pinMode( GREEN, OUTPUT ); }
これは、Arduino に、これらの 3 つのピンを出力値 (この場合はオンまたはオフ) に使用することを伝えます。
loop() では、まず赤/黄色のライトをオフにし、緑のライトをオンにして、onDelay 秒待機します。
void loop( void ) { // Green - Start digitalWrite( RED, LOW ); digitalWrite( YELLOW, LOW ); digitalWrite( GREEN, HIGH ); delay( onDelay );
onDelay の後、緑のライトを消灯し、黄色のライトを点灯し、yellowDelay 秒間待機します。
digitalWrite( GREEN, LOW ); digitalWrite( YELLOW, HIGH ); delay( yellowDelay );
yellowDelay の後、黄色のライトを消灯し、赤色のライトを点灯し、onDelay 秒間待機します。
// Red digitalWrite( YELLOW, LOW ); digitalWrite( RED, HIGH ); delay( onDelay );
最後に、onDelay が経過したら、赤ライトをオフにして、シミュレーションをリセットします。
digitalWrite( RED, LOW ); }
ループが次に実行されると、同じシーケンスが繰り返され、青信号から始まります。このループは停止するまで永遠に実行されます。これで、動作する信号シミュレータが完成しました。
スケッチを Arduino にアップロードしたら、Arduino の DC バレル ジャックに外部電源を接続し、USB ケーブルを抜いても、シミュレーションは引き続き実行されます。
これは Arduino の利点の 1 つです。マイクロコントローラをプログラムすると、ホスト コンピュータから独立してプログラムを実行できるようになります。
Arduinos は、センサーとして動作したり、情報を表示したり、入力を待ったり、音を出したり、カメラを使用して他のデバイスに画像を送信したり、状態を監視したり、モーターを駆動したりなど、ほぼあらゆることを行うことができます。
Arduino の C のような言語を学ぶには、読む価値のある入門書がいくつかあります。
- Arduinoプログラミング:スケッチ入門
- Arduinoの基本
- ArduinoのためのC入門
- ArduinoのためのCを学ぶ
- Arduino テクニカル リファレンス
- Arduinoクックブック
- Arduinoをマスターする
これらの簡単な例から、Arduinoプログラミングを始めることができます。プログラミングスキルを磨き、自信がついてきたら、より大きな例に挑戦してみましょう。
今後の記事では、Arduino デバイス、シールド、I2C や SPI などのバスのプログラミングと、複雑なデバイス環境の作成について説明します。