Arduinoで温度や照度などを測定する方法

Ardiunoとセンサー類を使用して温度、照度、大気圧、湿度を測定する試作品を製作しました。  
今年は電子工作をやりたくなったので挑戦しました。  

## １．試作品の構成

## １．１　仕様

今回は、環境測定器にほしい機能・性能を表で整理しました。データ通信や部品保護用の筐体は別途作ろうと考えています。また、機能といえるものではありませんが、なるべく廃棄物を減らすためにセンサー類はコネクタによる接続を行いました。

|   |   |   |
|---|---|---|
|ほしい機能|ほしい性能|メモ|
|マイコン機能|データの入出力、プログラムによる電子部品の制御|Ardiunoでつくること前提にしていたので、ほしい性能は大雑把に書いています。|
|温度を測定できる|-10～50℃|性能は、関東の平野部だと冬は最低-5℃くらい、夏は35℃ぐらいのためなので、余裕代を見た。|
|湿度を測定できる|20～90％|一般的なものであればおそらく大丈夫と考えてみた。|
|大気圧を測定できる|900～1050hPa|最大は、晴れの日の大気圧は1020hpa程度として余裕代を見込む。最小は、台風の気圧の低さを考えて、950hPa程度として余裕代を見込む。|
|照度を測定できる|100000lux以上|夏の太陽光は、100000lux以上といわれているため、夏の太陽光の強さを検知したい。|
|各種データを長期間通信できる|電源を乾電池とし1ヶ月以上、測定データを通信できる。|性能は暫定目標です。省電力が望ましいです。  <br>今は候補部品を選定し、将来プログラミング機能を追加するようにしました。|
|散水、埃から電気部品を保護する|散水、埃、飛散物から電気部品を保護する。|性能は暫定目標です。温度などの測定するセンサやマイコンが室外に置くと雨、埃などがかることで破損をするので、これを防きたい。|

## １．２　部品一覧

1.1に示した仕様を元に使う部品を選定しました。

![LCDmodule.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/f5a9c119-b384-9149-82db-e2ac0543127e.jpeg)


<使用部品一覧＞  
制御マイコン：Arduino Uno  
シールド(*)：Sigfox Shield for Arduino (UnaShield V2S)  
マルチセンサ（温度、湿度、大気圧計測）：BME280(シールド内蔵）  
照度センサ：VEML6030 光センサモジュール  
電池ボックス：単3単電池 の5本セット  
液晶モジュール:WayinTop 1602 LCD ディスプレイモジュール 16×2キャラクタ 青  
　　　　　　　 バックライト付き  
その他部品：I2C用通信ケーブル20cm（1本）、I2C用コネクタ（1個）  
(*)　Sigfox Shield を使ったのは、通信機能を試したいためです。

Arduinoと各種センサーとのインターフェースは、信号をI2C、コネクタをGroveとしました。  
I2Cは、I2C対応電子部品が多く普及しており、インターネット上上から情報を収集できるために選びました。  
Groveは、Arduinoとセンサをコネクタ接続できるので、用途によりセンサを容易に追加と削除が可能になるため、用途を広がられるようにしました。

## １．３　制御プログラムの作成

Arduinoの制御プログラムをスケッチと呼びます。  
サンプルスケッチと呼ばれるセンサなど電子部品の動作プログラムを見ていくと、Arduinoは以下の構成になっていました。今回は、一定時間に各種データを測定し、LCDに表示させるプログラムのため、機能ごとに分割してプログラミングを進めます。

```
//１．ヘッダ部(ライブラリや変数など）
#include <???.h>　　//　ライブラリ類
１．１　マルチセンサ関係のヘッダ部
１．２　照度センサのヘッダ部
１．３　LCD表示のヘッダ部

//２．初期化
void setup()
{
２．１　マルチセンサの初期化
２．２　照度センサの初期化
２．３　LCD表示の初期化 
}

//３．繰り返し処理
void loop()
{
３．１　マルチセンサから温度、湿度、大気圧のデータ取得
３．２　照度センサから照度のデータ取得
３．３　LCDへ温度、湿度、大気圧、照度を表示させる
delay(3000); 　//　左記の場合は、3000ms(3秒)ごとにloop()内の処理を続ける
}

//４．このブログラム専用のものやデバイス用に定義した関数

４．１　マルチセンサ用に定義された関数
void XXX()
{
…

}
４．２　照度センサ用に定義された関数
void YYY()
{
…
}
４．３　LCD表示用に定義された関数
void ZZZ()
{
…
}


```

プログラミングを機能ごとに分割してプログラミングをして、最終的に一つに集約しました。  
プログラムは、ステップ１～ステップ３の3段階に分けて行いました。  
ステップ１：温度、湿度、大気圧、照度をシリアルモニタに表示  
ステップ２：LCD表示テスト  
ステップ３：温度、湿度、大気圧、照度をLCDに表示  
ステップ３は、ステップ１とステップ２のプログラムを合体させます。

## ２．コネクタの接続

温度センサの接続例  
Arduinoとの接続は、GroveケーブルとGroveコネクタを用いて行うことにしました。そのため、Groveコネクタと照度センサをはんだ付けしました。  
はんだ付け前にGroveケーブルをつないで、黒のコードがGNDに接続しているかを確認します。

![light_sensor2-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/5c646c8c-74c9-2468-37e4-82fe5b063cfb.jpeg)


LCDディスプレイ  
配線間違えやすいので注意です。

![LCDmodule.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/23dacf12-5223-9373-2375-9cae2ba5bbde.jpeg)


## ３．温度、湿度、大気圧、照度をシリアルモニタに表示させる（ステップ１）

ステップ１である温度、照度、大気圧を測定してシリアルモニタに表示させます。  
シリアルモニタは、Arduinoの処理結果をパソコンの画面上に表示させるものです。

## ３．１　接続構成

![light_sensor_test4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/4773695d-3ad7-84f3-5b89-b02b19e6a6eb.jpeg)


## ３．２　プログラミング

github上に公開されていた2個のサンプルスケッチをダウンロードして組み合わせて作りました。  
[BME280用のサンプルスケッチ](http://trac.switch-science.com/wiki/BME280)…マルチセンサ（温度、照度、大気圧）をシリアルモニタに表示させる  
[VEML6030用のサンプルスケッチ](https://github.com/sparkfun/SparkFun_Ambient_Sensor_VEML6030/commit/c1cfa306ac328e6286c707e8db695bd74c35bc5e)…照度をシリアルモニタに表示させる  
  
<プログラミング>  
赤字…マルチセンサ（温度、照度、大気圧）をシリアルモニタに表示させるためのプログラム  
青字…照度をシリアルモニタに表示させるためのプログラム

```
//１．ヘッダ部(ライブラリや変数など）
１．１　マルチセンサ関係のヘッダ部
#include <???.h>　　//　ライブラリ類
…
１．２　照度センサのヘッダ部
#include <???.h>　　//　ライブラリ類
…

//２．初期化
void setup()
{
２．１　マルチセンサの初期化
２．２　照度センサの初期化
}

//３．繰り返し処理
void loop()
{
３．１　マルチセンサから温度、湿度、大気圧のデータ取得、シリアルモニタへ表示
３．２　照度センサから照度のデータ取得、シリアルモニタへ表示
}

//４．このブログラム専用のものやデバイス用に定義した関数

４．１　マルチセンサ用に定義された関数
void XXX()
{
…

}
４．２　照度センサ用に定義された関数
void YYY()
{
…
}
```

## ３．3 　結果

シリアルモニタ上に温度、大気圧、湿度、照度が表示されていました。  
気温21.38℃、大気圧1010.47hPa、湿度55.76%、照度255lux
![68747470733a2f2f6179746563686c61622e636f6d2f77702d636f6e74656e742f75706c6f6164732f323032312f30382f457469486c344155554145656c4b612e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/509d4aed-6573-c317-2145-1969126dcbda.png)




## ４．　LCDの表示テスト（ステップ２）

一定時間ごとにLCDに文字を表示させます。このプログラムでは、ループ処理の回数をLCDに表示させるプログラムとしました。

## ４．１　接続構成

下図のように配線をおこないます。

68747470733a2f2f6179746563686c61622e636f6d2f77702d636f6e74656e742f75706c6f6164732f323032312f30322f4c4344746573742d312d31303234783736382e6a7067.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/8bab6a8f-092c-3362-29a7-13252e0167e9.jpeg)


## ４．２　プログラミング

ArduinoIDEに"LiquidCrystal_I2C.h"ライブラリをインストールし、サンプルスケッチを元にプログラムを作りました。  
ライブラリは、ArduinoIDEの[スケッチ | ライブラリをインクルード | ライブラリを管理] からライブラリマネージャを開き、"LiquidCrystal I2C" を検索してインストール可能です。  
このプログラムではI2Cアドレスを==0x27==と指定しています。なお、アドレス設定はシリアルインタフェースボードのAddressJumperに依存します。  
注意点は、loop回数を記録する変数iをグローバル変数として定義することです。（==黄色マーカー==）

```
数字をループ回数分だけ表示させるプログラム
#include <LiquidCrystal_I2C.h>　 //ライブラリです。
//　Library　convert int to type string
#include <stdio.h>
#include <string.h>
int i = 0; //count number ←　loop回数用の変数で初期値を0としています。

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  // put your setup code here, to run once:
  lcd.init();                      // initialize the lcd 
  // Print the text to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("LCD print test");　
  lcd.setCursor(0,1);
  lcd.print("loop count");
  delay(3000);
  lcd.clear();
}

void loop() {
  String str; //print springs
  
  str = String(i);　// 整数を文字列の型に変換します。
  lcd.setCursor(0,0);　 //LCDへの文字の表示開始位置を指定します。
  lcd.print("loop number");　//LCDへ文字を表示させます。
  lcd.setCursor(0,1);
  lcd.print(str);　
  i = i + 1;　//loop回数が増えていきます。
  delay(3000);
  lcd.clear();　//lcdの表示をすべて消します。
  
}
```

## ４．３　テスト結果

数秒ごとに数字が増えていくのが見えてきます。  

https://youtu.be/0mpktwDSKZI

## ５．温度、湿度、大気圧、照度をLCDに表示（ステップ３）

ステップ１、ステップ２で作ったプログラムを集約します。

![68747470733a2f2f6179746563686c61622e636f6d2f77702d636f6e74656e742f75706c6f6164732f323032312f30322f6c696768745f6c63642d5f74656d705f73797374656d2d312d31303234783537362e6a7067.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782081/cc121316-bdb3-3bcf-324f-37260358cbd3.jpeg)


## ５．１　プログラミング

ステップ１、ステップ２で作ったプログラムを集約します。  
赤…マルチセンサ（温度、照度、大気圧）のデータを記録する  
青…照度のデータを記録する  
オレンジ…照度をシリアルモニタに表示させる  
主な注意点は、２つあります。  
1点目は、ステップ１で作ったプログラムに対して、シリアルモニタに表示させるプログラム部を削除します。  
2点目は、LCD表示を1回の繰り返し処理で、温度と湿度と、大気圧と照度の2回に分割して表示させます。  
これは、買ったLCDが2行までしか表示できない制約をカバーしています。

```
#include <Wire.h>
#include <stdio.h>
#include <string.h>
//１．ヘッダ部(ライブラリや変数など）
１．１　マルチセンサ関係のヘッダ部
#include <???.h>　　//　ライブラリ類
…
１．２　照度センサのヘッダ部
#include <???.h>　　//　ライブラリ類
…
１．３　LCD表示部のヘッダ部
#include <???.h>　　//　ライブラリ類
…
//２．初期化
void setup()
{
２．１　マルチセンサの初期化
２．２　照度センサの初期化
２．３　LCD表示部のヘッダ部
}

//３．繰り返し処理
void loop()
{
３．１　マルチセンサから温度、湿度、大気圧のデータ取得、シリアルモニタへ表示
３．２　照度センサから照度のデータ取得、シリアルモニタへ表示
//３．３　LCDへ温度、湿度、大気圧、照度を表示させる
  str = "TEMP " + String(temp)+"degC"; //1行目に温度を表示させるプログラム、以下３行
  lcd.setCursor(0,0);
  lcd.print(str);
  str = "HUM " + String(hum)+"%";　//２行目に湿度を表示させるプログラム、以下３行
  lcd.setCursor(0,1);
  lcd.print(str);
  delay(3000); 　//3秒間表示させっぱなしにして、LCD画面を消去する、以下2行
  lcd.clear();
  
  str = "PRES " + String(press)+"hPa";　//1行目に大気圧を表示させるプログラム、以下３行
  lcd.setCursor(0,0);
  lcd.print(str);
  str ="LIT "+String(lux)+"Lux";　//２行目に照度を表示させるプログラム、以下３行
  lcd.setCursor(0,1);
  lcd.print(str);
  delay(3000); 　//3秒間表示させっぱなしにして、LCD画面を消去する、以下2行
  lcd.clear();
}

//４．このブログラム専用のものやデバイス用に定義した関数

４．１　マルチセンサ用に定義された関数
void XXX()
{
…

}
```

## ５．２　動画結果

以下の動画のように表示されます。  

https://youtu.be/6yZiRHyArNA

https://youtu.be/2oX-LbYGbxo

## ６．まとめ

Ardiunoは、シールドと呼ばれる基盤を使うと、SDカードによるデータの記録やSigfox通信による記録も可能です。今後、このブログで製作した試作品をベースに再試作をおこない挑戦しようと思います。

製品設計目線で見た場合、規格化された電子部品を組み合わせて試作することで、モジュール設計を体験できます。  
この試作品は、入力部であるセンサ類、センサデータの入出力を制御するマイコンであるArduino、出力部であるLCDのそれぞれの機能を組み合わせて作っています。  
センサ、LCDは、Ardiunoとの接続方法を統一することでモジュール設計対応をさせて、用途に応じて、測定機能を容易に変更できるようにしました。

|   |   |
|---|---|
|分類|モジュール設計対応|
|機械|センサのコネクタはI2C用のGroveコネクタを使用した。  <br>（シールド内にあるオンボードのセンサを使用）|
|電気|センサ、LCDはすべてI2C通信によりArdiunoとセンサ間で信号をやりとりすることにした。|
|ソフト|５．１のようにプログラムを各段階においてモジュールごとに分割して作成し、プログラム変更を容易にさせた。|