Arduino IDE

Поскольку датчик умеет работать только по I2C интерфейсу, подключаем его по стандартной в таких случаях схеме.

Arduino+5VGNDSDASCL
Датчик цвета TCS34725 ROCVINGND SDA SCL

При использовании беспаечной пакетной платы понадобится 4 соединительных провода вилка-вилка.

Управление встроенной подсветкой

Как уже говорилось, на плате есть белый светодиод, который нужен в случае недостатки фонового освещения или когда спектр этого освещения неподходящий.

Если подать питание на плату, то светодиод зажжется. Однако, есть три варианта, как им управлять:

  1. подключить контакт LE к земле (GND), тогда светодиод постоянно будет выключен;
  2. подключить LE к любому цифровому контакту Ардуино и управлять им с помощью digitalWrite. При этом, подавая сигнал LOW мы будем его выключать, а HIGH — включать;
  3. подключить LE к контакту INT на самом модуле датчик и управлять с помощью функции setInterrupt из библиотеки модуля.

Программа: RGB тест

Для работы с модулем на понадобится библиотека Adafruit TCS34725. Устанавливаем её из менеджера библиотек Arduino IDE.

Первая программа будет выводить в последовательный порт RGB компоненты, которые датчик видит перед собой.

#include "Adafruit_TCS34725.h"
// создаём объект для работы с модулем, указываем настройки

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

void setup() {
    Serial.begin(9600); // запускаем обмен по последовательному порту
    tcs.begin(); // активируем датчик
    delay(60);  // ждём 60 мс, пока датчик собирает первые данные
}
void loop() {
    float red, green, blue;

    tcs.getRGB(&red, &green, &blue); // запрашиваем у датчика цветовые компоненты

    // вывод RGB компонентов в последовательный порт
    Serial.print("R:\t"); Serial.print(int(red)); 
    Serial.print("\tG:\t"); Serial.print(int(green)); 
    Serial.print("\tB:\t"); Serial.print(int(blue));
    Serial.print("\n");

    delay(60);  // ждём 60 мс, пока датчик собирает новые данные
}

Загружаем программу на плату и открываем монитор COM-порта. Теперь, для эксперимента, стоит поднести к датчику объекты разных насыщенных цветов. Во избежание попадания на датчик нежелательной засветки лучше приблизить предмет в упор. Смотрим на показания датчика:

Похоже, было что-то очень синее, ведь значение компонента B сильно больше остальных.

Программа: TCS34725 и RGB-светодиод

Вот бы вместо цифр, какой-нибудь цветной индикатор. Что, если цветовые компоненты каким-то образом преобразовать и передать на RGB светодиод? Попробуем.

Для работы этой программы необходимо подключить к контроллеру RGB светодиод. Например, матовый светодиод D=10мм с общим катодом. Подключим его к контактам 11, 10 и 9, на которых возможна генерация ШИМ сигнала с помощью команды analogWrite.

Исходный код

#include <Wire.h>
#include "Adafruit_TCS34725.h"

// контакты RGB светодиода
const byte redPin = 11;
const byte greenPin = 10;
const byte bluePin = 9;

byte gammatable[256]; // таблица гамма-коррекции
float ltc[3] = {1, 0.95, 0.75}; // коэффициенты коррекции цветовой температуры

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);

void setup() {
    Serial.begin(9600);

    tcs.begin(); // активируем датчик

    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);

    // заполняем таблицу гамма-коррекции
    for (int i=0; i<256; i++) {
        float x = i;
        x /= 255;
        x = pow(x, 2.5);
        x *= 255;

        gammatable[i] = x;
    }
}

void loop() {
    float red, green, blue;
  
    delay(60); // пауза 60мс, чтобы дать время датчику подготовить данные

    tcs.getRGB(&red, &green, &blue); // получаем RGB компоненты из датчика

    // выводим значения RGB компонент в порт
    Serial.print("R:\t"); Serial.print(int(red)); 
    Serial.print("\tG:\t"); Serial.print(int(green)); 
    Serial.print("\tB:\t"); Serial.print(int(blue));
    Serial.print("\n");

    // задаём ШИМ для отдельных цветов RGB светодиода
    analogWrite( redPin, gammatable[ (int)(red*ltc[0]) ]);
    analogWrite( greenPin, gammatable[ (int)(green*ltc[1]) ]);
    analogWrite( bluePin, gammatable[ (int)(blue*ltc[2]) ]);
}

В этом коде есть два момента, которые следует пояснить.

Первый — гамма-коррекция. Это такое преобразование цветовых компонент, которое позволяет регулировать яркость светодиода для лучшего восприятия нашими глазами.

Второй — коррекция цветовой температуры. В данном модуле мы устанавливаем белый светодиод с цветовой температурой 6000К. Чтобы снизить влияние дисбаланса этого светодиода в сторону синей компоненты, мы применяем коэффициенты коррекции. Эти коэффициенты легко вычислить, если положить перед датчиком чистый белый предмет и убрать постороннее освещение.

Программа: детектор цвета с OLED дисплеем

Наконец, самая продвинутая программа в этом уроке — детектор цвета. В действительности, именно в этой программе рассмотрен самый распространённый сценарий использования подобных датчиков. Мы не будем пытаться отобразить увиденный датчиком цвет. Вместо этого, запомним некоторые конкретные цвета и затем попробуем их определить.

Алгоритм работы программы:

  1. просим пользователя показать красный цвет
  2. ждём пока пользователь не нажмёт кнопку, затем сразу определяем цвет и сохраняем RGB компоненты
  3. повторяем то же самое для зелёного и синего цветов
  4. просим пользователя показать любой цвет
  5. проверяем все сохранённые цвета на соответствие предъявленному
  6. если обнаружено совпадение, выводим название этого цвета

Для общения с пользователем добавим в наш стенд OLED-дисплей и самую обычную тактовую кнопку.

Исходный код

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Adafruit_TCS34725.h"

#define RED 0
#define GREEN 1
#define BLUE 2

// погрешность при определении цвета
#define TOLERANCE 16

// контакт кнопки
const byte selectPin = 12;

int colors[3][3]; // массив для запоминания цветов
char *color_names[3] = {"RED","GREEN","BLUE"}; // имена цветов для вывода на дисплей

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
Adafruit_SSD1306 display(128, 64, &Wire, 4);

void saveColor( byte color ){
    float red, green, blue;

    delay(60); // пауза 60мс, чтобы дать время датчику подготовить данные

    tcs.getRGB(&red, &green, &blue); // получаем RGB компоненты из датчика

    // сохраняем три цветовых компонента в массив
    colors[color][RED] = (int)red;
    colors[color][GREEN] = (int)green;
    colors[color][BLUE] = (int)blue;
}

byte detectColor(){
    float red, green, blue;

    delay(60); // пауза 60мс, чтобы дать время датчику подготовить данные

    tcs.getRGB(&red, &green, &blue); // получаем RGB компоненты из датчика

    byte color = 255;
    // перебираем все три запомненных цвета
    // и проверяем на совпадение с учетом погрешности
    for(byte i=0; i<3; i++){
        if(abs(red-colors[i][RED])<TOLERANCE &&
           abs(green-colors[i][GREEN])<TOLERANCE &&
           abs(blue-colors[i][BLUE])<TOLERANCE){
            color = i;
            break;
           }
    }

    return color;
}

void setup() {
    tcs.begin(); // активируем датчик
    display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // активируем дисплей

    pinMode(selectPin, INPUT_PULLUP);

    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);

    // по очереди просим пользователя
    // поднести объекты разных цветов для запоминания
    for(byte i=0; i<3; i++){
        display.clearDisplay();
        display.setCursor(35, 31);
        display.print(F("Show "));
        display.println(color_names[i]);
        display.display();

        while( digitalRead(selectPin) ){
            // ждём нажатия кнопки
        }
        saveColor(i);

        display.clearDisplay();
        display.setCursor(35, 31);
        display.println(F("OK!"));
        display.display();

        delay(1000);
    }
}

void loop() {
    display.clearDisplay();
    display.setCursor(25, 31);
    display.println(F("Show any color"));
    display.display();

    while( digitalRead(selectPin) ){
        // ждём нажатия кнопки
    }

    byte color = detectColor();

    display.clearDisplay();
    display.setCursor(35, 31);
    
    if( color == 255 ){
        display.print(F("Bad color")); // если цвет не определился
    } else {
        display.print(F("Color is "));
        display.println(color_names[color]);
    }
    display.display();

    delay(5000);
}

Изменено: