2013/08/18

I2Cカラーセンサ

秋月で販売している浜松フォトニクスのカラーセンサ S11059-02DTを試してみた。

・RGBに加えIRが計測できて、解像度が16bit/chになった。
・I2Cバス接続が可能。
・ダイナミックレンジが向上し、明るい太陽光下でも値が飽和しにくくなったので使いやすい。

接続のポイント
・3.3V系なので、5V系ボードではレベル変換が必要
・数kΩでプルアップ (3kΩ程度かな)

実物は米粒くらいの大きさ


ユニバーサル基板にハンダ付けするときは、四隅の足だけ残して、真ん中寄りの足をピンセットなどで上に折り曲げてから、4本の足をパッドにハンダ付けすると簡単にできる。

手前がカラーセンサ。奥はTMP006(非接触IR温度センサ)

1画素ドットカメラの時みたいに、またレンズでも付けてみようかと思っている。
得られた数値で、照度の換算なども出来そう。 

動作確認用スケッチ
最初はEnergia IDE(MSP430)で作っていたけど、Arduinoでも動く。Wireの仕様の関係で、1.0以降のAPIに対応したバージョンなら大丈夫だと思う。

MSP430 LaunchPadの場合、デフォルトのボードはI2CのSCLにLED2が接続されているため、通信ができない。 あらかじめLED2の黒いジャンパを外しておくこと。

スケッチでは固定露出モード動作となる。 マニュアル露出についてはまだテストしていないけど、任意の露出時間を選べそう。



/******************************************************************************** 
 * S11059_02dt I2C color sensor test sketch  v20151220   by KentN 
 *
 * 
 *  tested boards  
 *  MSP430 LaunchPad(G2553) (Energia IDE 0101E016)
 *   Arduino 1.0 or later (3.3V board or I2C level converter) 
 * 
 *  MSP430LaunchPad (Energia) 
 *  before enabling I2C bus, remove led2 JUMPER PIN 
 ********************************************************************************/

#include "Wire.h"

#define led 13 // Arduino LED PIN
//#define led RED_LED  //(MSP430 LaunchPad)

#define device_address 0x2A
#define control_reg 0x00
#define timing_reg_H  0x01
#define timing_reg_L 0x02

uint16_t red = 0;
uint16_t green = 0;
uint16_t blue = 0;
uint16_t IR = 0;

void getRGB();

void setup()
{
  Wire.begin();
  Serial.begin(9600); 
  pinMode(led,OUTPUT);
  digitalWrite(led,LOW);
  led_blink();
}

void loop()
{

  getRGB();

  Serial.print(red);
  Serial.print(", ");
  Serial.print(green);
  Serial.print(", ");
  Serial.print(blue);
  Serial.print(", ");
  Serial.println(IR);

  delay(500);
}

void getRGB()
{
  uint16_t colordata= 0;
  
  /* //manual exposure mode  
   setManualtGain(100);
   Wire.beginTransmission(device_address);
   Wire.write(control_reg);
   Wire.write(0x84); // ADC reset LowGain wakeup
   Wire.endTransmission();
   Wire.beginTransmission(device_address);
   Wire.write(control_reg);
   Wire.write(0x04); //start 
   Wire.endTransmission();
   */
   
  //Fixsed exposure mode settings
  //  LowGain mode
  //  0x00 = 87.5us
  //  0x01 = 1.4ms
  //  0x02 = 22.4ms
  //  0x03 = 179.2ms 
  //  HighGain Mode
  //  0x08 = 87.5us
  //  0x09 = 1.4ms
  //  0x0a = 22.4ms
  //  0x0b = 179.2ms 

    
  Wire.beginTransmission(device_address);
  Wire.write(control_reg);
  Wire.write(0x83); // ADC reset wakeup
  Wire.endTransmission(false);
  Wire.beginTransmission(device_address);
  Wire.write(control_reg);
  Wire.write(0x03);  // set gain & exposure time 
  Wire.endTransmission();

  delay(180*4); //wait exposure time x4ch

  led_blink();
  Wire.beginTransmission(device_address);
  Wire.write(0x03);
  Wire.endTransmission(false);
  Wire.requestFrom(device_address,8);
  //read data
  if (Wire.available() > 0){
  colordata = Wire.read();
  colordata <<= 8;
  colordata |= Wire.read();
  red = colordata;
  colordata =0;
  colordata = Wire.read();
  colordata <<= 8;
  colordata |= Wire.read();
  green = colordata;
  colordata =0;
  colordata = Wire.read();
  colordata <<= 8;
  colordata |= Wire.read();
  blue = colordata;
  colordata =0;
  colordata = Wire.read();
  colordata <<= 8;
  colordata |= Wire.read();
  IR = colordata;
  }   return;
}

void setManualtGain(uint16_t ex_time){
  uint8_t reg =0;
  Wire.beginTransmission(device_address);
  reg =(ex_time >>= 8);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.beginTransmission(device_address);
  reg |= ex_time;
  Wire.write(reg);
  Wire.endTransmission();
}

void led_blink()
{
  digitalWrite(led,HIGH);
  delay(10);
  digitalWrite(led,LOW);
}