記事内に広告が含まれています

電子工作で便利に使えるArduino言語の基本構成

Arduino

はじめに

私は電子工作とは、なんらかの情報を取り込み加工した結果を電子回路を用いて目に見える形で”表現”する手段だと思っています。”表現”とは、役に立つもの、面白いもの、芸術的なものなど何でもかまいません。

”表現”を具現化するために、近頃の電子工作ではインプットとアウトプットの間にはマイコンが使用されることが多く、マイコンを中心に電子部品を周辺回路として接続する設計が多くなされています。

使用する電子部品としては、我々を取り巻く環境を計測する場合、例えば温度計測するためには温度センサーであったり、ある物体までの距離を計測するためには測距センサーであったりします。また、物体を動かす場合であればモーターなどのアクチュエータをマイコンに接続します。

マイコンに接続した電子部品を制御するには少なからずプログラミングのスキルが必要になるのですが、私は電子工作でよく使用しているArduino言語について、まだまだ理解できていない事が多いですが、これまで学習してきたことを復習の意味で何回かに分けて整理してみようと思います。

なぜArduinoなのか

電子工作界隈ではいくつかのプログラミング言語が使われますが、広く一般的に利用されているArudinoでは、センサーやアクチュエータなどの電子部品を比較的簡単に制御する事ができるような環境が整っているためこれを利用しない手はありません。

電子部品の製造元からはユーザーが電子部品を容易に使用できるように、あらかじめArduinoに対応したライブラリーと呼ばれる電子部品を簡単に取り扱うための仕組み、および使い方の一例を示したサンプルプログラムが提供されていることが多く、自身で作成するプログラミングに取り込んで活用することが出来ます。

またインターネットには沢山の電子工作界隈の先人たちがおられ、その方々の偉大なるお知恵を拝借する事もできます。

さらに、多くの優良な書籍やマニュアル本も発売されているので、理解度を確認したり系統だった学習が可能です。一例として以下3つの書籍をあげておきます。

こちらの書籍は、LCDや温度センサーをI2CやSPIといったマイコンとの通信規格を使用した具体例が記載されていますので電子工作をすぐにでも試したい場合に参考になるのではないでしょうか。

次の書籍はArduino IDEのインストールから基本的な電子部品の使い方までの説明が記述されていることに加えて、公式リファレンス(日本語版)が付録として付いていますので手元にあると便利です。また、洋書の翻訳なので文脈やイラストが日本の書籍と違った独特の雰囲気で楽しめますね。

特にESP32マイコンを使用してArduino言語のプログラミングを行ってみたい場合は、次の参考書が電子工作とプログラミングを絡めて紹介しているのでお勧めします。

兎にも角にも、電子工作を趣味として楽しめばよく、格好良いプログラミングテクニックはさて置き、基本的なところを理解しつつ、読みやすいプログラムの記述になるように注意しながら楽しく電子工作をまず始めてみることをおすすめします。色々と電子工作を進めていくうちに疑問に思ったことやプログラム言語の応用的なところは必要に迫られて少しずつ理解できるようになるでしょう。

Arduinoプログラムの基本構成

Arduinoにおけるプログラム(コード)は”スケッチ(sketch)”と呼ばれており、C言語、C++言語をベースに簡略化し初心者でも比較的扱いやすいようにした言語で、主に以下の要素で構成されます。

基本構造

Arduinoスケッチは、2つの主要な関数を中心に構築されます。

  • setup() : プログラム開始時に1回だけ実行される初期設定用の関数。
  • loop() : プログラムが繰り返し実行されるメイン処理用の関数。

この2つの関数は必ず必要なもので、仮に記述するコードが無くても省略する事はできません。

記述は次の通りになります。

void setup() {
// 初期化コード
}
void loop() {
// 繰り返し実行されるコード
}

それぞれの関数の中には、次のような役割を記述します。
setup()
 ハードウェアの初期設定を記述することが多いです。

 ・ピンのモード設定「例: pinMode(13, OUTPUT);」
 ・シリアル通信の開始「例:Serial.begin(9600);」
 ・センサーやモジュールの初期化コード

loop()
 電子回路に繰り返し実行させる動作を記述します。

 ・センサー値の読み取りとディスプレイへの表示およびデータ保存
 ・アクチュエータ(モーターやLED)の制御
 ・データ処理や通信

なお、これら2つの関数にコードを記述する必要がない場合は、
setup() {}

loop () {}
のように味気ない記述で不安になるかもしれませんが問題なく、実際にSetup()関数のみのプログラムも存在します。また、上記コード例で使用している“//”(2つのスラッシュ)記号は、この記号から右側はコメントを意味し、プログラムには影響しませんので、付箋代わりにメモ書きするなどして、後日プログラムを見返すときの備忘録として活用できます。

その他の構成要素

上述した2つの必須の関数以外に、Arduinoプログラムでは多くの場合において次にあげるような要素が追加されます。

グローバル変数と定数

プログラム全体で使用する変数(グローバル変数と言う)や定数を、setup()loop()の外で定義します。

#define ledPin = 13 // LEDピン番号の定義
const float PI = 3.14; // 定数

setup(){
・・・
・・・
}

グローバル変数は、setup()やloop()およびそれ以外に作成した全ての関数で使える変数となります。対してsetup()の中や、loop()の中、およびそれ以外のそれぞれの関数の中で宣言した変数はローカル変数と呼ばれ、それぞれの関数の中でのみ使用できることになります。
実際のプログラムでの変数の扱いはもう少し複雑になっていて、変数のスコープの理解が重要であり、ある関数の中でも、さらに変数が適用される範囲が限定されていることになります。(上記参考書等で学習しましょう)

定数は、Arduino言語で事前に定義された表現であって、プログラムの可読性を上げるために利用されています。
上記の例であれば、”13”という定数に”ledPin” という名前を定義し、”3.14”という定数に”PI”という名前を定義してます。定数を定義する記述には、ほとんどの場合、#defineまたはconstを使用しますが、それぞれに特徴があります。なお、Arduinoでは、定数を定義する際には、constの使用を推奨しています。

#define

  • #defineで定義された定数は、コンパイル時に定義した値へ置きかえられチップ上のメモリ(RAM)を消費しない
  • 型がないため、デバッグが難しく、意図しない副作用を引き起こす可能性あり

const

  • 型付きの変数として使え、コンパイル時に型チェックが行われるため安全性が高い
  • 変数を読み取り専用にし、constで定義した変数に値を代入しようとするとコンパイルエラーになる
  • constを付けた変数はスコープのルールに従うため#defineよりもconstを使用するほうが良いとされている

Arduinoでは、文末に「;」セミコロンが必ず必要です。セミコロンが無いとコンパイルは通りません。慣れないうちはセミコロンを忘れがちですので注意しましょう。
#defineの「#」も忘れないようにするとともに、#Defindeでは文末の「;」が不要なことにも注意しましょう。

ライブラリのインクルード

・ライブラリとは、Arduinoユーザーが開発したプログラム(型、マクロ、関数を集めたもの)で、自分のプログラムに組み込んで使用することができる便利な拡張機能です。Arduino IDEに付属している標準ライブラリに加えて、自分でライブラリを作成して使用したり、世の中の開発者が公開しているライブラリを使用することも可能です。もちろん、自分が作成したライブラリを皆に公開することも可能です。

ライブラリのおかげで、プログラミングを簡略化する事ができ、様々な電子部品を簡単に扱うことができる一方で、ライブラリは(解析しない限り)ブラックボックスの為、プログラムに動作不具合があった場合のバグフィックスに時間を要したり、ライブラリをインクルードする順序が適切でないとコンパイル出来なかったりなどの弊害が発生することもあります。

ライブラリを使用する場合、次のようにファイル冒頭にインクルードを記述します。

#include <Servo.h>; // サーボモーターライブラリ
Servo myServo; // サーボオブジェクト

・ライブラリをインクルードする記述として、#include <ライブラリ名>#include "ライブラリ名"の2通りがあるのですが、その違いはヘッダーファイルの検索場所に関係します。

#include <>
  • 用途: 標準ライブラリやシステムのヘッダーファイルをインクルードする際に使用。
  • 検索場所: コンパイラが定義済みの標準ディレクトリ(例: Arduinoのライブラリフォルダやシステムのインクルードパス)からヘッダーファイルを探す。
  • : #include <Arduino.h>(Arduinoのコアライブラリ)や#include <Wire.h>(I2Cライブラリ)など。
  • 特徴: 外部ライブラリや公式ライブラリを参照する場合に一般的。
#include “”
  • 用途: ユーザーが作成したヘッダーファイルや、同じプロジェクトディレクトリ内にあるファイルをインクルードする際に使用。
  • 検索場所: まず現在のプロジェクトフォルダ(スケッチと同じディレクトリ)を検索し、見つからない場合は標準ディレクトリも探す。
  • : #include "myHeader.h"(同じフォルダにある myHeader.h をインクルード)。
  • 特徴: ローカルファイルやカスタムライブラリを参照する場合に使用。
主な違い
  • 優先検索場所:< >」は標準ディレクトリを優先、「””現在のプロジェクトフォルダを優先。
  • 用途の違い: 「< >」はシステム/ライブラリ用、「””はユーザー定義ファイル用。
  • エラー回避: 間違った形式を使うとファイルが見つからないエラーが発生する可能性がある(例: ローカルファイルを「< >」で指定)
Arduinoでの注意点
  • Arduino IDEでは、ライブラリフォルダ(`libraries/`)にあるヘッダーファイルは通常「< >」で指定。スケッチと同じフォルダにある`.h`ファイルは「””で指定
  • 間違った形式を使っても、Arduino IDEが自動的に補正する場合があるが、明確に使い分けるのが良し。
#include <SPI.h> // 標準ライブラリ(SPI通信用) 
#include "myConfig.h" // 同じフォルダにある自作ヘッダーファイル

カスタム関数

  • 再利用可能な処理を独自の関数として定義可能です。

例えば、GPIO「pin」番号の端子を「delayTime」の間隔でLEDを点滅させる関数はこのようになります。「pin」番号と「delayTime」はこの関数の呼び出し元から引数として受けとります。

void blinkLED(int pin, int delayTime) {
digitalWrite(pin, HIGH);
delay(delayTime);
digitalWrite(pin, LOW);
delay(delayTime);
}

コメント

  • コードの説明やメモを記述しておきます。プログラミングを行っている間は記述しているコードの内容をよく理解していますが、数日後、時間が経ってからプログラムを見返した場合に、何のために記述していたのか内容を忘れていることも多く役立ちます。
// 1行コメントは「//」を使用します

/* 複数行にわたる
コメントは「/*」と「*/」で挟んで記載します */

Arduinoでのプログラムの流れ

記述したプログラム全体の一連の動作は次の通りです。これまで説明した通りですが、Arduinoでは、マイコンでセンサーやアクチュエータを繰り返しコントロールすることが基本であるため一度きりの動作で終了することはあまり無く、loop()関数でマイコンに対して命令が無限に繰り返し実行される点が特徴と言えます。

  • コンパイル時にグローバル変数やライブラリが処理。
  • setup()が1回実行され、初期化が完了。
  • loop()が無限ループで実行され、プログラムが継続的に動作。

Arduinoでの注意点

色々な注意点があると思いますが、電子工作では特に次の3点を上げておきます。

  • データ型: Arduinoはメモリが限られているため、適切なデータ型(int, byte, floatなど)を選択。
  • 時間管理: delay()は処理を停止するため、非同期処理にはmillis()を使用。
  • デバッグ: Serial.print()Serial.println()で変数や状態を確認。

※ 限られたメモリを効率よく使用することが望まれるため最適なデータ型を選択します。

※ millis()関数は、Arduinoプログラムが開始されてからの経過時間をミリ秒(1/1000秒)単位で返す関数で、プログラムの起動から時間が加算されていきます。delay()関数はその時間中すべての処理を停止しますが、millis()を使うことで、現在時刻と前回記録した時刻の差分を計測して一定の間隔で処理を実行することができ、時間の計測中に他の処理を並行して実行することが可能です。

※ プログラミングにおいてデバックは必要不可欠です。プログラムが想定した動作をしているかどうか変数をSerial.print()やSerial.println()を使用してシリアルモニタに表示して確認します。

サンプルスケッチ

最後にArduinoプログラムの全体像をイメージするために、Lチカと呼ばれるLEDを点滅させる基本プログラム例をご紹介します。

// 動作保証無しサンプルプログラムです

#include <Arduino.h> // ライブラリをインクルード

int ledPin = 13; // 内蔵LEDピン

void setup() {
pinMode(ledPin, OUTPUT); // ピンを出力に設定
}

void loop() {
digitalWrite(ledPin, HIGH); // LEDオン
delay(1000); // 1秒待機
digitalWrite(ledPin, LOW); // LEDオフ
delay(1000); // 1秒待機
}

まとめ

Arduinoプログラムは、setup()loop()と言う2つの関数を基盤に、変数、ライブラリ、カスタム関数を組み合わせて構成されます。シンプルな構造ながら、センサーやアクチュエータの制御を柔軟に実現可能です。メモリ制約や非同期処理に留意しながら目的に応じたコードを記述します。

コメント

タイトルとURLをコピーしました