はじめての電子工作超入門

第43回 複数のセンサを組み合わせた照明デバイス制作に挑戦! 〜Arduino+センサの開発が劇的に楽になる!ローム・センサ評価キットを試してみた

1-P1220993

前回ロームセンサ評価キットのカラーセンサ×Arduinoを使って取得した色をフルカラーLEDで表示するプログラムを作成しました。今回は、そのプログラムをさらに応用し、評価キットに付属している気圧センサ、温度センサも組み合わせて、複数のセンサによる環境情報で色や光りかたが変化するちょっと知的な照明デバイスの制作にチャレンジします!

今回の電子工作レシピ

完成までの時間目安:60分
必要なパーツ

※ロームセンサ評価キットは下記サイトから購入できます!
チップワンストップ
ザイコストア

目次

  1. 照明デバイスの仕様を考えてみる
  2. 気圧センサ、温度センサの使い方
  3. 複数のセンサを搭載した場合のデータの取得方法
  4. 照明デバイスプログラムの作成
  5. 照明デバイスのケースを作成
  6. まとめ

1.照明デバイスの仕様を考えてみる

まずは制作する照明デバイスの仕様を考えてみます。今回はカラーセンサ、温度センサ、気圧センサの3種類のセンサを使ってデバイスの制作にチャレンジしたいと思いますので、3種類のセンサの値がどのようになった場合、光りかたが変わるかを決めていきます。今回はセンサの値をもとにLEDを「明るさ」・「光の揺らぎ」・「色」の3種類で表現できるようにしてみます。

  • 光の揺らぎ = 色センサ
  • 光る色 = 気圧センサ
  • 光の明るさ = 温度センサ
図1.照明デバイスの仕様

図1 照明デバイスの仕様

実際に制作してみないとどのような照明の雰囲気になるかわかりませんが、一旦上記の仕様で考えて製作してみて、あまり実用的でなければ変更する流れで進めていきます。

 

2.気圧センサ、温度センサの使い方

カラーセンサは前回使い方を覚えたので、新たに気圧センサ、温度センサの使い方を学びます。といっても地磁気センサそしてカラーセンサを使っているので、この2つのセンサも同様に手軽に扱うことができます。温度センサ、気圧センサがシールドのどこの部分に設置できるか確認します。

 

図1 センサシールドの接続方法解説

図2 センサシールドの接続方法解説

 

これまでと同じように、センサパーツを評価キットシールドの上に設置します。今回I2C I/Fエリアには気圧センサとカラーセンサの2つが必要となるので、写真1のように並べて取り付けます。

 

写真1 温度センサ、気圧センサ、カラーセンサ

写真1 温度センサ、気圧センサ、カラーセンサ

 

写真2 温度センサBD1020HFV

写真2 温度センサBD1020HFV

 

写真3 気圧センサBM1383GLV

写真3 気圧センサBM1383GLV

 

取り付けが完了したら、Arduinoで複数のセンサからデータの取得ができるようにプログラム側を設定していきます。

 

3.複数のセンサを搭載した場合のデータの取得方法

温度センサと気圧センサのライブラリは下記の公式サイトからダウンロードしてください。ダウンロードからインストールまでの一連の流れは第42回第41回第40回の記事で詳しく紹介していますので、今回初めてセンサキットを試してみる方はそちらも参考にしてみてください。

上記サイトのページ下部から、センサ用ソフトウェアをダウンロードしたのち、Arduino IDEを開いてライブラリの追加から、ダウンロードしたファイルをそれぞれ選択してライブラリのインストールを完了してください。

写真9 ライブラリの追加

図3 ライブラリの追加

 

ライブラリのインストールが完了したら、スケッチの例から、気圧センサおよび温度センサのサンプルを開いて、Arduinoに書き込んで正常に動作するかチェックしてください。

  • 気圧センサのサンプル:「ファイル」-「スケッチの例」-「BM1383GLV」-「example」-「BM1383」
  • 温度センサのサンプル:「ファイル」-「スケッチの例」-「BD1020HFV」-「example」-「BD1020」

 

図4 気圧センサのサンプル動作例

図4 気圧センサのサンプル動作例

 

図5 温度センサのサンプル動作例

図5 温度センサのサンプル動作例

 

気圧センサと温度センサの単体での動作が確認できました。

では、複数センサの場合、データの取得はどうすればよいでしょうか?

 

「なんか複数になったらいきなり動かなくなるんだよなー」

「電圧とか電流足りないとかそこら辺のこと気を使わないといけないんだよなー」

「センサそれぞれの入出力違うから、そういうめんどくさいこと調整してあげないといけないんだよなー」

 

などと、電子工作をはじめたばかりだと、パーツが増えた途端一気に難易度があがって挫折するケースが多いのですが、そこは本製品が「キット」であることの強みでしょうか、複数センサの場合でも、基本そのままプログラムを組み合わせるだけで簡単に複数センサを扱うことができました。

今試した気圧センサ、温度センサのプログラムを組み合わせたのが下記の例です。

#include <BD1020.h> //温度センサ用
#include <Wire.h> //気圧センサ用
#include <BM1383GLV.h>  //気圧センサ用

BM1383GLV bm1383;//温度センサ用
int tempout_pin = A2; //温度センサ用
BD1020 bd1020;  //気圧センサ用

void setup() {

  Serial.begin(9600);
  while (!Serial);

  //温度センサ用
  bd1020.init(tempout_pin);
  Serial.println("BD1020HFV Sample");

  //気圧センサ用
  byte rc;
  Wire.begin();
  rc = bm1383.init();

}

void loop() {

  //************************************
  //温度センサ用
  //************************************
  float temp;
  bd1020.get_val(&temp);
  Serial.print("BD1020HFV Temp=");
  Serial.print(temp);
  Serial.print("  [degrees Celsius], ADC=");
  Serial.println(bd1020.temp_adc);
  
  delay(500);

  //************************************
  //気圧センサ用
  //************************************
  byte rc;
  float press;

  rc = bm1383.get_val(&press);
  if (rc == 0) {
    Serial.write("BM1383GLV (PRESS) = ");
    Serial.print(press);
    Serial.println(" [hPa]");
    Serial.println();
  }
  delay(500);
}

 

図6 温度センサ・気圧センサ組み合わせプログラム

図6 温度センサ・気圧センサ組み合わせプログラム

 

簡単に気圧センサ、温度センサの値を同時に取得することができましたね。では、さらに前回のカラーセンサのプログラムとも合体させてみます。これで、照明デバイスで利用する全てのセンサを1つのArduinoでデータ取得することができるようになりますね。

 

 

3センサの取得サンプルスケッチプログラム

#include <Wire.h> //気圧センサ・カラーセンサ用
#include <BM1383GLV.h>  //気圧センサ用
#include <BD1020.h> //温度センサ用
#include <BH1745NUC.h>

//カラーセンサ用
BH1745NUC bh1745nuc(BH1745NUC_DEVICE_ADDRESS_39);

//気圧センサ用
BM1383GLV bm1383; 

//温度センサ
int tempout_pin = A2;
BD1020 bd1020; 

void setup() {
  //温度センサ
  Serial.begin(9600);
  while (!Serial);
  bd1020.init(tempout_pin);
  Serial.println("BD1020HFV Sample");

  //気圧センサ・カラーセンサ用
  Wire.begin();


  //気圧センサ
  byte rc;
  rc = bm1383.init();

  //カラーセンサ
  byte rc2;
  rc2 = bh1745nuc.init();

  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}

void loop() {
  //***************************************************
  //温度センサの値を取得
  //***************************************************
  float temp;

  bd1020.get_val(&temp);
  Serial.print("BD1020HFV Temp=");
  Serial.print(temp);
  Serial.print("  [degrees Celsius], ADC=");
  Serial.println(bd1020.temp_adc);
  delay(20);

  //***************************************************
  //気圧センサの値を取得
  //***************************************************
  byte rc;
  float press;
  rc = bm1383.get_val(&press);
  if (rc == 0) {
    Serial.write("BM1383GLV (PRESS) = ");
    Serial.print(press);
    Serial.println(" [hPa]");
  }
  delay(20);

  //***************************************************
  //カラーセンサの値を取得
  //***************************************************
  byte rc2;
  unsigned short rgbc[4];
  rc2 = bh1745nuc.get_val(rgbc);
  int rVal  = 0;
  int gVal  = 0;
  int bVal  = 0;

  int maxVal  = 0;
  if (rc2 == 0) {

    for(int i=0;i < 3;i++){
      if(maxVal < rgbc[i]){
        maxVal  = rgbc[i];
      }
    }

    rVal  =  (float(rgbc[0])/maxVal)*255;
    gVal  =  (float(rgbc[1])/maxVal)*255;
    bVal  =  (float(rgbc[2])/maxVal)*255;

    //それぞれの色の閾値を設定
    Serial.print("BH1745NUC R=");   
    Serial.print(rVal);   
    Serial.print(",G=");
    Serial.print(gVal);
    Serial.print(",B=");
    Serial.print(bVal);
    Serial.print(",C=");
    Serial.println(rgbc[3]);
    Serial.println();
  }
  analogWrite(9,rVal);
  analogWrite(10,gVal);
  analogWrite(11,bVal);

  delay(1000);

}

 

図7 気圧センサ・温度センサ・カラーセンサのデータ一括取得

図7 気圧センサ・温度センサ・カラーセンサのデータ一括取得

 

複数センサのデータ取得はこれで問題ないですね。

 

4.照明デバイスプログラムの作成

ようやく本題ですね、照明プログラムを実装していきます。1.で決めた仕様にそって、センサデータの値をフルカラーLEDの制御に落とし込んでいきます。今回はわかりやすくするために、気圧は1013気圧より下なら青、上なら赤として、気温は0~35度の範囲で割合を出して明るさに、色は赤に近ければ近いほど揺らめくようにしています。

 

照明デバイスプログラム

#include <Wire.h> //気圧センサ・カラーセンサ用
#include <BM1383GLV.h>  //気圧センサ用
#include <BD1020.h> //温度センサ用
#include <BH1745NUC.h>

//カラーセンサ用
BH1745NUC bh1745nuc(BH1745NUC_DEVICE_ADDRESS_39);

//気圧センサ用
BM1383GLV bm1383; 

//温度センサ
int tempout_pin = A2;
BD1020 bd1020; 

void setup() {
  //温度センサ
  Serial.begin(9600);
  while (!Serial);
  bd1020.init(tempout_pin);
  Serial.println("BD1020HFV Sample");

  //気圧センサ・カラーセンサ用
  Wire.begin();


  //気圧センサ
  byte rc;
  rc = bm1383.init();

  //カラーセンサ
  byte rc2;
  rc2 = bh1745nuc.init();

  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}

void loop() {
  //***************************************************
  //温度センサの値を取得
  //***************************************************
  float temp;

  float power = 0;

  bd1020.get_val(&temp);
  Serial.print("BD1020HFV Temp=");
  Serial.print(temp);
  Serial.print("  [degrees Celsius], ADC=");
  Serial.println(bd1020.temp_adc);
  delay(20);

  //0~35度で仮定
  power = 1 - (temp / 35);

  //***************************************************
  //気圧センサの値を取得
  //***************************************************
  byte rc;
  float press;
  int colR  = 0;
  int colG  = 0;
  int colB  = 0;
  rc = bm1383.get_val(&press);
  if (rc == 0) {
    Serial.write("BM1383GLV (PRESS) = ");
    Serial.print(press);
    Serial.println(" [hPa]");
  }
  delay(20);

  //色を決定
  if(press < 1013){
    colR  = 255;
  }
  else{
    colB  = 255; 
  }

  //***************************************************
  //カラーセンサの値を取得
  //***************************************************
  byte rc2;
  unsigned short rgbc[4];
  rc2 = bh1745nuc.get_val(rgbc);
  int rVal  = 0;
  int gVal  = 0;
  int bVal  = 0;
  int yuragiVal = 0;

  int maxVal  = 0;
  if (rc2 == 0) {

    for(int i=0;i<3;i++){
      if(maxVal < rgbc[i]){ maxVal = rgbc[i]; } } rVal = (float(rgbc[0])/maxVal)*255; gVal = (float(rgbc[1])/maxVal)*255; bVal = (float(rgbc[2])/maxVal)*255; //それぞれの色の閾値を設定 Serial.print("BH1745NUC R="); Serial.print(rVal); Serial.print(",G="); Serial.print(gVal); Serial.print(",B="); Serial.print(bVal); Serial.print(",C="); Serial.println(rgbc[3]); Serial.println(); //色が赤寄りだと揺らぎが強い-青寄りだと穏やか if(rVal > bVal){
      yuragiVal = 100;
    }
    else{
      yuragiVal = 0;
    }
  }

  light(colR,colG,colB,yuragiVal,power);
/*  analogWrite(9,rVal);
  analogWrite(10,gVal);
  analogWrite(11,bVal);*/

  delay(20);
}

/*******************************
 * LEDの出力関数
/*******************************/
void light(int rVal,int gVal, int bVal,int yuragiVal,float power){
  
  int value = 100;
  
  if(yuragiVal){
    value = chaos();
  }

  analogWrite(9,rVal*value/100*power);
  analogWrite(10,gVal*value/100*power);
  analogWrite(11,bVal*value/100*power);
}

/*******************************
 * LEDのゆらぎ 0~100
/*******************************/
float x = 0.1; 
float x1 = 0.1;
int chaos(){
  // 1/f yuragi
  x = x1;
  if(x < 0.5){
    x = x + 2 * x * x;
  } 
  else {
    x = x - 2 * (1.0 - x) * (1.0 - x);
  }

  if(x < 0.08){ x = (float)(random(20,80))/1023; } if(x > 0.995){
    x = (float)(random(128,253))/1023;
  }

  x1 = x;
  x = x * 100;

  return (unsigned int)x;
}

写真6 フルカラーLEDの制御

写真4 フルカラーLEDの制御

プログラムを書き込んで動作させてみると、センサの値によって光りかたが変化するのがわかりますね。実験時は雨の日だったので色は青、色センサはそのLEDの青色を拾ってしまうので、揺らがなかったのですがこれはケースを取り付けるときに工夫して解消しましょう。

プログラムの条件をもっと複雑にして照明デバイスの表情を豊かにしたい気持ちもありますが、一旦このプログラムで進めていきたいと思います。

 

5.照明デバイスのケースを作成

デバイスの回路部分ができたら、あとはケースを作成していきます。ちょうど適当なサイズのランプフェードがあったので、それに合うArduinoケースを3Dプリンターで出力してそのケースに必要なパーツを納めます。

 

写真5 照明デバイスの土台となるケースを3Dプリンタで作成

写真5 照明デバイスの土台となるケースを3Dプリンタで作成

 

写真6 ランプシェードと照明基板

写真6 ランプシェードと照明基板

 

写真7 ランプシェードを上に載せて光らせると...

写真7 ランプシェードを上に載せて光らせると…

 

完成しましたね!この日は、曇りで低気圧が近づいているため、青く淡く光を放っていました。後日、気がついたら赤くゆらめくように光が変わっていて、時間経過と共に変わるのはなんだか楽しいですね。

 

まとめ

複数センサの扱いも、センサ評価キットであれば難しいことを考えずに利用することが可能ですね!今回利用した照明デバイスは、光りかたの条件をプログラムで変えてみたり、利用するセンサを変えてみるなど無限の工夫ができるデバイスです。さらにはイーサネットシールドや無線LANシールドと組み合わせることで、スマートフォンを利用して遠隔で照明デバイスの制御も可能になるなどの工夫も可能ですね。

ぜひ、みなさんも自分だけの照明デバイスを作っていただければ幸いです。

電子工作マニュアル Vol.5
赤川シホロ

電子工作や新しいデバイスをこよなく愛するエンジニア。日常生活のちょっとしたことを電子工作で作って試して、おもしろく過ごしたいと日々考えています。