Arduinoで温度センサーを扱う

標準

今回はArduinoで温度センサーを扱うのに挑戦したいと思います。温度センサーとして使うのは「MCP9700E」です。このMCP9700Eは温度をアナログ出力してくれます。
しかし、今回は出力されたアナログ値の大小が分かればいいだけではなく、電圧をなるべく正確に求める必要があります。この点について、詳しく書いていきます。

ArduinoのA/D変換

Arduinoには、入力されたアナログ信号、つまりは電圧の変化をデジタル信号に変換するA/Dコンバーターが内蔵されています。この出力されるデジタル値は、0Vを最小、基準電圧を最大として10bit(210=1024段階)の数値として表現されます。

この基準電圧は、何も設定しなければ5.0Vになり、これが1024段階に分割されるので、分解能は5000÷1024=4.88mVということになります。しかし、これでは大雑把すぎて、もう少し正確な値を読み取りたいという時があります。そんな時には、この基準電圧を変更することで可能になります。以下はスケッチでanalogReference()に指定することが出来る内部基準電圧の一覧です。

analogReference() 概要 分解能
DEFAULT 電源電圧が基準になる。5.0V 4.88mV
INTERNAL 内部基準電圧が基準になる。1.1V 1.07mV
EXTERNAL AREFピンに供給される電圧。0V以上5V以下

AREFピンは、SDAピンとGNDピンの間にあるピンです。ここに電圧をかけることで、基準電圧を変更できます。

MCP9700Eの特性

今回使っていくMCP9700Eは色々な特性があるので、ある程度は把握しておく必要があります。

  • 誤差:±4.0 ℃ (0~70℃)
  • 出力電圧:500 mV (0℃)
  • 温度係数:10.0 mV/℃

以上の情報を利用して、電圧を求めていきます。ただし、このセンサーは電圧と温度が曲線的な関係なので、どうしても誤差が出てしまいます。この点を留意して次に進みましょう。

回路

今回は単純に、温度センサーに電圧を供給し、出力をA0で受け取るのみです。以下にその図を示します。

温度センサー回路図

ただ、プルダウン抵抗は無いと大分出力が不安定になってしまうので、これは必須アイテムです。

スケッチ

前項で紹介した特性を用いて、「電圧 = 温度 ÷ 10.0 + 500」という関係式を導きます。また、デジタル値から基準電圧の変換式を「デジタル値 × 1100 ÷ 1024」という関係式も導きます。この式を使って、簡単にスケッチを書いていきます。以下がそのスケッチです。

float volt;
float temp;

void setup() {
  Serial.begin(9600);
  analogReference(INTERNAL); //基準電圧を1.1Vに
}

void loop() {
  volt = (float)analogRead(A0) * 1100 / 1024; //デジタル値を電圧に変換
  temp = (volt - 500) / 10; //電圧を温度に変換
  Serial.println(temp);
  delay(100);
}

こんな感じです。基準電圧に関する記述はsetup()関数の中に記述します。

考察

上記スケッチで動かすと以下の様な結果を得ることが出来ます。温度センサー

指などで温めると、ちゃんと数値が上がることが分かります。(人によっては下がることも?)

Arduinoで地磁気センサーを扱う

標準

今回はArduinoで地磁気センサーを扱っていきます。
使用した地磁気センサーは「HMC5883L」です。三軸測定が可能で、分解能は1~2°という精度です。遊びで使う分には十分ですね。
また、センサーとの接続はI2Cです。

回路

今回使うセンサーは8本足ですが、通常時に実際使う端子は4本のみです。
Vddには3.3[V]電源、SDA、SCLにはそれぞれ対応するもの、GNDにはGNDを接続するのみです。こちらも単純な回路ですね。

ライブラリ

今回も、色々と扱いが難しいので、これを簡単にするためのユーザー製作のライブラリをインクルードします。
まず、下記GitHubプロジェクトから.zipでプロジェクトごとダウンロードします。

GcraudNano/GC5883

その後、ダウンロードした.zipファイルを解凍し、中にあるsample.cppを除去し、再び圧縮します。この工程を飛ばすと、sample.cppもロードされ、エラーが発生しますので気をつけてください。
この再圧縮した.zipを下記の図のようにArduinoに導入します。

ライブラリのロード

以上でライブラリの導入終了です。

スケッチ

上記ライブラリを使うことで非常に簡単にスケッチを書けます。以下がそのスケッチです。

#include <GC5883.h>
#include <Wire.h>

GC5883 com;

void setup() {
  Serial.begin(9600);
  com.init();
}

void loop() {
  double deg = com;
  Serial.println(deg);
  delay(100);
}

考察

上記スケッチで動作させると、シリアルプロッタからこんな感じのグラフが取得できます。

地磁気センサー

値が最大値から最小値まで飛んでいるのは、出力される値が180°→-180°まで飛んでいるわけで、つまりは真南を通り越したからです。
ブレッドボードをクルクル回すとちゃんと地磁気センサーが動作していることが分かります。
本来は3軸なので他の値も取得できそうな感じがしますが、今回はこのくらいにしておきます。

Arduinoでカラーセンサーを扱う

標準

今回はArduinoでカラーセンサーの値を読み取ってみようと思います。
使ったカラーセンサーは「S11059」です。

回路

今回使うS11059は動作電圧(Vdd)が2.25~3.63[V]といったように、Arduinoの5[V]を直接引っ張ることが出来ません。これをするには、レベル変換回路が必要になるのですが、これは面倒なので今回はArduinoの3.3[V]を引っ張ることにします。
他の端子はSCLはSCL、SDAはSDAに接続するのみです。単純ですね。
この時、SCLとSDAにはプルアップ抵抗を挟むことが推奨されています。 (CbusとVddの値によって変化するが2.2[kΩ]程度)

ライブラリの導入

今回のプログラムを作成するにあたって、カラーセンサーの値をより簡単に読み取るための専用ライブラリを使います。
下記GitHubのプロジェクトページの下の方から、ライブラリを.zip形式でダウンロードしてください。

jakalada/Arduino-S11059

その後、ソフト側からライブラリをロードします。

ライブラリのロード

以上でライブラリの導入は完了です。あとはコード側で指定することでライブラリを実際に使用することが出来ます。

スケッチ

上記ライブラリを導入した上で、同プロジェクト内にあるサンプルソースをコピペします。
また、以下のソースはそのサンプルソースをSketchのシリアルプロッタのグラフの色に概ね合致するように若干カスタムしてあります。どっちを使っても構いません。

#include <Wire.h>
#include <S11059.h>

S11059 colorSensor;

void setup() {
  Serial.begin(9600);
  colorSensor.begin();

  // 積分モードを固定時間モードに設定
  colorSensor.setMode(S11059_MODE_FIXED);

  // ゲイン選択
  // * S11059_GAIN_HIGH: Highゲイン
  // * S11059_GAIN_LOW: Lowゲイン
  colorSensor.setGain(S11059_GAIN_HIGH);

  // 1色あたりの積分時間設定(下記は指定可能な定数ごとの固定時間モードの場合の積分時間)
  // * S11059_TINT0: 87.5 us
  // * S11059_TINT1: 1.4 ms
  // * S11059_TINT2: 22.4 ms
  // * S11059_TINT3: 179.2 ms
  colorSensor.setTint(S11059_TINT1);

  // ADCリセット、スリープ解除
  if (!colorSensor.reset()) {
    Serial.println("reset failed");
  }

  // ADCリセット解除、バスリリース
  if (!colorSensor.start()) {
    Serial.println("start failed");
  }
}

void loop() {
  // 積分時間よりも長く待機
  //
  // 固定時間モード時のS11059.delay()で実行される待機処理の時間は
  // S11059.setTint(tint)で設定した値に応じて異なります
  colorSensor.delay();

  // センサのデータ用レジスタ(赤、緑、青、赤外)をまとめてリード
  if (colorSensor.update()) {
    Serial.print(colorSensor.getBlue());
    Serial.print(",");
    Serial.print(colorSensor.getGreen());
    Serial.print(",");
    Serial.print(colorSensor.getRed());
    Serial.print(",");
    Serial.print(colorSensor.getIR());
    Serial.println("");
  } else {
    Serial.println("update failed");
  }

  delay(100);
}

考察

上記ソースコードで動作させて、シリアルプロッタで見てみたところ以下のようになりました。
カラーセンサー

上記プロットで赤は赤色要素、オレンジは緑色要素、青は青色要素、アクアは赤外線要素の値を表しています。
感度の差があるのか、デフォルトとしての値が違いますね。

この検証でArduinoの尊さを実感しましたね。I2CはRaspiでも読み取れますが、電圧を下げれるのはArduinoの利点ですね。この調子で地磁気センサーも扱っていきます。

Arduinoで超音波センサーを扱う

標準

今回は、Arduinoで超音波センサーを使って、距離を測定したいと思います。
使用した超音波センサーモジュールは「HC-SR04(400円)」です。モジュール化されているのでとても扱いやすいです。

回路図

基本的に、超音波センサーモジュールの基盤に書かれている配線にすれば完了です。念の為、ソフトで作図したものも貼っておきます。

超音波センサー回路図

Trigピンに、パルス波の信号を出し、反射するのに要した時間がEchoピンから返ってきます。

センサー特性

この超音波センサーモジュールは、データシートによると以下の特性を持っています。

  • 分解能:0.3[cm]
  • 測定可能距離:2~400c[cm]
  • 範囲:15°

スケッチ

Trigピンに10μsだけHIGHを書き込むとそのうちに8回のパルス波を出すそうなので、それに従って書いていきます。

double value = 0;
void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
}

void loop() {
  digitalWrite(3, LOW);
  delayMicroseconds(2);
  digitalWrite(3, HIGH );
  delayMicroseconds(10);
  digitalWrite(3, LOW);

  value = pulseIn(2, HIGH);
  value = value / 2 * 340 * 100 / 1000000;

  Serial.println(value);
  delay(100);
}

8~12行目でパルス波を出し、それをpulseInで拾います。この時、反射に要した時間がvalueに代入されているので、これを音速340[m/s]と仮定して、距離を算出します。

考察

シリアルプロッタを使って距離が正しく測定できているか確認してみました。

距離測定

概ね正常に測定できていますが、正常に拾えなかった時に極端に値が大きくなったり、超音波の特性上布状の材質は測定が困難なようです。実際、上記グラフの極端に値が上下しているところは、布に対して測定した時です。
また、手などの反射できる範囲が狭い材質に対しても測定に若干難がありそうです。

このセンサーは価格400円のわりには分解能が0.3cmという精密さを誇っているので、プログラムの改良によっては、実用的な何かが作れそうです。

ArduinoでCdSセンサーを扱う

標準

今回は、Arduinoの初心者は初心者らしく、簡単なCdSセンサーの扱いについて学んでいきたいと思います。
CdSセンサーをRaspberry Piで扱った時の記事はこちらの「Raspberry PiでCdSセンサーの値を読み取る」を参照してください。基礎的な事項はこちらと同じです。
ただ、何度も言っている通りArduinoはアナログ値の読み取りが直接可能なので、A/Dコンバーターは不要です。

回路図

まず、Arduinoでの回路を作ります。プルダウン抵抗を忘れないほうが良いです。センサーの値が安定します。
今回は、明るさである閾値を下回ったらLEDが点灯するという単純なものを作ってみます。

CdSセンサー回路図

スケッチ

Arduinoで動作するプログラミング言語をスケッチ(Sketch)といいます。見た感じJavaで動作するらしく、文法もJavaライクな点が多いように感じます。(当ブログでは、SketchのハイライトはJavaで設定しています。)
では、今回のCdSセンサーの値を読み取るスケッチを見てみます。

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
}
void loop() {
  int value = analogRead(0);
  Serial.println(value);
  if(value>=40) {
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }
  delay(100);
}

13番ピンを出力、A0番ピンを入力に設定しています。
もし、A0番ピンから入力された明るさの値が40を下回った時、LEDが消灯し、40以上になった時、LEDが点灯するようになっています。
もし、変化がないという場合はシリアルモニタやシリアルプロッタなどを活用し、適切な閾値に設定し直してください。

考察

プルダウン抵抗である程度値が安定しているといえども、コンデンサーが必要なのか、明るさが同じでも一定の振れ幅を持っているようです。以下のシリアルプロッタの図を御覧ください。

シリアルプロッタの様子

振幅約10で延々と数値が振れています。
指などでCdSセンサー部分を隠すと確実に読みっていることが分かります。LEDの状態が変化することも確認してください。

指で隠してみる

実用的に使うには、もうちょっと誤差的な振れ幅を無くしたいところですね。やはりコンデンサーが必要なのでしょうか。これを使えば、必要な時間に照明をつける装置などを作れたり、色々なものに応用できそうですね。回路も簡単ですし、是非この機会に。

Arduinoを購入しました

標準

今日、秋月電子通商 八潮店にて、Arduino SMD Edtion Rev.3を購入しました。価格は2,940円です。
※追加でUSB type-bケーブル(100円程度)を購入する必要があります。

Arduino SMD Rev.3

このSMDエディションは、通常版のチップがDIP化されていない、基盤に組み込まれたバージョンのようです。なので、チップ故障時などの時は交換することは出来ません。まぁ、そう頻繁に壊れることは無いと思うのでこれで十分ですね。

使ってみた感じを率直に言うと、Raspberry Piに比べて、必要な環境の整備(OSが無いので、パソコンと接続するだけで使える)が少なく、また十分な開発環境(オープンソースなので、様々な開発ソフトがある上、公式も開発ソフトをリリースしている)が用意されているので、とても簡単に電子工作が出来て楽しいです。また、Raspberry Piと違い、アナログ値の入力に対応しているので、アナログ出力のセンサーの類を簡単に使いこなすことが出来ます。価格も3,000円を切るほど安いので、是非関心のある方は手を伸ばしてみてはいかがでしょうか。

今後はRaspberry Pi関連の他にもArduino関連の記事も出していくことになります。よろしくお願いします。