【M5】M5Stackとカラーセンサユニット[U009]で色判別を試す

システム・インフラ

構成

  • 本体: M5Stack Basic / Core
  • センサ: カラーセンサユニット [U009] (TCS34725搭載)
  • 接続: Port A (I2C)

準備

本プログラムでは、Adafruit製のTCS34725ライブラリを使用します。

  1. GitHubから Adafruit_TCS34725 をダウンロード。
  2. Adafruit_TCS34725.hAdafruit_TCS34725.cpp を .ino ファイルと同じフォルダに配置します。

プログラム

Partition SchemeNo OTA に設定して書き込んでください。

//********************************************************
// Project : カラーセンサテストプログラム
// Device  : M5Stack-Core-ESP32
// Created : 2023.07.27
// Update  : 2024.03.14
//********************************************************
#include <Wire.h>
#include <M5Stack.h>
#include "Adafruit_TCS34725.h"

// 16bitカラー(RGB565)変換関数
static uint16_t color16(uint16_t r, uint16_t g, uint16_t b) {
  uint16_t _color;
  _color  = (uint16_t)(r & 0xF8) << 8;
  _color |= (uint16_t)(g & 0xFC) << 3;
  _color |= (uint16_t)(b & 0xF8) >> 3;
  return _color;
}

// 積分時間とゲインの設定
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

float maxv, minv, h, s, v;

void setup() {
  delay(100);
  M5.begin(true, false, false); // LCD, SD, Serial
  M5.Power.begin();
  
  M5.Lcd.setTextSize(2);
  
  // センサー初期化チェック
  while(!tcs.begin()){
    M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);
    M5.Lcd.setCursor(0, 60);
    M5.Lcd.print("Sensor not found");     
    delay(1000);
  }

  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 10);
  M5.Lcd.print("Color Sensor Test");

  tcs.setIntegrationTime(TCS34725_INTEGRATIONTIME_154MS);
  tcs.setGain(TCS34725_GAIN_4X);
}

void loop() {
  M5.update();
  
  uint16_t clear, red, green, blue;
  delay(60);     
  tcs.getRawData(&red, &green, &blue, &clear); 

  // RGB比率計算
  uint32_t sum = clear;
  if (sum == 0) sum = 1; // ゼロ除算防止
  int r = red   * 256 / sum;
  int g = green * 256 / sum;
  int b = blue  * 256 / sum;

  M5.Lcd.setCursor(0, 26);
  M5.Lcd.printf("Clear: %3d\n", clear);
  M5.Lcd.printf("Red  : %3d (%3d) \n", red,   r);
  M5.Lcd.printf("Green: %3d (%3d) \n", green, g);
  M5.Lcd.printf("Blue : %3d (%3d) \n", blue,  b);

  // HSV変換処理
  maxv = max(max(r, g), b);
  minv = min(min(r, g), b);
  h = maxv - minv;

  if (h > 0) {
    if (maxv == r)      h = 60.0 * (g - b) / h;
    else if (maxv == g) h = 60.0 * (b - r) / h + 120.0;
    else                h = 60.0 * (r - g) / h + 240.0;
    if (h < 0)          h += 360.0;
  }

  s = (maxv == 0) ? 0 : (maxv - minv) / maxv * 255;
  v = (maxv / 255.0) * 100.0;

  M5.Lcd.printf("h : %3.1f s : %3.1f v : %3.1f\n", h, s, v);

  // 色判定ロジック
  M5.Lcd.setCursor(0, 120);
  if (s < 100) {
    M5.Lcd.print("WHITE ");
  } else if (v < 40) {
    M5.Lcd.print("DARK  ");
  } else {
    if (h < 60 || h >= 300) M5.Lcd.print("RED   ");
    else if (h < 180)       M5.Lcd.print("GREEN ");
    else                    M5.Lcd.print("BLUE  ");
  }

  // カラーボックス表示
  uint16_t boxcolor = color16(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b);
  M5.Lcd.fillRect(60, 160, 200, 60, boxcolor); 
}

注意事項

  • ゼロ除算の考慮: sum が 0 の場合に r = red * 256 / sum でエラー(フリーズ)になる可能性があるため、if (sum == 0) sum = 1; などの処理を入れるとより安全です。
  • 色判定の閾値: 周囲の明るさ(環境光)によって h, s, v の値はかなり変動します。

コメント