wiki:TSL2561

光センサ TSL2561 の使い方

現在こちらのページで販売中のTSL2561デジタル光センサボードの説明ページです。 TSL2561はデジタル出力の光センサーです。

取得したデータを元に計算することで、Cdsセルなどに比べて正確な照度を求めることができます。 メーカー公開のデータシートへのリンクはこちらです。(pdf)

デーシートに記載されている詳細説明を意訳したものを載せます。※内容の正確さについては保証いたしかねます。

TSL2560とTSL2561は次世代型の光センサデバイスです。
どちらの製品も2つのアナログ・デジタルコンバーター(ADC)を搭載し、2つのフォトダイオードからの電流を積分します。
両チャンネルの積分は同時に行われます。
A/D変換サイクルが終わると、変換結果はChannel0とChannel1レジスタにそれぞれ送られます。
送信はデータが完全なままであるのを保証するためにダブルバッファリングされています。
この送信の後、デバイスは自動的に次の積分(測定)サイクルに入ります。
デバイスとの通信はI2CまたはSMBus通信によって独立して行われます。
よって、TSL256xデバイスはマイクロコントローラや組み込みのコントーローラと簡単に接続できます。
信号品質のために外部回路を必要としないので、基板面積を大幅に節約できます。
TSL256xはデジタル出力であるため、出力はアナログ信号と比較してノイズに耐性があります。
TSL256xは割り込み機能にも対応し、センサが光強度測定をするのを待つ必要性を排除することでシステムを簡便化できます。
割り込み機能の主要な使い方は光強度の有意な変化を検知することです。
検知する変化量はユーザーが光強度と時間で指定したり、光強度の不変さによって指定したりできます。
TSL2561は現在の光量からの強弱方向への変化量に対して閾値を設定することができます。
割り込みは測定値がこれらの閾値を超えた時に生成されます。

また、Adafruitからライブラリが公開されています。リンク(github) こちらも参考にしてください。
また、上記ライブラリのサンプルスケッチのコメントを意訳したものもページ下部にて公開していますので、ご覧ください。


通信方法

I2CまたはSMBusで通信を行います。電子工作で利用する際はI2Cになるとおもいますので、 このページではI2C通信での利用を前提に解説を進めます。

送信方法

データシートの一部を抜粋します。 脚注にあるように、I2C通信では簡略化して行われます。
結果として一般的なI2C通信と大きな違いはありません。

fig16

下はArduinoでの1byte分を書き込む実装例の一つです。

int _addr = 0x39;
void TSL2561::write8 (uint8_t reg, uint8_t value)
{
  Wire.beginTransmission(_addr);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

受信方法

データシートの一部を抜粋します。 脚注にあるように、I2C通信では簡略化して行われます。
結果として一般的なI2C通信と大きな違いはありません。

fig17

下はArduinoで2byte分を読みだす実装例の一つです。

int _addr = 0x39;
uint16_t TSL2561::read16(uint8_t reg)
{
  uint16_t x; 
  uint16_t t;

  Wire.beginTransmission(_addr);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(_addr, 2);
  t = Wire.read();
  x = Wire.read();
  x <<= 8;
  x |= t;
  return x;
}

接続

販売中のボードには、VDDから入力された電圧を3.3Vに変換するレギュレーターを実装してあります。 よって、電源電圧はArduinoと共通の5Vでも動作可能です。
下図のように配線してください。電源は3.3Vではなく5Vに接続しても構いません。 (実体配線図)

jittaihaisen

また、Arduinoのanalogピンの部分に次のように設置することもできます。

direct connect

この場合、ピンの入出力設定を書く必要があります。 Setup(){}内部の、初期化のはじめの方にに以下の文を追加してください。

  /* TSL2561 を基板に直付するときのピン設定 */
  #define TSL2561_VDD A2
  #define TSL2561_GND A3

  setup(){
    pinMode(TSL2561_VDD, OUTPUT);
    pinMode(TSL2561_GND, OUTPUT);
    digitalWrite(TSL2561_VDD, HIGH);
    digitalWrite(TSL2561_GND, LOW);

  }

計算方法

元々、TSL2561は液晶の輝度制御などに用いられることを想定しているため、人間の目の感度特性に近い測定ができるように工夫がされています。
大雑把に言えば、

1.もともと光センサというのは赤外線領域に対しての感度が強くなる

2.赤外線が強い環境では感覚とは違う測定値が出てしまう

3.そこで、赤外線と可視光のどちらも測定可能なCH0の測定値から、赤外線を中心的にを測定するCH1の測定値を引き算する

というものです。
なので、取得した測定値を式に代入することで、照度(単位:lux(ルクス))を正確に求めることができます。

どういう式を用いるかについて、データシートを元に示します。 販売しているのはCSパッケージです。

1. 0 < CH1/CH0  0.52 
 Lux = 0.0315  CH0 − 0.0593  CH0  ((CH1/CH0)^(1.4))
2. 0.52 < CH1/CH0  0.65 
 Lux = 0.0229  CH0 − 0.0291  CH1
3. 0.65 < CH1/CH0  0.80 
 Lux = 0.0157  CH0 − 0.0180  CH1
4. 0.80 < CH1/CH0  1.30 
 Lux = 0.00338  CH0 − 0.00260  CH1
5. CH1/CH0 > 1.30 
 Lux = 0

実装例については、長くなってしまうため、ライブラリを直接御覧ください。

動作サンプル

サンプルスケッチ(コメント意訳版)※コメントの正確性については保証いたしかねます

#include <Wire.h>
#include "TSL2561.h"

// TSL2561 サンプルプログラム 2015/12

// SCL は analog 5 に接続してください
// SDA は analog 4 に接続してください
// VDD は 3.3V DC に接続してください
// GROUND は common ground に接続してください
// ADDR を未接続/GND/VDDのどれに接続するかによってi2cアドレスを変更します
// Adruinoで利用する際の7bit表記では以下のとおり
// 接続状況によって適宜変更してください
// 未接続: TSL2561_ADDR_FLOAT (0x39)
// GND: TSL2561_ADDR_LOW  (0x29)
// VDD: TSL2561_ADDR_HIGH (0x49)
TSL2561 tsl(TSL2561_ADDR_FLOAT);

void setup(void) {
  Serial.begin(9600);
  //while (!Serial);
  if (tsl.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No sensor?");
    while (1);
  }

  // 周囲の明暗状況に合わせて適切にゲインを変更してください
  //tsl.setGain(TSL2561_GAIN_0X);         // ゲインなし:周囲が明るい場合
  tsl.setGain(TSL2561_GAIN_16X);      // ゲインx16:周囲が暗い場合

  // 積算時間を変更することで、光の測定時間を変更することができます
  // 長時間測定すると、データの取得は遅くなりますが、低光度環境での測定性能が向上します
  tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);  // 短時間測定:明るい環境
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS);  // 中時間測定:中程度の明るさ
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS);  // 最長時間測定:暗い環境

  // 設定は以上です
}

void loop(void) {
  // データを取得する簡単なサンプルです
  //単純に、赤外線か全波長域のダイオードの値か
  // "可視光"(ダイオードからの値とは違います)のチャンネルの測定値を読みます

  // 13-402 millisecondsかかります
  // 取得したいデータに応じてコメントアウトを外してください
  uint16_t x = tsl.getLuminosity(TSL2561_VISIBLE);
  //uint16_t x = tsl.getLuminosity(TSL2561_FULLSPECTRUM);
  //uint16_t x = tsl.getLuminosity(TSL2561_INFRARED);

  Serial.println(x, DEC); //SerialPlotterが読める(IDE 1.6.6で動作確認)

  // 詳細な値をよみとるサンプルです
  // MSB 16bitが赤外線、LSB 16bitが全波長域チャンネルの値で構成された32bitのデータを読みます
  // 値を自由に加工や比較して利用してください
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  Serial.print("IR: "); Serial.print(ir);   Serial.print("\t\t");
  Serial.print("Full: "); Serial.print(full);   Serial.print("\t");
  Serial.print("Visible: "); Serial.print(full - ir);   Serial.print("\t");

  Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir));

  delay(100);
}

動作図

・上記のプログラムを書き込むと、 ArduinoIDEのシリアルモニタではこのように表示されます。(センサから取得可能な値をすべて表示している状態)

serialmonitor

・ArduinoIDE 1.6.6から追加されたSerialPlotterではこのように表示されています。lux値が小さくなっているのはセンサに手をかざして暗くなっているところです。

plotter

Last modified 19 months ago Last modified on Feb 4, 2016 11:23:54 PM

Attachments (7)

Download all attachments as: .zip