0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【電子工作】I2C対応カラーセンサー S13683-03DTで色判定モジュールを自作

0
Last updated at Posted at 2026-03-16

はじめに

いつか別の記事にしたいと思っていますが、最近ミニ四駆の改造をしています。
その一環としてカラーセンサーが必要になりました。

使用部品

回路図

カラーセンサー:

  • センサのピン配置は、データシートを参考に、受光部の向きに注意して配線します。
  • I2C通信はオープン・コレクタ方式なので、プルアップ抵抗が必要です。
    センサ内部のトランジスタが接地$\rightarrow$"Low", オープン$\rightarrow$3.3Vで"High"になります。
  • ArduinoはI2C用のピンが指定されています。SDAはA4、SCLはA5です。
  • 中央の3本のピンはGNDにつながっているので、半田づけの際は短絡しないよう注意。

その他

  • 白色LEDの反射光の色を検出するために、LEDは30度ほど傾けています。
  • センサの裏側に抵抗を配置しています。

※とても雑な図ですみません泣
FB5A618F-23BF-4AE7-8C4A-1F8FD4253BAC.jpg

プログラム

AIに書かせたので全然わかっていないです。修正したほうがいいところがあれば教えてほしいです。

上手く動かなかくて修正した部分を挙げます。

  • const int S13683_ADDR = 0x2A;
    I2C通信ではマスタ(Arduino)からセンサーにスレーブと呼ばれる通信開始の合図を出します。アドレスはデバイスごとに異なります。特に今回のセンサのアドレスはレア(?)らしいので注意。データシートを確認しましょう。
  • 色判定の補正係数は自分で修正する必要があります。
    特に以下の二か所:
    1.実データに乗算する補正係数
    float k_r = 1.0;
    float k_g = 0.7; 
    float k_b = 1.0;
    
    2.色の閾値の設定
    r_final > g_final * 1.3 && r_final > b_final * 1.3
    
    b_final > g_final * 1.3 && b_final > r_final * 1.3
    
  • その他、必要であれば積分時間など微調節してください。

コード全体

ColorSensor.ino
#include <Wire.h>

const int S13683_ADDR = 0x2A;

// --- 補正係数適当な初期値白路面で 'c' を送信すると自動更新される ---
float k_r = 1.0;
float k_g = 0.7; 
float k_b = 1.0;

void setup() {
  Wire.begin();
  Serial.begin(115200); // 高速通信のため115200bps推奨
  delay(100);

  // 1. ミニ四駆向けの高速応答設定積分時間 1.4ms/ch
  writeReg(0x00, 0x89); // ADCリセット(Bit7=1) + High Gain + 1.4ms
  delay(10); 
  writeReg(0x00, 0x09); // ADC動作開始(Bit7=0)
  
  delay(10); // 初回のデータ更新を待つ
  Serial.println("Mini4WD Color Sensor Ready.");
}

void loop() {
  // --- キャリブレーション処理シリアルモニタから 'c' を受信した時 ---
  if (Serial.available() > 0) {
    char cmd = Serial.read();
    if (cmd == 'c' || cmd == 'C') {
      calibrate();
    }
  }

  // --- センサーからデータ読み出し ---
  Wire.beginTransmission(S13683_ADDR);
  Wire.write(0x03); 
  Wire.endTransmission(false);
  Wire.requestFrom(S13683_ADDR, 8);
  
  if (Wire.available() == 8) {
    // Highバイト -> Lowバイトの順で結合
    uint16_t r_raw = (Wire.read() << 8) | Wire.read();
    uint16_t g_raw = (Wire.read() << 8) | Wire.read();
    uint16_t b_raw = (Wire.read() << 8) | Wire.read();
    uint16_t comp  = (Wire.read() << 8) | Wire.read();

    // 赤外迷光成分の減算マイナスになる場合は0に丸める
    int32_t r_c = (int32_t)r_raw - comp;
    int32_t g_c = (int32_t)g_raw - comp;
    int32_t b_c = (int32_t)b_raw - comp;
    r_c = (r_c < 0) ? 0 : r_c;
    g_c = (g_c < 0) ? 0 : g_c;
    b_c = (b_c < 0) ? 0 : b_c;

    // 係数を掛けて最終的なRGB値を算出
    float r_final = r_c * k_r;
    float g_final = g_c * k_g;
    float b_final = b_c * k_b;

    // --- 色の簡易判定ロジック ---
    // 光量が少なすぎる場合はコース外または影と判定
    float total_light = r_final + g_final + b_final;
    String detected_color = "UNKNOWN";

    if (total_light < 50) {
      detected_color = "BLACK/OUT";
    } else {
      // RGBの中で一番強い成分を見る白の場合はRGBがほぼ均等に高くなる
      if (r_final > g_final * 1.3 && r_final > b_final * 1.3) {
        detected_color = "RED";
      } else if (b_final > g_final * 1.3 && b_final > r_final * 1.3) {
        detected_color = "BLUE";
      } else {
        detected_color = "WHITE (STRAIGHT)";
      }
    }

    // --- 結果の出力 ---
    Serial.print("R:"); Serial.print(r_final, 0);
    Serial.print("\tG:"); Serial.print(g_final, 0);
    Serial.print("\tB:"); Serial.print(b_final, 0);
    Serial.print("\t-> "); Serial.println(detected_color);
  }

  // 1.4ms * 4ch = 5.6ms の更新周期に合わせて待機
  delay(10); 
}

// レジスタ書き込み用ヘルパー
void writeReg(byte reg, byte val) {
  Wire.beginTransmission(S13683_ADDR);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission();
}

// キャリブレーション実行用関数
void calibrate() {
  Wire.beginTransmission(S13683_ADDR);
  Wire.write(0x03); 
  Wire.endTransmission(false);
  Wire.requestFrom(S13683_ADDR, 8);
  
  if (Wire.available() == 8) {
    uint16_t r_raw = (Wire.read() << 8) | Wire.read();
    uint16_t g_raw = (Wire.read() << 8) | Wire.read();
    uint16_t b_raw = (Wire.read() << 8) | Wire.read();
    uint16_t comp  = (Wire.read() << 8) | Wire.read();

    int32_t r_c = max(0, (int32_t)r_raw - comp);
    int32_t g_c = max(0, (int32_t)g_raw - comp);
    int32_t b_c = max(0, (int32_t)b_raw - comp);

    if (r_c > 0 && b_c > 0) {
      k_r = (float)g_c / r_c;
      k_b = (float)g_c / b_c;
      Serial.println("\n*** CALIBRATION COMPLETED ***");
      Serial.print("New k_r: "); Serial.println(k_r);
      Serial.print("New k_b: "); Serial.println(k_b);
      Serial.println("*****************************\n");
    }
  }
}

動作

動画の載せ方が分からないので、後日追記しておきます。

青い物体から赤色の物体にセンサをスライドさせたときのSerial Monitorの出力は以下のようになります。
色判定のアルゴリズムは使用環境に応じて調節する必要があります。
データシートに記載の通り、使用したLEDは青と緑の強度が高く、センサは赤と緑の感度が高いです。そのため、今回は色判定時の緑の重みを小さくしています。

Serial Monitor
R:48	G:85	B:114	-> BLUE
R:48	G:84	B:113	-> BLUE
R:48	G:84	B:112	-> BLUE
R:47	G:83	B:111	-> BLUE
R:47	G:82	B:110	-> BLUE
R:47	G:81	B:110	-> BLUE
R:47	G:81	B:108	-> BLUE
R:48	G:80	B:105	-> BLUE
R:48	G:80	B:104	-> BLUE
R:47	G:78	B:102	-> BLUE
R:46	G:76	B:98	-> WHITE (STRAIGHT) 
R:48	G:75	B:96	-> WHITE (STRAIGHT)
R:49	G:73	B:92	-> WHITE (STRAIGHT)
R:48	G:71	B:87	-> WHITE (STRAIGHT)
R:47	G:67	B:81	-> WHITE (STRAIGHT)
R:48	G:64	B:77	-> WHITE (STRAIGHT)
R:48	G:62	B:72	-> WHITE (STRAIGHT)
R:50	G:61	B:68	-> WHITE (STRAIGHT)
R:0	G:0	B:0	-> BLACK/OUT
R:56	G:58	B:60	-> WHITE (STRAIGHT)
R:59	G:57	B:57	-> WHITE (STRAIGHT)
R:65	G:56	B:54	-> WHITE (STRAIGHT)
R:71	G:59	B:54	-> WHITE (STRAIGHT)
R:77	G:62	B:55	-> WHITE (STRAIGHT)
R:81	G:63	B:53	-> WHITE (STRAIGHT)
R:83	G:62	B:51	-> RED
R:84	G:61	B:50	-> RED
R:86	G:62	B:50	-> RED
R:86	G:61	B:48	-> RED
R:87	G:61	B:48	-> RED
R:86	G:60	B:47	-> RED
R:86	G:60	B:46	-> RED
R:86	G:60	B:47	-> RED
R:86	G:60	B:47	-> RED
R:85	G:58	B:46	-> RED
R:84	G:58	B:46	-> RED
R:83	G:57	B:46	-> RED
R:83	G:58	B:46	-> RED
R:82	G:57	B:45	-> RED
R:81	G:56	B:45	-> RED
R:81	G:57	B:46	-> RED
R:80	G:56	B:45	-> RED
R:81	G:57	B:46	-> RED
R:82	G:57	B:45	-> RED
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?