Подключение датчика цвета TCS230/TCS3200 к Arduino
Датчики цвета предоставляют более надёжные решения для сложных задач автоматизации. Они используются в различных отраслях, включая пищевую, автомобильную и производственную промышленность, для таких целей, как обнаружение материалов, определение цветных меток на деталях, проверка этапов производственного процесса и так далее.
В то время как дорогие датчики цвета используются в промышленных приложениях, недорогие датчики, такие как TCS230, можно использовать для менее требовательных задач.
Датчик цвета TCS230 (также выпускаемый под маркой TCS3200) довольно популярен, недорог и прост в использовании. Прежде чем использовать этот датчик цвета в нашем проекте на Arduino, давайте разберёмся, как вообще работает датчик цвета.
Как работают датчики цвета
Белый свет состоит из трёх основных цветов (красного, зелёного и синего), которые имеют различные длины волн. Эти цвета комбинируются друг с другом, образуя различные оттенки.
Когда белый свет падает на любую поверхность, некоторые длины волн поглощаются, а некоторые отражаются, в зависимости от свойств материала поверхности. Цвет, который мы видим, является результатом того, какие длины волн отражаются обратно в наши глаза.
Теперь вернёмся к датчику. Типичный датчик цвета содержит яркий белый светодиод, который проецирует модулированный свет на объект. Для определения цвета отражённого света почти все датчики цвета состоят из сетки цветочувствительных фильтров, также известных как «фильтр Байера», и массива фотодиодов под ними, как показано на рисунке ниже.
Один пиксель состоит из 4 фильтров: одного красного, одного синего, одного зелёного и одного прозрачного (без фильтра). Этот шаблон также известен как «шаблон Байера». Каждый фильтр пропускает свет только одного цвета к фотодиоду под ним, а прозрачный фильтр пропускает свет как есть, как показано ниже. Этот дополнительный свет, проходящий через прозрачный фильтр, является большим преимуществом в условиях низкой освещённости.
Обрабатывающий чип затем обращается к каждому фотодиоду (по одному цвету за раз) и измеряет интенсивность света. Поскольку существует массив фотодиодов, результаты сначала усредняются, а затем отправляются на обработку. Путём измерения относительного уровня красного, зелёного и синего света определяется цвет объекта.
Модуль датчика цвета TCS230
В основе модуля лежит недорогой RGB-сенсорный чип от Texas Advanced Optoelectronic Solutions — TCS230. Датчик цвета TCS230 представляет собой полноценный детектор цвета, способный обнаруживать и измерять практически бесконечный диапазон видимых цветов.
Сам датчик расположен в центре модуля и окружён четырьмя белыми светодиодами. Светодиоды загораются при подаче питания на модуль и используются для освещения объекта. Благодаря этим светодиодам датчик может работать даже в полной темноте для определения цвета или яркости объекта.
TCS230 работает от напряжения питания от 2.7 до 5.5 вольт и обеспечивает выходные сигналы TTL-уровня.
Принцип работы TCS230
TCS230 определяет цвет с помощью массива из 8 x 8 фотодиодов, из которых 16 фотодиодов имеют красные фильтры, 16 — зелёные, 16 — синие, а оставшиеся 16 — прозрачные (без фильтров).
Если вы внимательно посмотрите на датчик, то сможете увидеть эти фильтры.
Каждые 16 фотодиодов соединены параллельно, поэтому с помощью двух управляющих выводов S2 и S3 вы можете выбрать, какие из них считывать. Например, если вы хотите определить только красный цвет, вы можете выбрать 16 фотодиодов с красными фильтрами, установив оба вывода в LOW, согласно таблице.
Аналогично, вы можете выбрать различные типы фотодиодов с помощью различных комбинаций S2 и S3.
S2 |
S3 |
Тип фотодиода |
|---|---|---|
LOW |
LOW |
Красный |
LOW |
HIGH |
Синий |
HIGH |
LOW |
Прозрачный (без фильтра) |
HIGH |
HIGH |
Зелёный |
Встроенный преобразователь тока в частоту преобразует показания фотодиодов в прямоугольный сигнал, частота которого пропорциональна интенсивности выбранного цвета. Диапазон типичной выходной частоты составляет 2Гц~500КГц.
У датчика есть ещё два управляющих вывода, S0 и S1, которые используются для масштабирования выходной частоты. Частота может быть масштабирована до трёх различных предустановленных значений: 2%, 20% или 100%. Эта функция масштабирования частоты позволяет использовать датчик с различными микроконтроллерами и другими устройствами.
S0 |
S1 |
Масштабирование выходной частоты |
|---|---|---|
LOW |
LOW |
Выключение |
LOW |
HIGH |
2% |
HIGH |
LOW |
20% |
HIGH |
HIGH |
100% |
Вы можете получить различные коэффициенты масштабирования различными комбинациями S0 и S1. Для Arduino в большинстве приложений используется масштабирование 20%.
Распиновка модуля датчика цвета TCS230
На следующей схеме показана распиновка типичного модуля TCS230.
GND — вывод заземления.
OE — вывод разрешения выхода (Output Enable). Этот вывод используется редко, и на большинстве модулей он постоянно включён. Если он не включён, подтяните его к LOW.
S0 и S1 — выводы для выбора масштабирования частоты.
S2 и S3 — выводы для выбора массива цветных фильтров.
OUT — прямоугольный сигнал TTL-уровня.
VCC — вывод питания модуля. Подключите его к источнику питания от 2.7В до 5.5В.
Подключение датчика цвета TCS230 к Arduino UNO
Подключить TCS230 к Arduino очень просто. Используются все выводы, кроме вывода разрешения выхода (OE), а модуль безопасно питается от 5-вольтового выхода Arduino.
Ниже приведена схема подключения для экспериментов с TCS230:
Ни один из используемых пинов Arduino не является критически важным, поскольку модуль не требует каких-либо специфических функций пинов, поэтому при желании вы можете использовать другие пины. Просто не забудьте изменить номера пинов в коде, если вы измените схему подключения.
После подключения датчика к Arduino пора писать код!
Калибровка датчика
На самом деле мы будем использовать два скетча для работы с датчиком цвета TCS230.
Первый скетч (калибровочный) поможет нам получить необработанные данные с датчика.
Второй скетч (основной скетч Arduino) будет использовать ранее полученные данные для отображения значений RGB для определяемого цвета.
Обратите внимание, что оба скетча используют одну и ту же схему подключения.
Ниже приведён калибровочный скетч. Этот скетч обращается к датчику TCS230 по одному цвету за раз и считывает длительность импульса на выходном выводе. Результат затем отображается в мониторе последовательного порта.
Загрузите скетч в Arduino и установите датчик так, чтобы он был направлен на объекты. Начните с поиска эталонных объектов белого и чёрного цвета. Эти эталонные объекты дадут показания при максимальных и минимальных значениях для всех трёх цветов.
// Define color sensor pins
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
// Variables for Color Pulse Width Measurements
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Pulse Width scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
}
void loop() {
// Read Red Pulse Width
redPW = getRedPW();
// Delay to stabilize sensor
delay(200);
// Read Green Pulse Width
greenPW = getGreenPW();
// Delay to stabilize sensor
delay(200);
// Read Blue Pulse Width
bluePW = getBluePW();
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red PW = ");
Serial.print(redPW);
Serial.print(" - Green PW = ");
Serial.print(greenPW);
Serial.print(" - Blue PW = ");
Serial.println(bluePW);
}
// Function to read Red Pulse Widths
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Green Pulse Widths
int getGreenPW() {
// Set sensor to read Green only
digitalWrite(S2,HIGH);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Blue Pulse Widths
int getBluePW() {
// Set sensor to read Blue only
digitalWrite(S2,LOW);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
После загрузки скетча вы получите подобные показания. Запишите показания, полученные при обоих крайних значениях.
Объяснение кода:
Скетч начинается с определения выводов, используемых для подключения TCS230. Также определяются переменные для хранения длительности импульсов красного, зелёного и синего массивов фильтров.
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
В функции setup мы определяем выводы S0-S3 как выходы. Эти выводы будут использоваться для выбора масштабирования частоты и цвета, который мы хотим считать. Выводы S0 и S1 используются для установки масштабирования частоты на 20%, что является стандартным значением при использовании этого датчика цвета с Arduino. Далее выходной вывод датчика определяется как вход Arduino — именно здесь мы будем получать прямоугольный сигнал. Наконец, мы настраиваем монитор последовательного порта.
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Pulse Width scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
}
В секции loop мы вызываем три функции getRedPW(), getGreenPW() и getBluePW() для получения длительности импульса. Рассмотрим getRedPW() в качестве примера.
Функция getRedPW() получает длительность импульса красного цвета. Она начинает с установки выводов S2 и S3 для выбора красного фильтра. Это единственный шаг, в котором эта функция отличается от аналогичных функций для зелёного и синего цветов.
Затем определяется целочисленная переменная для хранения длительности импульса. Длительность импульса определяется с помощью функции Arduino pulseIn(). Эта функция измеряет длительность импульса — обратите внимание, что мы настроили её на измерение длительности LOW-части импульса. Результат — время в миллисекундах. Это значение затем возвращается, и функция завершается.
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
Возвращаясь к основному циклу, мы вызываем три функции для считывания длительности цветовых импульсов с задержкой 200мс между ними для стабилизации датчика. Затем мы выводим значения в монитор последовательного порта и повторяем цикл.
void loop() {
// Read Red Pulse Width
redPW = getRedPW();
// Delay to stabilize sensor
delay(200);
// Read Green Pulse Width
greenPW = getGreenPW();
// Delay to stabilize sensor
delay(200);
// Read Blue Pulse Width
bluePW = getBluePW();
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red PW = ");
Serial.print(redPW);
Serial.print(" - Green PW = ");
Serial.print(greenPW);
Serial.print(" - Blue PW = ");
Serial.println(bluePW);
}
Код Arduino — чтение значений RGB с TCS230
После получения показаний вы можете загрузить следующий скетч, в котором мы будем считывать значения RGB с датчика цвета TCS230.
Перед загрузкой скетча введите шесть калибровочных значений, полученных из калибровочного скетча, в начало скетча. Замените «0» на ваши реальные значения.
// Define color sensor pins
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
// Calibration Values
// *Get these from Calibration Sketch
int redMin = 0; // Red minimum value
int redMax = 0; // Red maximum value
int greenMin = 0; // Green minimum value
int greenMax = 0; // Green maximum value
int blueMin = 0; // Blue minimum value
int blueMax = 0; // Blue maximum value
// Variables for Color Pulse Width Measurements
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
// Variables for final Color values
int redValue;
int greenValue;
int blueValue;
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Set Frequency scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Setup Serial Monitor
Serial.begin(9600);
}
void loop() {
// Read Red value
redPW = getRedPW();
// Map to value from 0-255
redValue = map(redPW, redMin,redMax,255,0);
// Delay to stabilize sensor
delay(200);
// Read Green value
greenPW = getGreenPW();
// Map to value from 0-255
greenValue = map(greenPW, greenMin,greenMax,255,0);
// Delay to stabilize sensor
delay(200);
// Read Blue value
bluePW = getBluePW();
// Map to value from 0-255
blueValue = map(bluePW, blueMin,blueMax,255,0);
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red = ");
Serial.print(redValue);
Serial.print(" - Green = ");
Serial.print(greenValue);
Serial.print(" - Blue = ");
Serial.println(blueValue);
}
// Function to read Red Pulse Widths
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Green Pulse Widths
int getGreenPW() {
// Set sensor to read Green only
digitalWrite(S2,HIGH);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Blue Pulse Widths
int getBluePW() {
// Set sensor to read Blue only
digitalWrite(S2,LOW);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
Загрузите скетч и наблюдайте за результатами с образцами различных цветов. При необходимости вы можете внести небольшие корректировки в калибровочные значения.
Объяснение кода
Вы заметите, что большая часть этого скетча полностью совпадает с предыдущим, за исключением следующего:
Шесть калибровочных значений, полученных из калибровочного скетча, вводятся в начале скетча.
// Calibration Values
int redMin = 0; // Red minimum value
int redMax = 0; // Red maximum value
int greenMin = 0; // Green minimum value
int greenMax = 0; // Green maximum value
int blueMin = 0; // Blue minimum value
int blueMax = 0; // Blue maximum value
Определяются три новые переменные для значений RGB, которые мы хотим выводить.
int redValue;
int greenValue;
int blueValue;
В секции loop мы считываем каждое из значений с помощью той же функции, что и в предыдущем скетче. Затем мы используем функцию Arduino map() для преобразования этих значений в значения RGB, используя наши калибровочные значения в качестве ориентира.
Обратите внимание, что мы инвертировали диапазон (минимальное значение маппится на 255, а максимальное — на 0), потому что наши функции возвращают длительность импульса, а не частоту.
// Read Red value
redPW = getRedPW();
// Map to value from 0-255
redValue = map(redPW, redMin,redMax,255,0);
// Delay to stabilize sensor
delay(200);
Наконец, мы выводим значения в монитор последовательного порта. Эти итоговые показания будут соответствовать значениям RGB сканируемого объекта.