ソースに絡まるエスカルゴ

貧弱プログラマの外部記憶装置です。

【Arduino】Seeed Studio XIAO ESP32C3で色センサーを使ってみる

 かなり前の記事でXIAO ESP32C3の環境構築の記事を書きました。

 小さいし高性能なので久々に引っ張り出して何かやってみようと思っていたところ、S11059-02DTという色センサーを見つけました。
 今回はXIAO ESP32C3でその色センサーを使ってみた備忘録になります。


 では、始めます。


1:準備するもの
 今回準備したものは以下の通りです。  


2:回路図
 以下のような回路図を作ります。今回の色センサーはI2Cを使うため、SDAとSCLを使っています。またこの時色センサーの真上に赤色LEDが来るように配置してください。


3:サンプルスケッチの実行
 回路図ができたら以下のサンプルスケッチを作成し、XIAO ESP32C3に書き込んでみてください。

・XIAO_ESP32C3_color_sensor.ino

/**
 * デジタルカラーセンサモジュール(S11059-02DT)のテスト
 */
#include <Wire.h>

// カラーセンサのアドレス
#define SENSOR_ADDRESS 0x2A
// カラーセンサのコントロール
#define CONTROL_MSB 0x00
// カラーセンサの出力バイト数
#define OUTPUT_BYTES_NUM 0x03
// カラーセンサのADCリセット(HIGHゲイン)
#define ADC_RESET 0x89
// カラーセンサのバスリリース(HIGHゲイン)
#define BUS_RELEASE 0x09

const int LED_PIN = D10;


void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("setup start!");
  pinMode(LED_PIN, OUTPUT);

  // I2Cの準備
  setupI2c();
  // LED点灯
  digitalWrite(LED_PIN, HIGH);

  Serial.println("setup end!");
}

bool is_on = true;
int count = 0;

void loop() {
  // 色センサーの値を取得して表示
  getSensorVal();
  count++;
  delay(500);

  if (count % 10 == 0) {
    is_on = !is_on;
    digitalWrite(LED_PIN, is_on);
    Serial.print("LED: ");
    Serial.println(is_on);
    count = 0;
  }
}

// 色センサのI2Cの準備をする関数
void setupI2c() {
  // I2C開始
  Wire.begin(SDA, SCL);

  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(CONTROL_MSB); // コントロールバイトを指定
  Wire.write(ADC_RESET);   // ADCリセット、スリープ解除
  Wire.endTransmission();

  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(CONTROL_MSB); // コントロールバイトを指定
  Wire.write(BUS_RELEASE); // ADCリセット解除、バスリリース
  Wire.endTransmission();
}

// 色センサの各値を取得して表示する関数
void getSensorVal() {
  int high_byte = 0;
  int low_byte = 0;
  int red = 0;
  int green = 0;
  int blue = 0;
  int IR = 0;

  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(OUTPUT_BYTES_NUM); //出力データバイト(ここでは8byte)を設定
  Wire.endTransmission();

  // 8Byteのデータ要求
  Wire.requestFrom(SENSOR_ADDRESS, 8);

  if (Wire.available()) {
    // 赤色のhigh_byteとlow_byteを読み込み結合して値を取得
    high_byte = Wire.read();
    low_byte = Wire.read();
    red = high_byte << 8|low_byte;
  
    // 緑色のhigh_byteとlow_byteを読み込み結合して値を取得
    high_byte = Wire.read();
    low_byte = Wire.read();
    green = high_byte << 8|low_byte;

    // 青色のhigh_byteとlow_byteを読み込み結合して値を取得
    high_byte = Wire.read();
    low_byte = Wire.read();
    blue = high_byte << 8|low_byte;

    // 赤外線のhigh_byteとlow_byteを読み込み結合して値を取得
    high_byte = Wire.read();
    low_byte = Wire.read();
    IR = high_byte << 8|low_byte;
  }

  Wire.endTransmission();

  // 取得した各値をSerialに表示
  Serial.print("r: ");
  Serial.print(red);
  Serial.print(" g: ");
  Serial.print(green);
  Serial.print(" b: ");
  Serial.print(blue);
  Serial.print(" IR: ");
  Serial.print(IR);
  Serial.println("");
}

 スケッチについての詳細はデータシートや参考資料に挙げているページ様を参照していただきたいのですが、このS11059-02DTの色センサーにはHIGHゲインモードとLOWゲインモードという2種類のモードがあります。

 これらモードは受光部分のセンサの数が違っており、LOWゲインは4セル分しか使わず、HIGHゲインは40セル分をフルで使うという違いがあります。
 LOWゲインとHIGHゲインはサンプルスケッチでいう定数の「ADC_RESET」と「BUS_RELEASE」の値を書き換えることで切り替えることができます。

 一度LOWゲインでも試しましたが、光を全然捉えられていないのか、色センサーから読み取る値がほとんど変化しないという感じだったため、サンプルスケッチではHIGHゲインの方を採用しています。

 実際に書き込んで動作させてみると、D10に繋いだ赤色のLEDが5秒間隔程度で点滅します。

 またシリアルモニタで確認してみると、以下のようにr, g, b, IRの4つの項目のセンサの値が表示されます。

15:19:57.146 -> LED: 0
15:19:57.146 -> r: 39 g: 57 b: 41 IR: 8
15:19:57.661 -> r: 48 g: 58 b: 34 IR: 7
15:19:58.146 -> r: 39 g: 59 b: 42 IR: 7
15:19:58.646 -> r: 49 g: 72 b: 42 IR: 7
15:19:59.146 -> r: 49 g: 59 b: 34 IR: 6
15:19:59.657 -> r: 49 g: 72 b: 42 IR: 7
15:20:00.172 -> r: 49 g: 59 b: 33 IR: 6
15:20:00.654 -> r: 39 g: 55 b: 39 IR: 8
15:20:01.138 -> r: 44 g: 68 b: 45 IR: 7
15:20:01.639 -> r: 52 g: 68 b: 38 IR: 6

 ちゃんと色センサーの部分に赤色LEDの光が当たっている場合、赤色LEDが点灯している時にはrの値が高くなり、消灯している時にはrの値が低くなっていることがわかるかと思います。


 以上がXIAO ESP32C3でS11059-02DTの色センサーを使ってみた内容になります。

 どの程度正確に色が取得できているかはわかりませんが、なんとなく赤が強め、青が強めなどある程度の色によって処理を変えることは可能だと思います。
 また今回はXIAO ESP32C3を使いましたが、I2Cを使えるものであれば別のマイコンボードでも問題なく使えると思うので、割といろいろなことに応用できそうです。


・参考資料