第四項 Arduino開発基礎
電子工作創作表現(2019/5/17)
スライドPDF
Messengerグループを作ります
比嘉さんの講義と同様に連絡用グループ作りました
https://m.me/join/AbZhVqUurvKr9_8u
休講のお知らせなど講義の連絡用に、FacebookのMessengerグループを作りました。
以下のURLから参加できますので、申請をお願いします。
Facebookアカウントを持っていない人でも、Messengerだけのアカウントを作ることができるので、アプリをダウンロードしてみてください。
今日の内容
- Arduinoプログラミング
- TinkerCADで開発のシミュレーション
TinkerCADで開発
- 色々試したい時配線が大変
- 簡単な部品を使ったシミュレーションができる
Arduinoの現物に色々配線をしていこうとするとそっちに時間が取られたり、回路に問題があるのかプログラムに問題があるのか分かりづらい事が多いです。
なので、ここから先Arduinoの開発に関する演習はこのTinkerCADを使ってやっていこうと思うので、ユーザー登録をしてみてください。
Arduino IDEができること
- Arduioファミリ用のプログラムを生成する
- シリアルモニタ/プロッタなどデバッグ機能
- ライブラリ(特別な機能を搭載するためのプログラム)の管理
前々回から触っているArduinoIDEについて少しおさらいです。
ArduinoIDEはArduinoの開発に関わる色々な機能をひとつにまとめたソフトで、プログラムの作成と書き込みをしたり、シリアルモニタやプロッタで情報を見たりする機能がついています。
加えて、特殊な機能を使えるようになる「ライブラリ」と呼ばれるものの管理ができたりもします。
開発手順のイメージ
1.Arduino IDEでコーディング
2.コードをコンパイルしてバイナリに変換
3.変換したバイナリをArduinoマイコンに転送
開発のイメージはこんな感じで、私たちが英語に近い文章で書いたプログラムをArduinoのマイコンが理解できるデータに変換(コンパイル)し、USBを経由して転送しています。
開発言語について
- ArduinoはC++という言語をベースにしている
- 基本的な拡張子は.inoだが、.cppや.hも使える
コーディングの際記述する文のルールをまとめて「プログラミング言語」と呼びます。今は非常に多くの言語が存在していますが、ArduinoはC++という言語をベースに作られています。そして保存したファイルを「スケッチ」と呼び(この辺りはProcessingの系譜を継いでいます)拡張子は.inoを使いますが、C++がベースになっていて.cppや.hも使うことができます。
補足:C++ベースとは?
- .inoはArduino IDEで変換されたあと、avr-g++に通される
- .cpp/.cで記述されたものはavrのコンパイラに直接流し込まれる
C++ベースとはどういうことなのかという点ですが、コンパイル段階で色々なことをしています。.inoスケッチはArduinoIDEで改変されてからAVRコンパイラへと流され、main関数を含むmain.cppは別で用意されているものが一緒にコンパイルされます。
.cpp/.cで定義されたファイルはダイレクトにAVRコンパイラへ通されるので、Arduinoの改変をされたくない場合はこの拡張子を使うということになります。
参考:https://garretlab.web.fc2.com/arduino/introduction/compile_process/index.html
前回のプログラムをおさらい
https://www.tinkercad.com/things/4danaaOlAin
ではどのようなルールに基づいてプログラムを書いて行ったら良いのか、前回書いたコードを元にとっかかりとなる基本的な構造を説明していきます。
void setup()
{
pinMode(9, OUTPUT);
}
void loop()
{
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(9, LOW);
delay(1000);
}
setupとloop
- Processingから来ている基本構造
- 1回のsetupと、半永久的に繰り返されるloop
プログラムというのは、下に向かって順番にコードが解釈・実行されていくものですが、プログラムの内容によってはその読んでいくラインがあちこちにジャンプします。
Arduinoにおいては、setupとloopという二つの「関数」と呼ばれるまとまりがベースとなっています。
setupは起動して一番初めに一度だけ処理される関数で、ピンの設定のような初めに決めておきたい事を書いていくブロックで、すぐ下の大かっこ{}で囲まれた部分がsetupの中身ということになります。
同様にloopの中も大かっこで囲まれた部分ですが、ここに書かれたことは一番下まで実行されるとまた先頭に戻って、電源が落とされない限り半永久的に実行され続けます。このsetupとloopの中にプログラムを書いていくのがArduinoの基本で、これはProcessingやOpenFrameworksのようなメディアアート系の開発環境によくある構造です。古くはProcessingの前身であるDesign by numbersから来ています。
関数と変数
- 小さなプログラムのまとまりが「関数」
- 関数名(引数){ 内容 }というフォーマットで定義される
setup・loopの事を関数と呼びますが、この中に記述する最も基本的な要素が「関数」と「変数」です。
前回出たdigitalWriteやdelayも関数の一つで、Arduinoが実現できる命令が色々な関数として定義されています。
関数の情報は「リファレンス」を見る
- どんな関数があるかリファレンスで知ることができる
- 使い方を知るにはサンプルも役立つ
英語リファレンス:https://www.arduino.cc/reference/en/
日本語リファレンス:https://www.arduino.cc/reference/jp/
非公式だが充実しているリファレンスも:http://www.musashinodenpa.com/arduino/ref/
つまりArduinoで何かやろうとすると、どんな関数があるかを知らなくてはならないわけですが、公式のWebなどに細かな情報がまとめられています。こういったプログラミング言語などに定義された機能をまとめた情報のことをよく「リファレンス」と言います。
Arduinoの場合は公式で出されている英語と日本語のリファレンスがありますが、日本語は随時翻訳しているようでまだ情報が歯抜けになっているので(2019/05/17現在)英語のリファレンスを読むか、非公式のリファレンスなどを見るのが良いでしょう。
前回までに使った関数
pinMode(pin, mode)
digitalWrite(pin, value)
delay(ms)
実際に、前回までに使った関数をリファレンスで見てみましょう。
変数
- 関数と同様に重要な「変数」
- 中に数値や文字を保存しておいて、色々な計算ができる
関数と同じくらい重要な要素に変数があります。変数はデータを入れておく箱のようなイメージです。
入力したデータを一時的に保存しておくことができるので、複雑な計算や複数の項目に同じパラメータを使いたい時などに有用です。
数学と少し違う「演算子」
" + - * / "という数学の記法とは少し異なる演算子を用いる
四則演算のほかにも%(余剰) ^(累乗)やビット演算子のような特殊な演算子も
プログラムに使うのは基本的に半角英数字なので、×や÷のような記号が無く、通常の四則演算しとは少し異なる記号を使って計算を表現します。Arduinoで用いる演算子はC++に準拠していて、余りや累乗のような演算子も使うことができます。
また補足ですが、パソコンと違ってメモリや処理速度に限りがあるため、大きなプログラムになるとデータの節約が必要になります。そういった際には2進数で保持されている数字を直接操作する「ビット演算」が役に立つので、より高度な制御をやりたいと思っている人は覚えておくと良いでしょう。
演習
梅:LEDが赤・緑・青と1秒ずつ順番に点灯していって、同時に消えるのを繰り返す
竹:電位差計のメモリを操作すると、点滅する速度が変化
松:全消灯~全点灯までの8通りの組み合わせを、int型の変数pattern1つで表現する
最後に、簡単な演習を用意したので梅から順にチャレンジしてみてください。
演習の正解例と解説
以下演習の正解例と解説です。あくまで正解例であり、書いてある要件を実現する方法はほかにも色々な書き方があると思います。
梅編
お題:LEDが赤・緑・青と1秒ずつ順番に点灯していって、同時に消えるのを繰り返す
delayで時間を区切りながら、digitalWriteで光らせたいところ、消したいところを記述していきます。
最後は同時に消えてほしいので、delayを挟まず三つのdigitalWriteを続けて書けばほぼ(人には知覚できない速度で)同時に消灯されます。
void setup()
{
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop()
{
delay(1000);
digitalWrite(9, HIGH);
delay(1000);
digitalWrite(10, HIGH);
delay(1000);
digitalWrite(11, HIGH);
delay(1000);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
竹編
お題:電位差計のメモリを操作すると、点滅する速度が変化
delayの値に変数を使ってみます。
analogRead(0) + 100という値を入れることで、点滅する感覚が100ミリ秒~1123ミリ秒の間で推移します。
秒数指定が中途半端で気持ち悪いと思ったら、map関数を組み合わせると簡単に範囲を変えることができます。リファレンスで調べてみましょう。
int interval;
void setup()
{
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop()
{
interval = analogRead(0) + 100;
delay(interval);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
delay(interval);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}
松編
お題:全消灯~全点灯までの8通りの組み合わせを、int型の変数pattern1つで表現する
複数のフラグを1バイトの変数にまとめておく手法は、マイコンなどPCを使わないデバイスではよく使われる手法です。ここでは3つのLEDの状態をint型変数の最後3ビットからそれぞれ取得することで、0~8までの数字をLED点灯パターンの組み合わせとして使っています。
int pattern = 0;
void setup()
{
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop()
{
delay(1000);
pattern = pattern + 1;
digitalWrite(9, pattern & 0x1);
digitalWrite(10, pattern & 0x2);
digitalWrite(11, pattern & 0x4);
}