UVセンサーSi1132をArduinoから制御する(I2C)

# Si1132

![Si1132.jpeg](https://qiita-image-store.s3.amazonaws.com/0/63450/038f4584-ecc4-2455-fb02-7b4820089ab1.jpeg)

# Datasheet

# Si1134で取得できる値
UV indexとambient lightが計測可能。

<img width="666" alt="si1134-input.png" src="https://qiita-image-store.s3.amazonaws.com/0/63450/ed97c9b4-34a5-be9e-94e2-8b12bce3df25.png">

| 項目名 | 値の意味 |
|:-:|:-:|:-:|
| ALS_VIS_DATA | Visibility |
| ALS_IR_DATA | Infrared Light|
| AUX_DATA | UVインデックスの値 |

# Slave Address

| Slave address | 0x60 |
|:-:|:-:|

# Who_am_i

| PART_ID  | 0x00 |
|:-:|:-:|

Si1132の場合、0x32が返ってくる。

```cpp:arduino
#define SI1132_PART_ID 0x00
#define SI1132_DEVICE 0x32

bool SearchDevice()
{
  byte device = 0x00;
  readI2c(SI1132_PART_ID, 1, &device);

  if(device == SI1132_DEVICE){
      return true;
  } else{
      return false;
  }
}
```

# Configuration

## UCOEF
UVindex測定係数を設定する。

| 項目  | アドレス | 値 |
|:-:|:-:|:-:|
| UCOEF0 | 0x13 | 0x7B |
| UCOEF1 | 0x14 | 0x6B |
| UCOEF2 | 0x15 | 0x01 |
| UCOEF3 | 0x16 | 0x00 |

## CHLIST
UV, IR, Visible lightを有効にする。

| 項目  | アドレス |Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 | 
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| CHILIST | 0x01 | EN_UV | EN_AUX | EN_ALS_IR | EN_ALS_VIS | | | 

## ここまでのコード

```cpp:arduino
#define SI1132_UCOEF0 0x13
#define SI1132_UCOEF1 0x14
#define SI1132_UCOEF2 0x15
#define SI1132_UCOEF3 0x16

#define SI1132_CHIPLIST 0x01
#define Si1132_MEASRATE0 0x08

#define SI1132_EN_UV 0b10000000
#define SI1132_EN_AUX 0b01000000
#define SI1132_EN_ALS_IR 0b00100000
#define SI1132_EN_ALS_VIS 0b00010000

void Configuration()
{
  writeI2c(SI1132_UCOEF0, 0x7B);
  writeI2c(SI1132_UCOEF1, 0x6B);
  writeI2c(SI1132_UCOEF2, 0x01);
  writeI2c(SI1132_UCOEF3, 0x00);

  int enable_sensor = SI1132_EN_UV|SI1132_EN_AUX|SI1132_EN_ALS_IR|SI1132_EN_ALS_VIS;
  writeI2c(SI1132_CHIPLIST, enable_sensor);

  // Rateの設定
  writeI2c(SI1132_CHIPLIST, 0xff);	
}
```

## Visible関連

VisibleのConfiguration。Visibilityでは、取得したVisibleと、ALS_VIS_ALIGN, ALS_RATE, ALS_VIS_ADC_REC, ALS_VIS_ADC_GAIN, VIS_RANGEの設定から、ALS_VIS_DATAを生成する。

![config_vis.png](https://qiita-image-store.s3.amazonaws.com/0/63450/e2e4a3fe-64ef-c162-5aeb-bfe80d8f2b0d.png)

| 設定する値 | 設定する場所 |
|:--|:--|
| ALS_VIS_ALIGN | ALS_ENCODING(0x06)の4bit目で設定 |
| ALS_RATE | MEAS_RATE0(0x08), MEAS_RATE1(0x09)で設定 |
| ALS_VIS_ADC_REC | ALS_VIS_ADC_COUNTER(0x10)の4〜6bit目で設定 |
| ALS_VIS_ADC_GAIN |  ALS_VIS_ADC_GAIN(0x11) の0〜2bit目で設定 |
| VIS_RANGE |  ALS_VIS_ADC_MISC(0x12)の5bit目で設定 |

### ALS_VIS_ALIGN

Bitをたてると17bit ADCの16bitを取ってくる。

| 項目  | アドレス | 
|:-:|:-:|
| ALS_ENCODING | 0x06 | 

| 項目  | アドレス |Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 | 
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| ALS_ENCODING | 0x06 |  | | ALS_IR_ALIGN | ALS_VIS_ALIGN | | | 

### ALS_VIS_ADC_REC

ALS-VIS測定を行う前に必要とするADCの回復周期を設定する。

| 項目  | アドレス | 
|:-:|:-:|
| ALS_VIS_ADC_COUNTER | 0x10 | 

| 値(bit)  | 周期 | 
|:--|:--|
| 000 | 1 ADC Clock (50 ns times 2ALS_VIS_ADC_GAIN) | 
| 001 | 7 ADC Clock (350 ns times 2ALS_VIS_ADC_GAIN)| 
| 010 | 15 ADC Clock (750 ns times 2ALS_VIS_ADC_GAIN)| 
| 011 | 31 ADC Clock (1.55 µs times 2ALS_VIS_ADC_GAIN)| 
| 100 | 63 ADC Clock (3.15 µs times 2ALS_VIS_ADC_GAIN)| 
| 101 | 127 ADC Clock (6.35 µs times 2ALS_VIS_ADC_GAIN)| 
| 110 | 255 ADC Clock (12.75 µs times 2ALS_VIS_ADC_GAIN)| 
| 111 | 511 ADC Clock (25.55 µs times 2ALS_VIS_ADC_GAIN)| 

### ALS_VIS_ADC_GAIN
ALS可視測定のための、ADCの積分時間を設定。

| 項目  | アドレス | 
|:-:|:-:|
| ALS_VIS_ADC_GAIN | 0x11 | 

| 値(bit)  | 周期 | 
|:--|:--|
| 000 | 1分割したADC Clock | 
| 100 | 16分割したADC Clock | 
| 110 | 64分割したADC Clock | 

## VIS_RANGE

| 項目  | アドレス | 
|:-:|:-:|
| ALS_VIS_ADC_MISC  | 0x12 | 


| 値(bit)  | 意味 | 
|:--|:--|
| 0 | Normal Signal Range | 
| 1 | High Signal Range  | 

## Visibleを追加したソースコード

```cpp:arduino
#define SI1132_UCOEF0 0x13
#define SI1132_UCOEF1 0x14
#define SI1132_UCOEF2 0x15
#define SI1132_UCOEF3 0x16
#define SI1132_CHIPLIST 0x01
#define Si1132_MEASRATE0 0x08
#define SI1132_ALS_ENCODING 0x06
#define SI1132_ALS_VIS_ADC_COUNTER 0x10
#define SI1132_ALS_VIS_ADC_GAIN 0x11
#define SI1132_ALS_VIS_ADC_MISC 0x12

#define SI1132_EN_UV 0b10000000
#define SI1132_EN_AUX 0b01000000
#define SI1132_EN_ALS_IR 0b00100000
#define SI1132_EN_ALS_VIS 0b00010000

#define SI1132_ALS_VIS_ALIGN 0b00010000

#define SI1132_1_ADC_CLOCK 0b00000000
#define SI1132_7_ADC_CLOCK 0b00010000
#define SI1132_15_ADC_CLOCK 0b00100000
#define SI1132_31_ADC_CLOCK 0b00110000
#define SI1132_63_ADC_CLOCK 0b01000000
#define SI1132_127_ADC_CLOCK 0b10100000
#define SI1132_255_ADC_CLOCK 0b01100000
#define SI1132_511_ADC_CLOCK 0b01110000

#define SI1132_1_DIVIDED_ADC_CLOCK 0b0000000
#define SI1132_16_DEVIDED_ADC_CLOCK 0b0000100
#define SI1132_64_DEVIDED_ADC_CLOCK 0b0000110

#define SI1132_NORMAL_SIGNAL_RANGE 0b00000000
#define SI1132_HIGH_SIGNAL_RANGE 0b00100000

void Configuration()
{
  writeI2c(SI1132_UCOEF0, 0x7B);
  writeI2c(SI1132_UCOEF1, 0x6B);
  writeI2c(SI1132_UCOEF2, 0x01);
  writeI2c(SI1132_UCOEF3, 0x00);

  int enable_sensor = SI1132_EN_UV|SI1132_EN_AUX|SI1132_EN_ALS_IR|SI1132_EN_ALS_VIS;
  writeI2c(SI1132_CHIPLIST, enable_sensor);

  // Rateの設定
  writeI2c(SI1132_CHIPLIST, 0xff);

  int flag_als_encoding = SI1132_ALS_VIS_ALIGN;
  writeI2c(SI1132_ALS_ENCODING, flag_als_encoding);

  // Visible
  writeI2c(SI1132_ALS_VIS_ADC_COUNTER, SI1132_511_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_GAIN, SI1132_1_DIVIDED_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_MISC, SI1132_HIGH_SIGNAL_RANGE);
}
```


## Infrared Light関連

![Config-ir.png](https://qiita-image-store.s3.amazonaws.com/0/63450/ddde7620-ca61-8da1-596b-36e6959a5ed3.png)

Infrared Light(IR)のConfiguration。Infrared Light(IR)では、取得したInfrared Light(IR)と、ALS_IR_ADCMUXのInputと、ALS_IR_ALIGN, IR_RATE, ALS_IR_ADC_REC, ALS_IR_ADC_GAIN, IR_RANGEの設定から、ALS_IR_DATAを生成する。

| 設定する値 | 設定する場所 |
|:--|:--|
| ALS_IR_ALIGN | ALS_ENCODING(0x06)の4bit目で設定 |
| ALS_RATE | MEAS_RATE0(0x08), MEAS_RATE1(0x09)で設定 |
| ALS_IR_ADC_REC | ALS_IR_ADC_COUNTER(0x1D)の4〜6bit目で設定 |
| ALS_IR_ADC_GAIN |  ALS_IR_ADC_GAIN(0x1E) の0〜2bit目で設定 |
| IR_RANGE |  ALS_VIS_ADC_MISC(0x1F)の5bit目で設定 |
| ALS_IR_ADCMUX | ALS_IR_ADCMUX(0x0E)で設定 |

### ALS_IR_ALIGN

Bitをたてると17bit ADCの16bitを取ってくる。

| 項目  | アドレス | 
|:-:|:-:|
| ALS_ENCODING | 0x06 | 

| 項目  | アドレス |Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 | 
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| ALS_ENCODING | 0x06 |  | | ALS_IR_ALIGN | ALS_VIS_ALIGN | | | 

### ALS_IR_ADC_REC

| 項目  | アドレス | 
|:-:|:-:|
| ALS_IR_ADC_COUNTER | 0x1D | 

ALS-IR測定を行う前に必要とするADCの回復周期。

| 値(bit)  | 周期 | 
|:--|:--|
| 000 | 1 ADC Clock (50 ns times 2ALS_IR_ADC_GAIN) | 
| 001 | 7 ADC Clock (350 ns times 2ALS_IR_ADC_GAIN)| 
| 010 | 15 ADC Clock (750 ns times 2ALS_IR_ADC_GAIN)| 
| 011 | 31 ADC Clock (1.55 µs times 2ALS_IR_ADC_GAIN)| 
| 100 | 63 ADC Clock (3.15 µs times 2ALS_IR_ADC_GAIN)| 
| 101 | 127 ADC Clock (6.35 µs times 2ALS_IR_ADC_GAIN)| 
| 110 | 255 ADC Clock (12.75 µs times 2ALS_IR_ADC_GAIN)| 
| 111 | 511 ADC Clock (25.55 µs times 2ALS_IR_ADC_GAIN)| 

### ALS_IR_ADC_GAIN
ALS可視測定のための、ADCの積分時間を設定。

| 項目  | アドレス | 
|:-:|:-:|
| ALS_IR_ADC_GAIN | 0x1E | 

| 値(bit)  | 周期 | 
|:--|:--|
| 000 | 1分割したADC Clock | 
| 100 | 16分割したADC Clock | 
| 110 | 64分割したADC Clock | 

### ALS_IR_ADC_MISC 

| 項目  | アドレス | 
|:-:|:-:|
| ALS_IR_ADC_MISC  | 0x1F | 


| 値(bit)  | 意味 | 
|:--|:--|
| 0 | Normal Signal Range | 
| 1 | High Signal Range  | 

### ALS_IR_ADCMUX 

Selects ADC Input for ALS_IR Measurement.

| 項目  | アドレス | 
|:-:|:-:|
| AUX_ADCMUX | 0x0E | 

| 値(bit)  | 周期 | 
|:--|:--|
| 0x00 |  Small IR photodiode | 
 
## IRを追加したソースコード


```cpp:arduino
#define SI1132_UCOEF0 0x13
#define SI1132_UCOEF1 0x14
#define SI1132_UCOEF2 0x15
#define SI1132_UCOEF3 0x16
#define SI1132_CHIPLIST 0x01
#define Si1132_MEASRATE0 0x08
#define SI1132_ALS_ENCODING 0x06
#define SI1132_ALS_VIS_ADC_COUNTER 0x10
#define SI1132_ALS_VIS_ADC_GAIN 0x11
#define SI1132_ALS_VIS_ADC_MISC 0x12
#define SI1132_ALS_IR_ADC_COUNTER 0x1D
#define SI1132_ALS_IR_ADC_GAIN 0x1E
#define SI1132_ALS_IR_ADC_MISC 0x1F
#define SI1132_ALS_IR_ADCMUX 0x0E

#define SI1132_EN_UV 0b10000000
#define SI1132_EN_AUX 0b01000000
#define SI1132_EN_ALS_IR 0b00100000
#define SI1132_EN_ALS_VIS 0b00010000

#define SI1132_ALS_VIS_ALIGN 0b00010000
#define SI1132_ALS_VIS_ALIGN 0b00100000

#define SI1132_1_ADC_CLOCK 0b00000000
#define SI1132_7_ADC_CLOCK 0b00010000
#define SI1132_15_ADC_CLOCK 0b00100000
#define SI1132_31_ADC_CLOCK 0b00110000
#define SI1132_63_ADC_CLOCK 0b01000000
#define SI1132_127_ADC_CLOCK 0b10100000
#define SI1132_255_ADC_CLOCK 0b01100000
#define SI1132_511_ADC_CLOCK 0b01110000

#define SI1132_1_DIVIDED_ADC_CLOCK 0b0000000
#define SI1132_16_DEVIDED_ADC_CLOCK 0b0000100
#define SI1132_64_DEVIDED_ADC_CLOCK 0b0000110

#define SI1132_NORMAL_SIGNAL_RANGE 0b00000000
#define SI1132_HIGH_SIGNAL_RANGE 0b00100000

#define SI1132_ALS_IR_ADCMUX_SMALLIR 0x00

void Configuration()
{
  writeI2c(SI1132_UCOEF0, 0x7B);
  writeI2c(SI1132_UCOEF1, 0x6B);
  writeI2c(SI1132_UCOEF2, 0x01);
  writeI2c(SI1132_UCOEF3, 0x00);

  int enable_sensor = SI1132_EN_UV|SI1132_EN_AUX|SI1132_EN_ALS_IR|SI1132_EN_ALS_VIS;
  writeI2c(SI1132_CHIPLIST, enable_sensor);

  // Rateの設定
  writeI2c(SI1132_CHIPLIST, 0xff);

  int flag_als_encoding = SI1132_ALS_VIS_ALIGN | SI1132_ALS_IR_ALIGN;
  writeI2c(SI1132_ALS_ENCODING, flag_als_encoding);
  
  // Visible
  writeI2c(SI1132_ALS_VIS_ADC_COUNTER, SI1132_511_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_GAIN, SI1132_1_DIVIDED_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_MISC, SI1132_HIGH_SIGNAL_RANGE);

  // IR
  writeI2c(SI1132_ALS_IR_ADC_COUNTER, SI1132_511_ADC_CLOCK);

  writeI2c(SI1132_ALS_IR_ADC_GAIN, SI1132_1_DIVIDED_ADC_CLOCK);

  writeI2c(SI1132_ALS_IR_ADC_MISC, SI1132_HIGH_SIGNAL_RANGE);

  writeI2c(SI1132_ALS_IR_ADCMUX, SI1132_ALS_IR_ADCMUX_SMALLIR);
}
```

## AUX

![config-aux.png](https://qiita-image-store.s3.amazonaws.com/0/63450/f4b8e4f5-b061-95e7-5fd5-8ce1fc32e341.png)

AUX_ADCMUXの設定からTemperatureもしくはVDDを選択し、AUX_DATAを生成する。

### AUX_ADCMUX
AUX MeasurementのInputを設定。

| 項目  | アドレス | 
|:-:|:-:|
| AUX_ADCMUX | 0x0F | 

| 値(bit)  | 周期 | 
|:--|:--|
| 0x65 | Temperature | 
| 0x75 | VDD | 

## IRを追加したソースコード


```cpp:arduino
#define SI1132_UCOEF0 0x13
#define SI1132_UCOEF1 0x14
#define SI1132_UCOEF2 0x15
#define SI1132_UCOEF3 0x16
#define SI1132_CHIPLIST 0x01
#define Si1132_MEASRATE0 0x08
#define SI1132_ALS_ENCODING 0x06
#define SI1132_ALS_VIS_ADC_COUNTER 0x10
#define SI1132_ALS_VIS_ADC_GAIN 0x11
#define SI1132_ALS_VIS_ADC_MISC 0x12
#define SI1132_ALS_IR_ADC_COUNTER 0x1D
#define SI1132_ALS_IR_ADC_GAIN 0x1E
#define SI1132_ALS_IR_ADC_MISC 0x1F
#define SI1132_ALS_IR_ADCMUX 0x0E
#define SI1132_AUX_ADCMUX 0x0F

#define SI1132_EN_UV 0b10000000
#define SI1132_EN_AUX 0b01000000
#define SI1132_EN_ALS_IR 0b00100000
#define SI1132_EN_ALS_VIS 0b00010000

#define SI1132_ALS_VIS_ALIGN 0b00010000
#define SI1132_ALS_VIS_ALIGN 0b00100000

#define SI1132_1_ADC_CLOCK 0b00000000
#define SI1132_7_ADC_CLOCK 0b00010000
#define SI1132_15_ADC_CLOCK 0b00100000
#define SI1132_31_ADC_CLOCK 0b00110000
#define SI1132_63_ADC_CLOCK 0b01000000
#define SI1132_127_ADC_CLOCK 0b10100000
#define SI1132_255_ADC_CLOCK 0b01100000
#define SI1132_511_ADC_CLOCK 0b01110000

#define SI1132_1_DIVIDED_ADC_CLOCK 0b0000000
#define SI1132_16_DEVIDED_ADC_CLOCK 0b0000100
#define SI1132_64_DEVIDED_ADC_CLOCK 0b0000110

#define SI1132_NORMAL_SIGNAL_RANGE 0b00000000
#define SI1132_HIGH_SIGNAL_RANGE 0b00100000

#define SI1132_ALS_IR_ADCMUX_SMALLIR 0x00

#define SI1132_AUX_ADCMUX_TEMPERATURE 0x65
#define SI1132_AUX_ADCMUX_VDD 0x75

#define SI1132_COMMAND 0x18
#define SI1132_COMMAND_ALS_AUTO 0x0E

void Configuration()
{
  writeI2c(SI1132_UCOEF0, 0x7B);
  writeI2c(SI1132_UCOEF1, 0x6B);
  writeI2c(SI1132_UCOEF2, 0x01);
  writeI2c(SI1132_UCOEF3, 0x00);

  int enable_sensor = SI1132_EN_UV|SI1132_EN_AUX|SI1132_EN_ALS_IR|SI1132_EN_ALS_VIS;
  writeI2c(SI1132_CHIPLIST, enable_sensor);

  int flag_als_encoding = SI1132_ALS_VIS_ALIGN | SI1132_ALS_IR_ALIGN;
  writeI2c(SI1132_ALS_ENCODING, flag_als_encoding);
  
  // Visible
  writeI2c(SI1132_ALS_VIS_ADC_COUNTER, SI1132_511_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_GAIN, SI1132_1_DIVIDED_ADC_CLOCK);

  writeI2c(SI1132_ALS_VIS_ADC_MISC, SI1132_HIGH_SIGNAL_RANGE);

  // IR
  writeI2c(SI1132_ALS_IR_ADC_COUNTER, SI1132_511_ADC_CLOCK);

  writeI2c(SI1132_ALS_IR_ADC_GAIN, SI1132_1_DIVIDED_ADC_CLOCK);

  writeI2c(SI1132_ALS_IR_ADC_MISC, SI1132_HIGH_SIGNAL_RANGE);

  writeI2c(SI1132_ALS_IR_ADCMUX, SI1132_ALS_IR_ADCMUX_SMALLIR);

  // AUX
  writeI2c(SI1132_ALS_IR_ADC_GAIN, SI1132_AUX_ADCMUX_TEMPERATURE);

  // COMMAND
  writeI2c(SI1132_COMMAND, SI1132_COMMAND_ALS_AUTO);
}
```


# RESET

| 項目  | アドレス | 
|:-:|:-:|
| COMMAND | 0x18 | 
 
| コマンド  | 値(Bit) | 
|:-:|:-:|
| RESET | 00000001 |

```cpp:arduino
#define SI1132_COMMAND_RESET 0b00000001
#define SI1132_COMMAND 0x18

void Reset()
{
  writeI2c(SI1132_COMMAND, SI1132_COMMAND_RESET);
}
```

# UV Indexの読み取り

```cpp:arduino
#define SI1132_AUX_DATA 0x2C

void ReadUV()
{
  uint16_t uv_index;
  uint8_t buffer[2];

  readI2c(SI1132_AUX_DATA, 2, buffer);
  uv_index = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  return uv_index;
}
```

# IRの読み取り

```cpp:arduino
#define SI1132_IR_DATA 0x24

void ReadIR()
{
  uint16_t ir;
  uint8_t buffer[2];

  readI2c(SI1132_IR_DATA, 2, buffer);
  ir = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  return ir;
}
```

# Visibleの読み取り

```cpp:arduino
#define SI1132_IR_DATA 0x22

void ReadIR()
{
  uint16_t visible;
  uint8_t buffer[2];

  readI2c(SI1132_AUX_DATA, 2, buffer);
  visible = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  return visible;
}
```

# I2Cのアクセス用コード

```cpp:Arduino
#define HTS221_SLAVE_ADDRESS 0x5F

// I2Cへの書き込み
void writeI2c(byte register_addr, byte value) {
  Wire.beginTransmission(HTS221_SLAVE_ADDRESS);  
  Wire.write(register_addr);         
  Wire.write(value);                 
  Wire.endTransmission();        
}

// I2Cへの読み込み
void readI2c(byte register_addr, int num, byte *buf) {
  Wire.beginTransmission(HTS221_SLAVE_ADDRESS); 
  Wire.write(register_addr);           
  Wire.endTransmission(false);         

  //Wire.beginTransmission(DEVICE_ADDR); 
  Wire.requestFrom(HTS221_SLAVE_ADDRESS, num);  

  int i = 0;
  while (Wire.available())
  {
    buf[i] = Wire.read(); 
    i++;   
  }
  //Wire.endTransmission();         
}
```