Arduino IDE
Поскольку датчик умеет работать только по I2C интерфейсу, подключаем его по стандартной в таких случаях схеме.
Arduino | +5V | GND | SDA | SCL |
Датчик цвета TCS34725 ROC | VIN | GND | SDA | SCL |
При использовании беспаечной пакетной платы понадобится 4 соединительных провода вилка-вилка.
Управление встроенной подсветкой
Как уже говорилось, на плате есть белый светодиод, который нужен в случае недостатки фонового освещения или когда спектр этого освещения неподходящий.
Если подать питание на плату, то светодиод зажжется. Однако, есть три варианта, как им управлять:
- подключить контакт LE к земле (GND), тогда светодиод постоянно будет выключен;
- подключить LE к любому цифровому контакту Ардуино и управлять им с помощью digitalWrite. При этом, подавая сигнал LOW мы будем его выключать, а HIGH — включать;
- подключить 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 дисплеем
Наконец, самая продвинутая программа в этом уроке — детектор цвета. В действительности, именно в этой программе рассмотрен самый распространённый сценарий использования подобных датчиков. Мы не будем пытаться отобразить увиденный датчиком цвет. Вместо этого, запомним некоторые конкретные цвета и затем попробуем их определить.
Алгоритм работы программы:
- просим пользователя показать красный цвет
- ждём пока пользователь не нажмёт кнопку, затем сразу определяем цвет и сохраняем RGB компоненты
- повторяем то же самое для зелёного и синего цветов
- просим пользователя показать любой цвет
- проверяем все сохранённые цвета на соответствие предъявленному
- если обнаружено совпадение, выводим название этого цвета
Для общения с пользователем добавим в наш стенд 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);
}