Problemas na Leitura de Cores com Sensores Ópticos TCRT5000 no Arduino Mega 2560

Olá a todos,

Estou enfrentando dificuldades ao tentar ler cores (verde, branco, cinza, preto) usando sensores ópticos reflexivos TCRT5000 em um Arduino Mega 2560. Estou usando três sensores conectados aos pinos analógicos A8, A9 e A10.

Apesar de ajustar os thresholds com base em leituras experimentais, estou tendo problemas porque os valores lidos das cores se sobrepõem, dificultando a distinção precisa entre elas. Aqui estão algumas médias, mínimos e máximos das leituras que obtive:

  • Verde: Média: 823, Mín: 808, Máx: 843
  • Branco: Média: 817, Mín: 803, Máx: 834
  • Cinza: Média: 816, Mín: 802, Máx: 833
  • Preto: Média: 818, Mín: 803, Máx: 835

Como podem ver, os valores estão muito próximos, causando sobreposição nas faixas de leitura. Já tentei calcular os thresholds como a média das médias das cores adjacentes, mas isso não resolveu o problema. Alterar a sensibilidade o sensor também apenas deixa as faixas menos iguais porém, ainda sobrepostas.

Aqui está um trecho do meu código atual para leitura e calibração:

#include <AFMotor.h>
#include <Ultrasonic.h>

// Definição dos pinos dos sensores
#define SENSOR_1 A8
#define SENSOR_2 A9
#define SENSOR_3 A10

// Estrutura para armazenar média, mínimo e máximo
struct SensorReadings {
  int average;
  int minimum;
  int maximum;
};

// Definição dos thresholds (ajuste conforme necessário)
int thresholdGreenWhite;
int thresholdWhiteGray;
int thresholdGrayBlack;

// Função para ler e calcular a média de valores de um sensor com 1000 leituras
SensorReadings readAverage(int sensorPin) {
  long sum = 0;
  int minVal = 1023;
  int maxVal = 0;
  int numReadings = 1000;

  // Coletar leituras
  for (int i = 0; i < numReadings; i++) {
    int reading = analogRead(sensorPin);
    sum += reading;
    if (reading < minVal) minVal = reading;
    if (reading > maxVal) maxVal = reading;
    delay(1); // Pequeno atraso para estabilizar a leitura
  }

  SensorReadings result;
  result.average = sum / numReadings;
  result.minimum = minVal;
  result.maximum = maxVal;
  return result;
}

// Função de depuração para imprimir leituras brutas do sensor
void debugReadings(int sensorPin) {
  Serial.print("Leituras do sensor no pino ");
  Serial.println(sensorPin);
  for (int i = 0; i < 100; i++) {
    int reading = analogRead(sensorPin);
    Serial.print(reading);
    Serial.print(" ");
    delay(10);
  }
  Serial.println();
}

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

  // Calibração inicial para definir os thresholds
  Serial.println("Calibrando...");

  Serial.println("Coloque o sensor no Verde e pressione uma tecla...");
  while (!Serial.available());
  Serial.read();
  debugReadings(SENSOR_1);
  SensorReadings greenReadings = readAverage(SENSOR_1);
  Serial.print("Verde: ");
  Serial.print(" Média: ");
  Serial.print(greenReadings.average);
  Serial.print(" Min: ");
  Serial.print(greenReadings.minimum);
  Serial.print(" Max: ");
  Serial.println(greenReadings.maximum);

  Serial.println("Coloque o sensor no Branco e pressione uma tecla...");
  while (!Serial.available());
  Serial.read();
  debugReadings(SENSOR_1);
  SensorReadings whiteReadings = readAverage(SENSOR_1);
  Serial.print("Branco: ");
  Serial.print(" Média: ");
  Serial.print(whiteReadings.average);
  Serial.print(" Min: ");
  Serial.print(whiteReadings.minimum);
  Serial.print(" Max: ");
  Serial.println(whiteReadings.maximum);

  Serial.println("Coloque o sensor no Cinza e pressione uma tecla...");
  while (!Serial.available());
  Serial.read();
  debugReadings(SENSOR_1);
  SensorReadings grayReadings = readAverage(SENSOR_1);
  Serial.print("Cinza: ");
  Serial.print(" Média: ");
  Serial.print(grayReadings.average);
  Serial.print(" Min: ");
  Serial.print(grayReadings.minimum);
  Serial.print(" Max: ");
  Serial.println(grayReadings.maximum);

  Serial.println("Coloque o sensor no Preto e pressione uma tecla...");
  while (!Serial.available());
  Serial.read();
  debugReadings(SENSOR_1);
  SensorReadings blackReadings = readAverage(SENSOR_1);
  Serial.print("Preto: ");
  Serial.print(" Média: ");
  Serial.print(blackReadings.average);
  Serial.print(" Min: ");
  Serial.print(blackReadings.minimum);
  Serial.print(" Max: ");
  Serial.println(blackReadings.maximum);

  // Definir thresholds dinamicamente
  thresholdGreenWhite = (greenReadings.average + whiteReadings.average) / 2;
  thresholdWhiteGray = (whiteReadings.average + grayReadings.average) / 2;
  thresholdGrayBlack = (grayReadings.average + blackReadings.average) / 2;

  Serial.print("Threshold Verde-Branco: ");
  Serial.println(thresholdGreenWhite);
  Serial.print("Threshold Branco-Cinza: ");
  Serial.println(thresholdWhiteGray);
  Serial.print("Threshold Cinza-Preto: ");
  Serial.println(thresholdGrayBlack);
}

void loop() {
  // Leitura dos sensores
  SensorReadings sensorReadings[3];
  sensorReadings[0] = readAverage(SENSOR_1);
  sensorReadings[1] = readAverage(SENSOR_2);
  sensorReadings[2] = readAverage(SENSOR_3);

  // Calcular a média dos três sensores
  int combinedAverage = (sensorReadings[0].average + sensorReadings[1].average + sensorReadings[2].average) / 3;

  // Mapeamento dos valores para as cores
  String color = mapColor(combinedAverage);
  Serial.print("Média dos sensores: ");
  Serial.print(combinedAverage);
  Serial.print(" -> ");
  Serial.println(color);

  delay(500);
}

// Função para mapear o valor lido em uma cor
String mapColor(int value) {
  if (value < thresholdGreenWhite) {
    return "Verde";
  } else if (value < thresholdWhiteGray) {
    return "Branco";
  } else if (value < thresholdGrayBlack) {
    return "Cinza";
  } else {
    return "Preto";
  }
}

Minhas Dúvidas
Há uma melhor maneira de calcular os thresholds para distinguir claramente entre as cores?
Devo considerar uma abordagem diferente, como filtragem ou ponderação das leituras?
Existe uma forma de melhorar a precisão dos sensores TCRT5000 para este tipo de aplicação?
Agradeço qualquer orientação ou sugestões que possam ajudar a resolver este problema.

Obrigado!

When posting in this category, you must use English.
But if you want to keep it in Portuguese, request (or change it yourself) to change your topic to the International Portuguese category.

Ao postar nesta categoria, voce deve usar lingua inglesa.
Mas se quiser manter na lingua portuguesa, solicite, (ou mude voce mesmo), a mudança do seu tópico para a categoria Internacional Português.

Provide more details about your project.
For example, the wiring diagram for the sensors and the Arduino.

Olá! bem vindo ao Forum.

O problema que você traz é interessante, mas eu tenho dúvidas se é possível usar esse sensor para fazer o que você quer. Basta ver que nenhum módulo comercial para identificação de cores é baseado neste sensor.

Os módulos mais comuns, ou usam o TCS230 acompanhado de LEDs coloridos, ou usam o TCS34725 acompanhando de um LED branco.

Um teste que você pode fazer se estiver disposto é iluminar o objeto e comparar as 4 leituras com luz e sem luz. Não sei se vai dar resultado, mas é uma tentativa.

Se fizer o teste, depois retorne para nos contar :wink: