EnsekiTT Blog

EnsekiTTが書くブログです。

TSL2561とESP-WROOM-32で部屋の明るさをはかった話

つまりなにしたの?

I2Cで遊ぼうと思って、ESP-WROOM-32に昔買った明るさセンサを繋いでみた。
f:id:ensekitt:20170916133805j:plain

TSL2561とは

レンジの広い明るさセンサ。二種類の帯域向けの明るさセンサを併せて使ってるみたい。
スイッチサイエンスさんで買って積んであったよ
https://www.switch-science.com/catalog/1801/

ライブラリつかわないの?

github.com

Arduino+TSL2561はうまく動いたけど、ESP-WROOM-32だとうまく動かなかったから
こちらのブログを参考に実装してみた。
okiraku-camera.tokyo

配線

ESP-WROOM-32のブレイクアウトボードが前提でこんな感じ。
f:id:ensekitt:20170916134624j:plain

Wireだけつかったコードの例

これをArduinoIDEで書き込む。

#include "Wire.h"

byte i2c_address = 0x39;
byte i2c_status = 0;
double lux_value;
uint16_t data_ch0 = 0;
uint16_t data_ch1 = 0;

enum {
  reg_control = 0,
  reg_timing = 1,
  reg_thr_L = 2,
  reg_thr_H = 4,
  reg_int = 6,
  reg_id = 0x0a,
  reg_data0 = 0x0c,
  reg_data1 = 0x0e
};


byte i2c_write_reg(byte reg, byte data){
  Wire.beginTransmission(i2c_address);
  Wire.write(reg);
  Wire.write(data);
  i2c_status = Wire.endTransmission();
  return i2c_status;
}

byte i2c_read16_swab(byte pointer){
  Wire.beginTransmission(i2c_address);
  Wire.write(pointer);
  i2c_status = Wire.endTransmission();
  Wire.requestFrom(i2c_address, (byte)2);
  uint16_t lsb = (uint16_t)Wire.read();
  uint16_t msb = (uint16_t)(Wire.read() << 8);
  return msb | lsb;
}

void start() {
  Serial.println("Start");
  Wire.begin();
  i2c_write_reg(reg_timing | 0x80, 0x2); //Log gain  402ms
  i2c_write_reg(reg_int | 0x80, 0x0);
  i2c_write_reg(reg_control | 0x80, 3);
  lux_value = 0;
}

void stop(){
  i2c_write_reg(reg_control | 0x80, 0);
}

double get_data(){
  data_ch0 = i2c_read16_swab(reg_data0 | 0x80);
  data_ch1 = i2c_read16_swab(reg_data1 | 0x80);
  Serial.print("data_ch0:");
  Serial.println(data_ch0);
  Serial.print("data_ch1:");
  Serial.println(data_ch1);
  if(!data_ch0 || !data_ch1){
    lux_value = 0.0;
  }
  double ch0 = (double)data_ch0;
  double ch1 = (double)data_ch1;
  double ratio = ch1 /ch0;
  //FN packageなので
  if (ratio > 0 && ratio <= 0.5)
    lux_value = 0.0304 * ch0 - 0.062*ch0 * pow(ratio, 1.4);
  else if(ratio > 0.5 && ratio <= 0.61)
    lux_value = 0.0224 * ch0 - 0.031 * ch1;
  else if(ratio > 0.61 && ratio <= 0.80)
    lux_value = 0x0128 * ch0 - 0.0153 * ch1;
  else if(ratio > 0.80 && ratio <= 1.30)
    lux_value = 0.00146 * ch0 - 0.00112 * ch1;
  else if(ratio > 1.30)
    lux_value = 0;
  lux_value *= ch0;
  return lux_value;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello TSL2561");
  start();
}

void loop() {
  // put your main code here, to run repeatedly:
  double current_lx = get_data();
  int v = current_lx*10.0;
  Serial.print("current_lx: ");
  Serial.println(v);
  delay(1000);
}

概ね1秒おきに各チャンネルのセンサ生値とLux換算した値を吐き出すはず。
換算は参考にしたブログだと想像してた値と違うのが出てきたので、
https://cdn-shop.adafruit.com/datasheets/TSL2561.pdf
の23ページT, FN, and CL Packageを使った。
多分自分が読み間違えたか写経しそこねたんだろうけど…

割り込みなどは使っていないのでたまに変な値が入ることがある。

できました

f:id:ensekitt:20170916133918p:plain

ESP-WROOM-32をArduinoIDEで使う方法はこちら

ensekitt.hatenablog.com