令和年度 スーパーサイエンス部学習会（Arduino）～電子制御プログラミングを学ぶ～
月 日（ ）
岡崎高校物理教室（北校舎 3F）【本学習会の目的・目標】
目的： 電子制御プログラミングの基本的な考え方を理解する。
目標： 各種センサを利用した測定器を製作し，プログラミングによって実用化する。
製作した測定器を用いて簡単な実験を行い，データを分析する。

【学習内容】□ 回路の作製□ 基本の L チカ
□ 9 軸慣性計測ユニット（加速度・角速度・磁束密度センサ）によるデータ取得□ 温度・湿度・気圧センサによるデータ取得□ OLED（有機 EL ディスプレイ）への文字の表示□ microSD カードへの保存□ 簡易実験（実験計画の立案，測定器のスケッチのカスタマイズ，測定，データ分析，発表）【Arduino についての基礎知識】(1) Arduino（アルドゥイーノ／アルデュイーノ）はマイコン（マイクロコントローラー）の一種で，プログラミングした通りに動作する機能を持っている。
(2) プログラミング言語は C++に似ている。
(3) プログラミングのためのアプリ（IDE／統合開発環境）は無料である。
(4) プログラム（コード）のことを「スケッチ」と呼ぶ。
(5) ソフトが“オープン”である。他の人が開発・公開したプログラムを自由に使うことができる。これらを「ライブラリ」と呼ぶ。
(6) ハードも“オープン”で，互換機が多く存在する。
(7) 令和 4 年 8 月現在，純正品で最も基本的な「Arduino UNO R3」は 3,940 円である。今回使用する互換機の Seeeduino XIAO は 850 円である。
(8) 電子制御プログラミングのためのシステムとしては，Arduino の他に RaspberryPi（ラズベリーパイ／ラズパイ）が有名である。一般には RaspberryPi の方が高機能とされるが，Arduino は RaspberryPi と比べて安価であり，起動が速く，また電力消費が少ない。

1

1. 回路の作製
今回は純正の Arduino ではなく，互換機の Seeeduino XIAO（シードゥイ
ーノシャオ）を用いて回路の作製・プログラミングを行う。Seeesuino XIAO
は数ある Arduino 互換機の中でも安価かつコンパクトで使いやすいのが特徴である。
【部品一覧】

⑥
⑤

④

⑦
⑧
③

②
⑨
①
⑩

⑫

⑪

① プリント基板
②
③
④
⑤
⑥
⑦
⑧
⑨
⑩
⑪
⑫

Seeeduino XIAO（+ シングルピンソケット 7P×2）
3.3V DC-DC コンバータ LM3671（+ シングルピンソケット 4P×1）
スライドスイッチ
XH コネクタ
9 軸慣性計測ユニット AE-BMX055（+ 丸ピンソケット 3P×2）
温度･湿度･気圧センサモジュール AE-BME280 （+ 丸ピンソケット 6P×1）
microSD カード
microSD カードスロット（+ 丸ピンソケット 10P×1，2P×2）
スズメッキ線（4 本）
OLED（有機 EL ディスプレイ）（+ シングルピンソケット 4P×1）
電池ボックス 単 3×3 本用 （XH コネクタハウジング取付済）

2

【回路図】

本学習会のメインはプログラミングなので，ハードウェアの詳細は省略する。回路図の意味を全て理解する必要はないが，一応，参考までに概略を示しておく。
・ Seeeduino XIAO，センサモジュール，OLED，microSD スロットは 3.3V の電圧で動作する。
（ちょうど 3.3V の電池がないため）専用の IC（LM3671）で乾電池 3 本の 4.5V
を 3.3V に変換している。なお，PC と USB 接続しているときには，USB の 5V を
Seeeduino XIAO が 3.3V に変換しているので LM3671 は必要ない。
・ Seeeduino XIAO とセンサモジュール／OLED は「I2C」という規格でデータの通信をする。それぞれの IC には，I2C 通信をするためのピンが 2 本ずつ決められており（SDA，
SCL）,それらを全部並列接続してよい。IC 内で別々のアドレスを割り当てているため，混線せず識別することができる。このため，複雑な機能を持つ回路でありながら，配線はシンプルである。
・ Seeeduino XIAO と microSD カード（スロット）は「SPI」という規格でデータ通信をする。
これは上述の I2C とは別なので，配線の系統もセンサモジュールとは別になっている。
【はんだ付けの実際】
はんだ付けをするときに注意するべき点は以下の通りである。
・ 火傷しないこと。
・ はんだを付けすぎないこと。
・ 低い部品から取り付けていくこと。
・ 極性がある部品は，取り付ける向きに注意すること。
・ こて先を基板の銅箔と部品のリード線の両方に当ててから，はんだを付けて融かす。はんだが流れるように融けて行き渡ったら，こて先を離す。

3

(1) スズメッキ線を写真のようにまげて取り付け，はんだ付けし，余分な線をニッパで切る。切る
ときに基板の銅線を切らないように注意する。

(2) シングルピンソケットを差し込み，基板に垂直になるように端の一箇所だけはんだ付けする。
横から見て斜めになっていたら，はんだを融かして付け直す。

斜めでないことを確認したら残りもはんだ付けする。シングルピンソケットは 4 箇所である。

(3) 丸ピンソケットも，シングルピンソケットと同様に斜めになっていないことを確認しながらはんだ付けする。丸ピンソケットは 6 箇所である。

切り欠き
が内側

(4) XH コネクタとスライドスイッチをはんだ付けする。XH コネクタは切り欠きのある方が内側になるようにする。

4

C1，C2，C3 の表示がある方が内側(5) Seeeduino XIAO，OLED，microSD カードスロット，AE-BMX055（9 軸慣性計測ユニット），AE-BME280（温度・湿度・気圧センサモジュール）を，向きに注意しながらソケットに差し込む。また，microSD カードをスロットに差し込んでおく。特に AE-BMX055 は向きがやや分かりにくいので，写真をよく見て正しく差し込むこと。この時点では，まだLM3671（3.3V DC-DC コンバータ）をソケットに差してはならない。電池も接続しては
ならない。

5

2. 基本の L チカ
このセクションは，プログラミングに慣れるためのトレーニングである。L チカとは「LED の点滅」のことである。Seeeduino XIAO には内蔵 LED が搭載されているので，それを利用してみよう。
(1) Seeeduino XIAO と PC を USB ケーブルで接続し，Arduino IDE を起動する。
メニュー［ツール］→ ボード：”Seeeduino XIAO”
シリアルポートを選択(2) スケッチを作成する。
ファイル名を設定して次のように記述する。コメント文（各行の//以降の文）は入力しなくてよい。ファイル名は自動で「sketch_aug10a」のように設定されるが，分かりやすいファイル名（「test_blink_01」「Lchika_01」など）に変更しておくとよい。
void setup() {pinMode(LED_BUILTIN, OUTPUT);}// 以下の処理を 1 回だけ行う（初期設定）// 内蔵 LED をデジタル出力に設定

void loop() {digitalWrite(LED_BUILTIN, LOW);}// 以下の処理を繰り返す// 内蔵 LED を点灯

アプリを起動，または新規ファイルを作成した段階で，void setup() { }と void loop() { }は既に入力されているので，入力は楽であろう。それぞれ初期設定を行う部分と繰り返し処理を行う部分である。Arduino ではこの 2 つは必須であり，決まり文句のようなものだと思えばよい。
Arduino などのマイコンは基本的にデジタルで動作する。Seeeduino
電位 3.3V
XIAO は「0」が電位 0V，「1」が電位 3.3V に対応している。上記スケッチの「LOW」は出力電位を 0V にするという意味である。内蔵 LED は予
め他方が 3.3V 側に接続されているため，「LOW」を出力することで LEDに電位差（電圧）が加えられ点灯する，というわけである。ちなみに「LOW」
ではなく「HIGH」とすると 3.3V が出力され，LED の電位差は 0V となり消灯する。
(3) スケッチを書き込む。
検証（コンパイル）→書き込み
橙色の LED が点灯すれば成功である。

検証(4) 他の内蔵 LED を点灯させてみる。
Seeeduino XIAO にはこの橙色の LED の他に 2 つの青 色 LED が 搭 載 さ れ て い る 。 上 記 ス ケ ッ チ の「LED_BUILTIN」を「PIN_LED2」「PIN_LED3」とす
るとこれらを点灯させることができる。
橙色の LED はスケッチを書き込むときにも点灯する
ので，制御できていることが明確に分かるようにするために青色に変更しておこう。

6

書き込み

LED

出力電位

(5) 内蔵 LED を点滅させてみる。

．．
このセクションでの目標は「L チカ」，すなわち LED の点滅であった。そこでスケッチを次のように変えてみよう。0 から作成し直す必要はなく，先に作成したスケッチを変更すればよい。
（「保存」ではなく）「名前を付けて保存」を選び，ファイル名を「test_blink_02」「Lchika_02」などに付け直せば元のスケッチも残しておける。今後，作成したスケッチの一部を再利用することが多いので，元のスケッチを残しておくとよい。変更した箇所は太字で示してある。
なお，今後スケッチが徐々に長くなっていくが，行頭の位置合わせには Space キーではなくTab キーを使うと便利である。
void setup() {pinMode(PIN_LED2, OUTPUT);}
void loop() {digitalWrite(PIN_LED2, LOW);
digitalWrite(PIN_LED2, HIGH);}// 内蔵 LED を点灯// 内蔵 LED を消灯

これを書き込んでみよう。
．
．
点滅 ではなく点灯 し続けてしまったのではないだろうか。実はきちんと点滅しているが，Arduino は命令を処理するのが非常に速いので，人間の目には点灯し続けているように見えてしまうのである。
そこで，「一定時間何もしない」命令（遅延関数）を加えてみよう。
void setup() {pinMode(PIN_LED2, OUTPUT);}
void loop() {digitalWrite(PIN_LED2, LOW);
delay(1000);
digitalWrite(PIN_LED2, HIGH);
delay(1000);}// 内蔵 LED を点灯// 1s 待つ// 内蔵 LED を消灯// 1s 待つ

明らかに点滅するようになったはずである。delay(1000)は 1000ms 待つ，という意味である。この数字を変えると点滅の周期が変わることを確認してみよう。
(6) 繰り返し処理をする。
前述のように，Arduino では setup()関数と loop()関数が必須である。setup()は{ }の中の処理をはじめに 1 回だけ行い，loop()は{ }の中の処理を（電源が OFF になるまで）無限に繰り返すものである。したがって，上のスケッチは LED の点滅が 1 回だけではなくずっと繰り返されるのである。
それでは，決まった回数だけ同じ処理を繰り返すにはどのようにすればよいだろうか。Arduino
ではこのようなとき for 文を用いる。スケッチを次のように変更してみよう。

7

void setup() {pinMode(PIN_LED2, OUTPUT);
for (int n=0; n<=4; n++) {digitalWrite(PIN_LED2, LOW);
delay(1000);
digitalWrite(PIN_LED2, HIGH);
delay(1000);}}// 以下の処理を 5 回繰り返す

void loop() {}for 文は，繰り返し回数を数えながら同じ処理を繰り返すものである。
for (int n=0; n<=4; n++) { }は，n=0 からスタートし n を 1 ずつ増やしながら 4 になるまで{ }中の処理を行う，という意味である。上の例では n=0,1,2,3,4 の 5 回分処理をする。
ここの条件を変更して，繰り返し回数を変えてみよう。
n++ は，「n に 1 を足して，改めて n に代入する」という意味である。また，n の前の int は，
このスケッチでは変数 n を整数（integer）として使う，という意味である。このように Arduino
では，スケッチに使用する変数の型を定義しておく必要がある。
この LED 点滅の命令が setup()の方に書かれていることに注意しよう。これを loop()の方に書くと，5 回点滅の処理を繰り返すとこになるので，結局はずっと点滅し続けてしまう。
繰り返し処理には while 文を用いてもよい。
void setup() {pinMode(PIN_LED2, OUTPUT);
int n=0;
while (n<=4) {digitalWrite(PIN_LED2, LOW);
delay(1000);
digitalWrite(PIN_LED2, HIGH);
delay(1000);
n++;
}
}

// n を整数として定義し 0 を代入する// 以下の処理を n が 4 になるまで繰り返す

void loop() {}(7) 明るさを変える。
p.7 で作成したスケッチを次のように変更してみよう。
void setup() {pinMode(PIN_LED2, OUTPUT);}
void loop() {digitalWrite(PIN_LED2, LOW);
delay(5);digitalWrite(PIN_LED2, HIGH);
delay(5);}// 内蔵 LED を点灯// 5ms 待つ// 内蔵 LED を消灯// 5ms 待つ

8遅延を 1s から 5ms に変えただけだが，その周期が速すぎて点灯し続けているように見えてしまう（delay 文がなかったときとほとんど同じである）。試しに，基板を軽く左右に振ってみよう。実際には LED が点滅していることが確認できるはずである。
このとき，常時点灯しているときと比べて少し暗く光っているのに気づいただろうか。
さらに次のように変更してみよう。さらに暗くなっていることが分かるはずである。
void setup() {pinMode(PIN_LED2, OUTPUT);}
void loop() {digitalWrite(PIN_LED2, LOW);
delay(1);digitalWrite(PIN_LED2, HIGH);
delay(9);}前述のように，Arduino は基本的にデジタルで動作するため，LED はは光
るか光らないかのいずれかである。しかし，高速で処理できることを利用す
ると，明るさを変えることができるのである。
ただ，明るさを変えたいだけなのにそれなりに長いスケッチを書く必要がある，とも言える。
なお，デジタルをアナログ的に使うために，パルスの幅を変調する方法のことを PWM（Pulse Width
Modulation）と呼ぶ。

// 内蔵 LED を点灯// 1ms 待つ// 内蔵 LED を消灯// 9ms 待つ

点灯

点灯
消灯
点灯

消灯している
時間が短い
5ms⇒ やや暗く点灯

消灯
5ms

点灯

消灯している
時間が長い

1ms⇒ 暗く点灯消灯
9ms

次のスケッチにしてみよう。
かなりシンプルになったが，これでも LED が暗く光っていることが分かる。
void setup() {}void loop() {analogWrite(PIN_LED2,223);}// 内蔵 LED を点灯

Arduino には PWM を簡単に実現するための関数 analogWrite が予め用意されているのである。これまで setup で記述してきた pinMode(PIN_LED2, OUTPUT) は，内蔵 LED をデ
ジタル出力に設定するためのものだったので，今回は不要である。
スケッチ中の 223 は明るさを決める数値である。ここには 0～255 までの整数を入力する。数値を大きくすると暗くなる。この数値を変えてみて，明るさが変わることを確認してみよう。
問 1 for と analogWrite を利用して，「徐々に明るくなって徐々に暗くなる」点滅を繰り返す
スケッチを作成せよ。

9

3. 9 軸慣性計測ユニット（加速度・角速度・磁束密度センサ）によるデータ取得
いよいよ，測定器にチャレンジしよう。
まずは 9 軸慣性計測ユニット（9 軸 IMU）を使ってみよう。加速度，角速度（ジャイロ），磁束密度（磁気）について，それぞれ 3 方向のデータを同時に取得できる便利なセンサである。
今回使用するのは BOSCH 社の BMX055 というセンサである。BMX055 が取得したデータ
は，「I2C」という通信規格で Arduino に送ることになっている。そのデータを処理するにはハードウェアに関する専門的な知識が必要であり，本来なら非常に長いスケッチを記述しなくてはならない。
そこで，ライブラリを使ってみよう。Arduino は“オープン”であり，他の人が開発・公開したスケッチ（ライブラリ）を自由に使うことができるのであった。BMX055 を利用するためのライブラリでは，I2C による複雑なデータ処理をいくつかの関数としてまとめてあり，分かりやす
い命令で実現できる。
（なお，今回使用するのは，秋月電子通商が公開しているサンプルスケッチの関数群を，新海がライブラリの形に整えたものであり，ライブラリとして一般に公開されているものではない。
）(1) センサ制御の基本スケッチ
まず，加速度を測定するスケッチを作成してみよう。
#include <Wire.h>#include <BMX055.h>// Arduino とセンサ間で I2C 通信をするライブラリの読み込み// 加速度・角速度・磁束密度センサを利用するライブラリの読み込み

BMX055 myBMX055;// このスケッチでライブラリを使うためのインスタンスを生成

void setup() {Wire.begin();Serial.begin(9600);
myBMX055.BMX055_Init();delay(300);}// I2C 通信を開始する宣言// 通信速度（bps）の設定// センサによるデータを初期化

void loop() {myBMX055.BMX055_Accl();// 加速度[m/s2]の読み取り

Serial.print(myBMX055.xAccl);
Serial.print(",");
Serial.print(myBMX055.yAccl);
Serial.print(",");
Serial.println(myBMX055.zAccl);// 加速度の表示

delay(100);// 100ms（0.1s）待つ

// 改行

}

スケッチを書き込んでも何も起こっていないように見えるが，きちんと測定できているはずである。PC のディスプレイにデータを表示してみよう。

10

メニュー［ツール］→［シリアルモニタ］

次々と数値が表示されていくのが確認できるはずである。グラフ化することもできる。
メニュー［ツール］→［シリアルプロッタ］

基板を傾けたり動かしたりしてみよう。ディスプレイに示された加速度の値が変化するはずである。静止していても 0m/s2 となっていないが，これは重力加速度を測定しているからである。
例えばセンサの𝑥軸，𝑦軸を水平にすると，𝑧軸方向の加速度が 9.8m/s2 または-9.8m/s2 となる。
スケッチには見慣れない命令がいくつか出てきたが，それぞれのコメント文を参照してほしい。
(2) クラスとインスタンス
コメント文にある「インスタンス」という用語については説明が必要であろう。今回使用したライブラリは以下の関数と変数がまとまったもの（クラス）で，その名称が BMX055 である。
BMX055_Init()
BMX055_Accl()
BMX055_Gyro()
BMX055_Mag()
xAccl，yAccl，zAccl
xGyro，yGyro，zGyro
xMag，yMag，zMag

センサを初期化する関数
加速度[m/s2]を測定し，下記の変数に一時的に保存する関数
角速度[°/s]を測定し，下記の変数に一時的に保存する関数
磁束密度[μT]を測定し，下記の変数に一時的に保存する関数
3 方向の加速度の値を一時保存するための変数，float（実数）型
3 方向の角速度の値を一時保存するための変数，float（実数）型
3 方向の磁束密度の値を一時保存するための変数，int（整数）型

これらを使うにはクラスをもとにインスタンスを生成する（一般的な型から具体的な実体を作る）必要がある。
BMX055 myBMX055;
は，BMX055 というクラスをもとにして myBMX055 というインスタンスを生成する，という意味である。このスケッチでは，これ以後 myBMX055 という名称でライブラリが使えるようになる。インスタンスはそのスケッチでしか通用しないため my～と名付けることが多いが，名称は他の関数などと重複しなければ何でもよい。

11実際にインスタンスを使ったのが次の文である。
myBMX055.BMX055_Init();
myBMX055.BMX055_Accl();
上の文は（自分が使う）myBMX055 を初期化する，下の文は（自分が使う）myBMX055 で加速度を測定するという意味である。インスタンス名とクラスで定義した関数をピリオド「.」でつなげればよい。
インスタンス名.クラスで定義される関数や変数(3) 表示方法のバリエーション
加速度を表示する部分
Serial.print(myBMX055.xAccl);
Serial.print(",");
Serial.print(myBMX055.yAccl);
Serial.print(",");
Serial.println(myBMX055.zAccl);
を，次のように変更してみよう。
Serial.print(myBMX055.xAccl1,1);
Serial.print(",");
Serial.print(myBMX055.yAccl,2);Serial.print(",");
Serial.println(myBMX055.zAccl,3);
シリアルモニタに表示される小数点以下の桁数が変わるはずである。
また，これらの 5 行の代わりに，
Serial.println(String(myBMX055.xAccl)+","+String(myBMX055.yAccl)+","+String(myBMX055.zAccl));または，Serial.println(String(myBMX055.xAccl,1)+","+String(myBMX055.yAccl,2)+","+String(myBMX055.zAccl,3));
としてみよう。これでも同じ結果になるはずである。1 行でも書けるわけだ。行数を減らしたいと考えるか，1 行を短くしてスケッチを見やすくしたいと考えるかは，単に好みの問題なのでどちらでもよい。1 行にする場合，複数のデータを + で連結すればよいが，それを実現するにはデータが「文字列」でなければならない。xAccl，yAccl，zAccl は実数（float 型）として定義されているので，String()という命令を加えて文字列に変換しておかなければならない。
問 2 角速度，磁束密度を測定するスケッチを書き，シリアルモニタとシリアルプロッタで確認せよ。加速度測定のスケッチを一部修正すればよい。

12

4. 温度・湿度・気圧センサによるデータ取得
続いて，温度・湿度・気圧センサを使ってみよう。使用するのは BOSCH 社の BME280 というセンサである。BME280 も I2C 規格に対応しており，ライブラリが公開されている。今回はSparkFun 社のライブラリを利用する。このライブラリ（BME280 クラス）では非常に多くの関数・変数が定義されているが，今回は次の 4 つのみを用いる。
beginI2C()
readTempC()
readFloatHumidity()

センサを初期化する関数
温度[℃]を測定して実数（float 型）を返す
湿度を[％]を測定して実数（float 型）を返す

readFloatPressure()

気圧[100hPa]を測定して実数（float 型）を返す#include <Wire.h>#include <SparkFunBME280.h>
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
myBME280.beginI2C();}// クラスからインスタンスを生成// センサを初期化

void loop() {}問 3 上記スケッチは loop 関数の部分が未完成である。1s おきに温度，湿度，気圧を測定する
スケッチを完成させよ。インスタンス名は変更してもよい。また，センサに指をあてて温度が上がっていく様子をシリアルモニタで確認せよ。

13

5. OLED（有機 EL ディスプレイ）への文字の表示
一応，測定器の原型はできた。しかし，いちいち PC に接続していては使いにくい。作製した回路には OLED（有機 EL ディスプレイ）があるので，それに測定値を表示してみよう。
今回の OLED には SSD1306 という IC が使われている。SSD1306 も I2C 規格で Arduino とデータ通信をするための ライブラリが公開されている。今回は Adafruit 社のライブラリ（Adafruit_SSD1306 クラス）を利用する。
まず，「Hello World !」と表示するスケッチを書いてみよう。使用する関数の意味などはコメン
ト文を参照してほしい。
#include <SPI.h>#include <Wire.h>#include <Adafruit_SSD1306.h>// 各種ライブラリの読み込み#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS// 各種定数を分かりやすい文字で定義しておく

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);// Adafruit_SSD1306 クラスからインスタンス myDisplay を生成
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);// エラーが出たらプログラムを実行しない}
myDisplay.clearDisplay();
myDisplay.display();
delay(1000);// 画面を消去// 上記命令を画面に出力// 1s 待つ

myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.setCursor(0, 0);
myDisplay.cp437(true);// 文字サイズ（括弧内の数値）を指定// 文字の色を指定// カーソルを(0, 0)に移動// フォントの種類を指定

myDisplay.println(F("Hello World !"));
myDisplay.display();// ”Hello World ! ”と表示して改行// 以上の命令を画面に出力}
void loop() {}コメント文の説明を参考にして，「Hello World !」以外の文字(0, 0)(127, 0)を表示してみよう。ただし表示できるのは半角英数のみである。
また，文字サイズ，表示位置も変えてみよう。カーソルの位置
は座標で指定するが，原点は左上隅なので注意しよう。
(0, 63)(127, 63)
このスケッチをベースに，p.10 で作成したセンサ制御のスケッチを組み合わせれば，測定値を OLED に表示できるはずである。例として，加速度を表示するスケッチを書いてみよう。
上の Hello World ! スケッチを開いておき，加速度測定のスケッチから適宜コピー&ペーストすればよい。センサによる測定値の表示を確認できればよいので𝑥方向のみでもよい。下記の例で14

は 3 方向とも表示するスケッチになっている。
#include <SPI.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>// 各種ライブラリの読み込み#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS// 各種定数を分かりやすい文字で定義

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;// クラスからインスタンスを生成
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);// エラーが出たらプログラムを実行しない}
myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();delay(500);// 画面を消去// 上記命令を画面に出力// センサを初期化// 0.5s 待つ

myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);// 文字サイズを指定// 文字の色を指定// フォントの種類を指定}
void loop() {myBMX055.BMX055_Accl();// 加速度[m/s2]の読み取り

myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.println(F("Accl"));myDisplay.println();// 画面を消去// カーソルを(0, 0)に移動// "Accl"と表示して改行// 空白行を入れて改行

myDisplay.print(F(" xAccl = "));
myDisplay.print(String(myBMX055.xAccl));myDisplay.println(F(" m/s2"));
myDisplay.println();// "xAccl = "と表示// x 方向の加速度を文字列に変換して表示// " m/s2"と表示して改行// 空白行を入れて改行

myDisplay.print(F(" yAccl = "));
myDisplay.print(String(myBMX055.yAccl));myDisplay.println(F(" m/s2"));
myDisplay.println();// 同上（y 方向の加速度を表示）

myDisplay.print(F(" zAccl = "));
myDisplay.print(String(myBMX055.zAccl));myDisplay.println(F(" m/s2"));// 同上（z 方向の加速度を表示）

myDisplay.display();// 以上の命令を画面に出力

delay(100);// 0.1s 待つ}

15

OLED に加速度が表示され，0.1s ごとに値が更新されていくのが確認できるであろう。
Arduino IDE を一端閉じてみよう。測定が継続できていることが OLED で確認できるはずである。すなわち，USB による給電以外は PC は必要ないということである。この時点で，外部（電池など）から給電するようにすれば，測定器として単独で使用できることになる。
なお，このスケッチでは Serial.print() を使っていないので，シリアルモニタやシリアルプ
ロッタを開いても PC のディスプレイではデータを確認できない。
問 4 上記スケッチを利用し，温度，湿度，気圧を 1s おきに OLED に表示するスケッチを書け。
問 5 上記スケッチと問 4 を利用し，加速度，角速度，磁束密度，温度，湿度，気圧を 1s おきに
OLED に表示するスケッチを書け。

16

6. microSD カードへの保存
これで一応，測定器として使える形になった。しかし，このまま実験で使うと，OLED に表示されたデータを見ながら記録用紙に書き写していかなければならない。この方法は現代ではスマートとは言えない。
そこで最後のステップとして，センサで測定したデータを microSD カードに保存してみよう。
Arduino では microSD カードを制御するためのライブラリが標準で用意されているので，それを利用する。まず，microSD カードに簡単な数値を書き込むスケッチを作成してみよう。
#include <SPI.h>#include <SD.h>// 各種ライブラリの読み込み

File myFile;// File クラスからインスタンス myFile を生成

void setup() {Serial.begin(9600);
while (!Serial);
if (!SD.begin(3)) {while(1);}// エラーが出たらプログラムを実行しない

myFile = SD.open("test.csv", FILE_WRITE);// ファイル”test.csv”を開いて書き込みモードにする
if (myFile) {myFile.println("data1,data2,data3,data4");
myFile.println("1,2,3,4");
myFile.println("12,3.4,0.56,7890");
myFile.close();}// "data1,data2,･･･"と書いて改行// "1,2,･･･"と書いて改行// "12,3.4,･･･"と書いて改行// ファイルを閉じる}
void loop(){}

詳細はコメント文の通りである。ファイル形式は csv で，一般的な表計算アプリ（Excel など）
で読めるものである。
Seeeduino XIAO への書き込み・実行が終わったら，一旦，PC から USB ケーブルを抜いて，
microSD カードを PC に差し込んで確認してみよう。
microSD カードに TEST(.CSV)というファイルが作成されている。これを開くと，1～3 行目のセ
ルに，スケッチの命令通りの文字・数値が書き込まれているのが確認できる。例えば，
myFile.println("1,2,3,4");のように，セルを分けたいときはカンマで区切ればよい。
センサで取得したデータを一定時間ごとに microSD カードに保存するには，「ファイルを開いてデータを取得し，それを書き込んで閉じる」命令を loop()に書けばよい。
17

#include <SPI.h>#include <SD.h>#include <Wire.h>#include <BMX055.h>
BMX055 myBMX055;
File myFile;int i = 1;// データ識別のための ID 番号を定義

void setup() {Wire.begin();Serial1.begin(9600);
while (!Serial1);// Serial を Serial1 に書き換えておく// 同上

if (!SD.begin(3)) {while(1);}
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myFile.println("ID,xAccl,yAccl,zAccl");myFile.close();}// ファイルを開いて書き込みモードにする

myBMX055.BMX055_Init();delay(500);// センサを初期化// 1 行目にデータのキャプションを書く// 一旦，ファイルを閉じる}
void loop() {myFile = SD.open("data.csv", FILE_WRITE);// ファイルを開いて書き込みモードにする

if (myFile) {myBMX055.BMX055_Accl();myFile.print(String(i)+",");
myFile.print(String(myBMX055.xAccl)+",");
myFile.print(String(myBMX055.yAccl)+",");
myFile.println(String(myBMX055.zAccl));myFile.close();}i++;delay(100);// 加速度を測定// ID 番号を書いて次のセルへ// x 方向の加速度を書いて次のセルへ// y 方向の加速度を書いて次のセルへ// z 方向の加速度を書いて改行// ファイルを閉じる// ID 番号を 1 つ増やす}

加速度のデータが microSD カードに書き込まれているのが PC で確認できただろうか。実験結果を分析するのに役立つであろう。グラフ化なども楽勝である。これと p.15 のスケッチを組み合わせれば，センサの測定値を OLED に表示しつつ，microSD カードに保存できるはずである。
#include <SPI.h>#include <SD.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS

128
64
3
0x3C

// 次頁へ続く

18

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;
File myFile;int i = 1;
void setup() {Wire.begin();Serial1.begin(9600);
while (!Serial1);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}if (!SD.begin(3)) {while(1);}
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myFile.println("ID,xAccl,yAccl,zAccl");myFile.close();}myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myBMX055.BMX055_Accl();myFile.print(String(i)+",");
myFile.print(String(myBMX055.xAccl)+",");
myFile.print(String(myBMX055.yAccl)+",");
myFile.println(String(myBMX055.zAccl));myFile.close();}myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.println(F("Accl"));myDisplay.println();
myDisplay.print(F(" xAccl = "));
myDisplay.print(String(myBMX055.xAccl));myDisplay.println(F(" m/s2"));
myDisplay.println();
myDisplay.print(F(" yAccl = "));
myDisplay.print(String(myBMX055.yAccl));myDisplay.println(F(" m/s2"));
myDisplay.println();19// 次頁へ続くmyDisplay.print(F(" zAccl = "));
myDisplay.print(String(myBMX055.zAccl));myDisplay.println(F(" m/s2"));
myDisplay.display();i++;delay(100);}

問 6 上記スケッチと問 5 を利用し，加速度，角速度，磁束密度，温度，湿度，気圧を 0.1s おきに OLED に表示し microSD カードに保存するスケッチを書け。

20

7. 簡易実験（実験計画の立案，測定器のスケッチのカスタマイズ，測定，データ分析，発表）
作製した測定器を利用して簡単な実験をしてみよう。Seeeduino XIAO から USB ケーブルを抜き，LM3671 をソケットに差し，電池を接続し，スイッチを ON にすれば測定できる。
実験のテーマは何でもよい。測定したデータを Excel でグラフ化して分析せよ。そのグラフの概形を予想してから測定すること。測定器のスケッチは問 6 をベースとし，テーマに応じて適宜アレンジせよ。例えば，最後の delay()で指定する測定周期を変更したり，OLED に表示する，
または microSD カードに保存するデータを精選したりせよ。
測定中にスケッチを変更したい場合は，必ずスイッチを OFF にし，電池と LM3671 を外してから PC と接続すること。

(1) テーマ(2) 目的(3) 方法(4) 仮説（グラフの概形の予想）(5) 結果(6) 考察

8. 参考文献
高本孝頼（2014）「みんなの Arduino 入門」リックテレコム
21

9. OLED（有機 EL ディスプレイ）のグラフィック表示
このセクションは，時間が余った場合の「おまけ」である。OLED は文字だけでなくグラフィックにも対応している。グラフィック表示のためのライブラリは Adafruit_GFX.h である。
#include <SPI.h>#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS// グラフィック表示のためのライブラリの読み込み

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}myDisplay.clearDisplay();
myDisplay.display();
delay(500);}
void loop() {myDisplay.drawPixel(10,5,SSD1306_WHITE);// 点の描画
myDisplay.drawLine(20,5,120,5,SSD1306_WHITE);// 線の描画
myDisplay.drawRect(5,15,20,20,SSD1306_WHITE);// 長方形の描画
myDisplay.fillRect(35,15,20,20,SSD1306_WHITE);// 長方形の塗りつぶし
myDisplay.drawCircle(80,25,10,SSD1306_WHITE);// 円の描画
myDisplay.fillCircle(110,25,10,SSD1306_WHITE);// 円の塗りつぶし
myDisplay.drawRoundRect(5,40,20,20,7,SSD1306_WHITE);// 角の丸い長方形
myDisplay.fillRoundRect(35,40,20,20,7,SSD1306_WHITE);// 角の丸い長方形の塗りつぶし
myDisplay.drawTriangle(80,40,70,60,90,60,SSD1306_WHITE);// 三角形の描画
myDisplay.fillTriangle(110,40,100,60,120,60,SSD1306_WHITE);// 三角形の塗りつぶし
myDisplay.display();}

上で挙げた関数の詳細は以下の通りである。
drawPixel(𝑥座標, 𝑦座標, 色)
drawLine(始点の𝑥座標, 始点の𝑦座標, 終点の𝑥座標, 終点の𝑦座標, 色)
drawRect(始点の𝑥座標, 始点の𝑦座標, 𝑥方向の辺の長さ, 𝑦方向の辺の長さ, 色)
fillRect(始点の𝑥座標, 始点の𝑦座標, 𝑥方向の辺の長さ, 𝑦方向の辺の長さ, 色)
drawCircle(中心の𝑥座標, 中心の𝑦座標, 半径, 色)
fillCircle(中心の𝑥座標, 中心の𝑦座標, 半径, 色)
drawRoundRect(始点の𝑥座標, 始点の𝑦座標, 𝑥方向の辺の長さ, 𝑦方向の辺の長さ, 角の半径, 色)
fillRoundRect(始点の𝑥座標, 始点の𝑦座標, 𝑥方向の辺の長さ, 𝑦方向の辺の長さ, 角の半径, 色)
drawTriangle(頂点 1 の𝑥座標, 頂点 1 の𝑦座標, 頂点 2 の𝑥座標, 頂点 2 の𝑦座標,
頂点 3 の𝑥座標, 頂点 3 の𝑦座標,色)fillTriangle(頂点 1 の𝑥座標, 頂点 1 の𝑦座標, 頂点 2 の𝑥座標, 頂点 2 の𝑦座標,
頂点 3 の𝑥座標, 頂点 3 の𝑦座標,色)22これと，p.15 のスケッチを利用して次のように書いてみよう。“水準器”である。
#include <SPI.h>#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS#define radius

128
64
3
0x3C
3

// グラフィック表示のためのライブラリの読み込み// 水準器の“泡”の半径を定義

int x,y;// 水準器の“泡”の座標を整数として定義
Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myBMX055.BMX055_Accl();// 加速度を測定
myDisplay.clearDisplay();
myDisplay.drawLine(45,30,95,30,SSD1306_WHITE); // 𝑥軸を表示
myDisplay.drawLine(115,5,115,55,SSD1306_WHITE); // 𝑦軸を表示
myDisplay.setCursor(5, 7);
myDisplay.print(String(myBMX055.xAccl,1)+" ");myDisplay.setCursor(5, 27);
myDisplay.print(String(myBMX055.yAccl,1)+" ");myDisplay.setCursor(5, 47);
myDisplay.println(String(myBMX055.zAccl,1));// 加速度の数値を[m/s2]で表示

x = int(myBMX055.xAccl*2.5);// 加速度の𝑥成分を軸のサイズに合わせて整数に変換
y = int(myBMX055.yAccl*2.5);// 加速度の𝑦成分を軸のサイズに合わせて整数に変換
myDisplay.fillCircle(70 - x,30,radius,SSD1306_WHITE);// 加速度に応じて“泡”の𝑥座標を移動
myDisplay.fillCircle(115,30 + y,radius,SSD1306_WHITE);// 加速度に応じて“泡”の𝑦座標を移動
myDisplay.display();
delay(100);}

回路を傾けると，“泡”が移動するのが分かるであろう。
さらに余力があれば，𝑎 − 𝑡図や𝑇 − 𝑡図などをリアルタイムで OLED に表示するスケッチにも挑戦してみよう。
23

10. 解答例
問1
void setup() {}void loop() {for (int n=255; n>=0; n--) {analogWrite(PIN_LED2,n);delay(10);}for (int n=0; n<256; n++) {analogWrite(PIN_LED2,n);delay(10);}}問 2 角速度#include <Wire.h>#include <BMX055.h>
BMX055 myBMX055;
void setup() {Wire.begin();Serial.begin(9600);
myBMX055.BMX055_Init();delay(300);}
void loop() {myBMX055.BMX055_Gyro();Serial.print(myBMX055.xGyro);
Serial.print(",");
Serial.print(myBMX055.yGyro);
Serial.print(",");
Serial.println(myBMX055.zGyro);delay(100);}

問 2 磁束密度#include <Wire.h>#include <BMX055.h>
BMX055 myBMX055;
void setup() {Wire.begin();Serial.begin(9600);
myBMX055.BMX055_Init();delay(300);}
void loop() {myBMX055.BMX055_Mag();
Serial.print(myBMX055.xMag);
Serial.print(",");
Serial.print(myBMX055.yMag);
Serial.print(",");
Serial.println(myBMX055.zMag);
delay(100);}24

問 2 加速度・角速度・磁束密度を同時に計測#include <Wire.h>#include <BMX055.h>
BMX055 myBMX055;
void setup() {Wire.begin();Serial.begin(9600);
myBMX055.BMX055_Init();delay(300);}
void loop() {myBMX055.BMX055_Accl();myBMX055.BMX055_Gyro();myBMX055.BMX055_Mag();
Serial.print("Accel x:");Serial.print(myBMX055.xAccl);
Serial.print("m/s2, y:");Serial.print(myBMX055.yAccl);
Serial.print("m/s2, z:");Serial.print(myBMX055.zAccl);
Serial.println("m/s2");
Serial.print("Gyro x:");Serial.print(myBMX055.xGyro);
Serial.print("deg/s, y:");Serial.print(myBMX055.yGyro);
Serial.print("deg/s, z:");Serial.print(myBMX055.zGyro);
Serial.println("deg/s");
Serial.print("Mag x:");Serial.print(myBMX055.xMag);
Serial.print("uT, y:");Serial.print(myBMX055.yMag);
Serial.print("uT, z:");Serial.print(myBMX055.zMag);
Serial.println("uT");
Serial.println();delay(100);}

問 3 温度#include <Wire.h>#include <SparkFunBME280.h>
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
myBME280.beginI2C();}
void loop() {Serial.println(myBME280.readTempC(),1);
delay(1000);}25

問 3 湿度#include <Wire.h>#include <SparkFunBME280.h>
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
myBME280.beginI2C();}
void loop() {Serial.println(readFloatHumidity(),1);
delay(1000);}

問 3 気圧#include <Wire.h>#include <SparkFunBME280.h>
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
myBME280.beginI2C();}
void loop() {Serial.println(readFloatPressure() / 100.0,1);
delay(1000);}

問 3 温度・湿度・気圧を同時に計測#include <Wire.h>#include <SparkFunBME280.h>
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
myBME280.beginI2C();}
void loop() {Serial.print("Temp: ");Serial.print(myBME280.readTempC(), 1);
Serial.print(" °C, Humidity: ");Serial.print(myBME280.readFloatHumidity(), 1);
Serial.print(" %, Pressure: ");Serial.print(myBME280.readFloatPressure() / 100.0, 1);
Serial.println(" hPa");
delay(1000);
}

26

問4
#include <SPI.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <SparkFunBME280.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}myDisplay.clearDisplay();
myDisplay.display();
myBME280.beginI2C();
delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.print(F("Temp = "));
myDisplay.print(String(myBME280.readTempC(),1));
myDisplay.println(F(" C"));
myDisplay.println();
myDisplay.print(F("Humidity = "));
myDisplay.print(String(myBME280.readFloatHumidity(),1));
myDisplay.println(F(" %"));
myDisplay.println();
myDisplay.print(F("Pressure = "));
myDisplay.print(String(myBME280.readFloatPressure()/100.0,1));
myDisplay.println(F(" hPa"));myDisplay.display();
delay(1000);
}

27

問5
#include <SPI.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>#include <SparkFunBME280.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;
BME280 myBME280;
void setup() {Wire.begin();Serial.begin(9600);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();myBME280.beginI2C();
delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myBMX055.BMX055_Accl();myBMX055.BMX055_Gyro();myBMX055.BMX055_Mag();
myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.print(F("Accl "));
myDisplay.print(String(myBMX055.xAccl,1)+" ");myDisplay.print(String(myBMX055.yAccl,1)+" ");myDisplay.println(String(myBMX055.zAccl,1));
myDisplay.print(F("Gyro "));
myDisplay.print(String(myBMX055.xGyro,1)+" ");myDisplay.print(String(myBMX055.yGyro,1)+" ");myDisplay.println(String(myBMX055.zGyro,1));
myDisplay.print(F("Mag "));
myDisplay.print(String(myBMX055.xMag)+" ");myDisplay.print(String(myBMX055.yMag)+" ");myDisplay.println(String(myBMX055.zMag));
myDisplay.println();
myDisplay.print(F("Temp "));
myDisplay.println(String(myBME280.readTempC(),1));
myDisplay.print(F("Humidity "));
myDisplay.println(String(myBME280.readFloatHumidity(),1));
myDisplay.print(F("Pressure "));
myDisplay.print(String(myBME280.readFloatPressure()/100.0,1));
myDisplay.display();
delay(1000);}28

問 6 解答例 1 スケッチの行数を少なくする。
#include <SPI.h>#include <SD.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>#include <SparkFunBME280.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;
BME280 myBME280;
File myFile;int i = 1;
void setup() {Wire.begin();Serial1.begin(9600);
while (!Serial1);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}if (!SD.begin(3)) {while(1);}
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myFile.println("ID,xAccl[m/s2],yAccl[m/s2],zAccl[m/s2],xGyro[deg/s],yGyro[deg/s],zGyro[deg/s],xMag[uT],yMag[uT],zMag[uT],Temp[C],Humidity[%],Pressure[hPa]");myFile.close();}myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();myBME280.beginI2C();
delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myBMX055.BMX055_Accl();myBMX055.BMX055_Gyro();myBMX055.BMX055_Mag();
myFile.print(String(i)+",");
myFile.print(String(myBMX055.xAccl)+","+String(myBMX055.yAccl)+","+String(myBMX055.zAccl)+",");
myFile.print(String(myBMX055.xGyro)+","+String(myBMX055.yGyro)+","+String(myBMX055.zGyro)+",");
myFile.print(String(myBMX055.xMag)+","+String(myBMX055.yMag)+","+String(myBMX055.zMag)+",");// 次頁へ続く29

myFile.println(String(myBME280.readTempC())+","+String(myBME280.readFloatHumidity())+","+String(myBME280.readFloatPressure()/100.0,1));
myFile.close();}myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.print(F("Accl "));
myDisplay.println(String(myBMX055.xAccl,1)+" "+String(myBMX055.yAccl,1)+" "+String(myBMX055.zAccl,1));
myDisplay.print(F("Gyro "));
myDisplay.println(String(myBMX055.xGyro,1)+" "+String(myBMX055.yGyro,1)+" "+String(myBMX055.zGyro,1));
myDisplay.print(F("Mag "));
myDisplay.println(String(myBMX055.xMag)+" "+String(myBMX055.yMag)+" "+String(myBMX055.zMag));
myDisplay.println();
myDisplay.print(F("Temp "));
myDisplay.println(String(myBME280.readTempC(),1));
myDisplay.print(F("Humidity "));
myDisplay.println(String(myBME280.readFloatHumidity(),1));
myDisplay.print(F("Pressure "));
myDisplay.print(String(myBME280.readFloatPressure()/100.0,1));
myDisplay.display();i++;delay(1000);}30

問 6 解答例 2 OLED の文字位置をなるべく揃える。スケッチ 1 行を短くする。
#include <SPI.h>#include <SD.h>#include <Wire.h>#include <Adafruit_SSD1306.h>#include <BMX055.h>#include <SparkFunBME280.h>#define SCREEN_WIDTH#define SCREEN_HEIGHT#define OLED_RESET#define SCREEN_ADDRESS

128
64
3
0x3C

Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
BMX055 myBMX055;
BME280 myBME280;
File myFile;int i = 1;
void setup() {Wire.begin();Serial1.begin(9600);
while (!Serial1);
if(!myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {while(1);}if (!SD.begin(3)) {while(1);}
myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myFile.print("ID,xAccl[m/s2],yAccl[m/s2],zAccl[m/s2],");
myFile.print("xGyro[deg/s],yGyro[deg/s],zGyro[deg/s],");
myFile.print("xMag[uT],yMag[uT],zMag[uT]",);
myFile.println("Temp[C],Humidity[%],Pressure[hPa]");myFile.close();}myDisplay.clearDisplay();
myDisplay.display();
myBMX055.BMX055_Init();myBME280.beginI2C();
delay(500);
myDisplay.setTextSize(1);myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.cp437(true);}
void loop() {myFile = SD.open("data.csv", FILE_WRITE);
if (myFile) {myBMX055.BMX055_Accl();myBMX055.BMX055_Gyro();myBMX055.BMX055_Mag();
myFile.print(String(i)+",");
myFile.print(String(myBMX055.xAccl)+",");
myFile.print(String(myBMX055.yAccl)+",");
myFile.print(String(myBMX055.zAccl)+",");
myFile.print(String(myBMX055.xGyro)+",");
myFile.print(String(myBMX055.yGyro)+",");
myFile.print(String(myBMX055.zGyro)+",");

31// 次頁へ続く

myFile.print(String(myBMX055.xMag)+",");
myFile.print(String(myBMX055.yMag)+",");
myFile.print(String(myBMX055.zMag)+",");
myFile.print(String(myBME280.readTempC())+",");
myFile.print(String(myBME280.readFloatHumidity())+",");
myFile.println(String(myBME280.readFloatPressure()/100.0,1));
myFile.close();}myDisplay.clearDisplay();
myDisplay.setCursor(0, 0);
myDisplay.print(F("a"));myDisplay.setCursor(15, 0);
myDisplay.print(String(myBMX055.xAccl,1)+" ");myDisplay.setCursor(55, 0);
myDisplay.print(String(myBMX055.yAccl,1)+" ");myDisplay.setCursor(95, 0);
myDisplay.println(String(myBMX055.zAccl,1));
myDisplay.setCursor(0, 10);
myDisplay.print(F("w"));
myDisplay.setCursor(15, 10);
myDisplay.print(String(myBMX055.xGyro,1)+" ");myDisplay.setCursor(55, 10);
myDisplay.print(String(myBMX055.yGyro,1)+" ");myDisplay.setCursor(95, 10);
myDisplay.println(String(myBMX055.zGyro,1));
myDisplay.setCursor(0, 20);
myDisplay.print(F("B"));
myDisplay.setCursor(15, 20);
myDisplay.print(String(myBMX055.xMag)+" ");myDisplay.setCursor(55, 20);
myDisplay.print(String(myBMX055.yMag)+" ");myDisplay.setCursor(95, 20);
myDisplay.println(String(myBMX055.zMag));
myDisplay.setCursor(0, 35);
myDisplay.print(F("Temp"));myDisplay.setCursor(72, 35);
myDisplay.println(String(myBME280.readTempC(),1)+" C");
myDisplay.setCursor(0, 45);
myDisplay.print(F("Humidity"));myDisplay.setCursor(72, 45);
myDisplay.println(String(myBME280.readFloatHumidity(),1)+" %");
myDisplay.setCursor(0, 55);
myDisplay.print(F("Pressure"));myDisplay.setCursor(60, 55);
myDisplay.print(String(myBME280.readFloatPressure()/100.0,1)+" hPa");
myDisplay.display();i++;delay(1000);}32