SEyTR_VIC – Grupo 2 – Cómo crear un sistema de clasificación de color con Arduino: Proyecto S.I.C.C.O.

Índice

  1. Introducción
  2. Especificaciones Técnicas (Hardware)
  3. Componentes del Sistema
  4. Esquema del circuito
  5. Funcionamiento y Metodología
  6. Código Fuente
  7. Vídeo de Demostración
  8. Dificultades Encontradas
  9. El Desafío del Software: Lógica Anti-Daltonismo
  10. Posibles Mejoras
  11. Conclusiones

Introducción

En este proyecto universitario se presenta S.I.C.C.O. (Sistema Industrial de Clasificación de Color Optimizado). En primer lugar, cabe definirlo como un prototipo de clasificación automatizada diseñado para identificar y separar piezas por color en una línea de producción. El sistema utiliza tecnología Arduino y se basa en el análisis de luz mediante el sensor TCS3200. De este modo, es posible dirigir actuadores mecánicos (servomotores) de forma precisa.


Especificaciones Técnicas (Hardware)

Para la construcción de este prototipo se han seleccionado componentes específicos. Por un lado, el «cerebro» es un Arduino Uno R3, mientras que el sensor de visión es un TCS3200. Asimismo, se han integrado 2 servomotores MG995 de alto torque. Por otro lado, la interfaz de usuario cuenta con una pantalla LCD 16×2 y un buzzer pasivo. Finalmente, el control se realiza mediante un pulsador con resistencia pull-up interna.


Componentes del Sistema

Antes de profundizar, es importante destacar que aproximadamente el 80% de los componentes ya se encontraban en posesión del autor o han sido reciclados. En consecuencia, este proyecto fomenta la sostenibilidad. No obstante, para fines informativos, presentamos una estimación del coste de mercado.

Tabla de componentes con su descripción
CategoríaComponenteFunción
ControlArduino Uno R3Microcontrolador central (Cerebro del sistema).
ControlControlador de motor DCRegulación de velocidad y dirección del motor.
Sensores / InputSensor TCS3200Escaneo de color mediante frecuencia de luz.
Sensores / InputPulsador (Botón)Gatillo de inicio para el proceso de escaneo manual.
ActuadoresServos MG995 (x2)Clasificación física de piezas (alto torque).
ActuadoresMotor 12V DCTracción y propulsión de la cinta transportadora.
Interfaz (HMI)LCD 1602Visualización de conteo y estado del sistema.
Interfaz (HMI)Buzzer PasivoFeedback acústico mediante frecuencias variables.
InfraestructuraFuentes Externas (9V/12V)Alimentación dedicada para evitar caídas de tensión
InfraestructuraChasis de MaderaSoporte estructural, alineación y aislamiento
Tabla de componentes con sus precios
ComponenteCantidadEstadoPrecio UnitarioSubtotal
Arduino Uno R3 (Compatible)1Reciclado9,50 €9,50 €
Sensor de Color TCS32001Nuevo5,80 €5,80 €
Servomotor MG9952Reciclado7,50 €15,00 €
Motor 12V DC1Reciclado8,50 €8,50 €
Controlador de motor DC1Nuevo10,00 €10,00 €
Pantalla LCD 16021Reciclado4,50 €4,50 €
Buzzer Pasivo1Reciclado0,60 €0,60 €
Fuente Externa (9V)1Nuevo2,50 €2,50 €
Fuente Externa (12V)1Reciclado12,00€12,00€
Pulsador y resistencias1Reciclado0,40 €0,40 €
Protoboard y jumpers1Reciclado5,00 €5,00 €
Chasis y Estructura de Madera1RecicladoIncalculable0,00 €
TOTAL ESTIMADO73,80 €

Esquema del Circuito

El diseño electrónico de S.I.C.C.O. se ha estructurado para separar la lógica de control de la etapa de potencia. Esto es vital para evitar que el ruido eléctrico de los motores afecte a las lecturas del sensor o la estabilidad de la pantalla LCD.

Imagen 1 – Esquema sin el sensor TCS200 (Sensor de color)

Nota: En la imagen 1, hay que considerar que los dos microservomotores no son los empleados, pero debido al programa empleado no daba opción de meter servomotores más grandes, pero lo crucial es su conexión de pines que son los mismos.

Imagen 2 – Conexión sensor de color (TCS3200) con el sistema completo

Arquitectura de Conexiones

El sistema se organiza en cuatro bloques principales:

  1. Bloque de Procesamiento: Arduino Uno R3 como unidad central.
  2. Bloque de Sensores e Input: El sensor TCS3200 (Pines 3-7) y el pulsador de inicio (Pin A0).
  3. Bloque de Actuadores: Dos servomotores MG995 (Pines 8 y 9) y el motor DC de la cinta.
  4. Bloque de Interfaz (HMI): Pantalla LCD 1602 en modo paralelo y Buzzer Pasivo (Pin 2).

Gestión de Energía (Power Management)

Se ha implementado una configuración de GND común (masa unificada) pero con líneas de alimentación separadas:

  • Línea de 5V: Alimenta el Arduino y la lógica del sensor.
  • Línea de 9V/12V: Fuente externa dedicada exclusivamente a los servomotores y al motor de la cinta. Esta separación es la que garantiza que la pantalla LCD no sufra parpadeos o reinicios durante la activación de los brazos mecánicos.

Pinout Detallado (Mapeado de Pines)

ComponentePin del ComponentePin Arduino / PlacaFunción
Sensor TCS3200VCC5V (Placa de pruebas)Alimentación del sensor
GNDGND (Placa de pruebas)Tierra común
S0Pin 3Escala de frecuencia
S1Pin 4Escala de frecuencia
S2Pin 5Filtro de color
S3Pin 6Filtro de color
OUTPin 7Lectura de frecuencia RGB
LED5V (Placa de pruebas)Iluminación constante
ServomotoresSeñal (Naranja/Blanco)Pin 8 y 9Control PWM (8: Azul, 9: Rojo)
(MG995)VCC (Rojo)Fuente Externa (+ o Placa de pruebas)Alimentación de potencia
GND (Marrón/Negro)GND ComúnTierra común del sistema
Pantalla LCDRSPin 13Selección de registro
(1602)EPin 12Habilitación (Enable)
D4, D5, D6, D711, 10, A2, A3Bus de datos
VSS / RWGNDTierra y modo escritura
VDD5VAlimentación lógica
V0Resistencia fija a GNDAjuste de contraste
Buzzer PasivoPositivo / SeñalPin 2Generación de tonos
NegativoGNDTierra común
PulsadorTerminal APin A0Gatillo de escaneo
Terminal BGNDCierre de circuito a masa

Funcionamiento y Metodología

A diferencia de los sistemas de escaneo continuo, S.I.C.C.O. implementa una «Estación de Chequeo Previo«. Debido a las limitaciones de distancia y la variabilidad de la luz ambiental, se ha optado por un diseño de «escaneo bajo demanda«. El proceso funciona de la siguiente manera:

  1. Escaneo Manual: El operador coloca la pieza y pulsa el botón.
  2. Análisis de Proporciones: Por consiguiente, el software mide el porcentaje relativo de RGB para evitar errores por sombras.
  3. Confirmación Acústica: El zumbador emite tonos distintos según el color.
  4. Clasificación Síncrona: Posteriormente, el sistema calcula el tiempo de viaje y activa el servo en el momento exacto.

Código Fuente

El código utiliza la librería Servo.h y LiquidCrystal.h. Destaca el uso de la función pulseIn() con timeout para evitar bloqueos del procesador y la lógica de porcentajes para la discriminación de color.

#include <Servo.h>
#include <LiquidCrystal.h>

// --- CONFIGURACIÓN DE PINES ---
LiquidCrystal lcd(13, 12, 11, 10, A2, A3);

#define S0 3
#define S1 4
#define S2 5
#define S3 6
#define sensorOut 7

#define PIN_SERVOA 9   
#define PIN_SERVOB 8   
#define BUZZER 2
#define PIN_BOTON A0   

Servo servoA; 
Servo servoB;

const int REPOSO = 90;
const int GOLPE = 0;
const int TIEMPO_VIAJE_ROJO = 3500; 
const int TIEMPO_VIAJE_AZUL = 2500;

int totalRojos = 0, totalAzules = 0, totalVerdes = 0;

void setup() {
  Serial.begin(9600);
  
  // 1. INICIALIZAR LCD Y BUZZER
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("INICIANDO...");
  
  // Prueba de sonido para Passive Buzzer
  tone(BUZZER, 1000, 200); 
  delay(500);
  
  // 2. CONFIGURAR PINES
  pinMode(S0, OUTPUT); pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT); pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  digitalWrite(S0, HIGH); digitalWrite(S1, LOW); 

  pinMode(PIN_BOTON, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);

  servoA.attach(PIN_SERVOA);
  servoB.attach(PIN_SERVOB);
  servoA.write(REPOSO);
  servoB.write(REPOSO);

  lcd.clear();
  lcd.print("S.I.C.C.O");
  lcd.setCursor(0, 1);
  lcd.print("LISTO!");
  delay(1000);
  mostrarContadores();
}

void loop() {
  // Comprobación constante: Si el botón se pulsa (va a LOW)
  if (digitalRead(PIN_BOTON) == LOW) {

    // 1. LEER FRECUENCIAS CON TIMEOUT
    float r = leerFrecuencia(LOW, LOW);   
    float v = leerFrecuencia(HIGH, HIGH); 
    float b = leerFrecuencia(LOW, HIGH);  

    // 2. CÁLCULO DE PORCENTAJES
    float intR = 1000.0 / r;
    float intV = 1000.0 / v;
    float intB = 1000.0 / b;
    float totalLuz = intR + intV + intB;

    int porcRojo = (intR / totalLuz) * 100;
    int porcVerde = (intV / totalLuz) * 100;
    int porcAzul = (intB / totalLuz) * 100;

    Serial.print("R:"); Serial.print(porcRojo);
    Serial.print("% | V:"); Serial.print(porcVerde);
    Serial.print("% | A:"); Serial.println(porcAzul);

    // 3. LÓGICA DE CLASIFICACIÓN
    if (porcRojo > porcAzul && porcRojo > porcVerde && porcRojo > 35) {
      totalRojos++;
      actualizarLCD("PIEZA ROJA", "ACCION: SERVO A");
      sonidoRojo(); 
      delay(TIEMPO_VIAJE_ROJO); 
      ejecutarGolpe(servoA);
    } 
    else if (porcAzul > porcRojo && porcAzul > porcVerde && porcAzul > 35) {
      totalAzules++;
      actualizarLCD("PIEZA AZUL", "ACCION: SERVO B");
      sonidoAzul(); 
      delay(TIEMPO_VIAJE_AZUL); 
      ejecutarGolpe(servoB);
    } 
    else if (porcVerde > porcRojo && porcVerde > porcAzul && porcVerde > 35) {
      totalVerdes++;
      actualizarLCD("PIEZA VERDE", "DEJAR PASAR...");
      sonidoVerde(); 
      delay(2000); 
    }
    else {
      actualizarLCD("ERROR COLOR", "REINTENTAR");
      tone(BUZZER, 300, 500); // Sonido grave de error
    }

    // Esperar a soltar el botón
    while(digitalRead(PIN_BOTON) == LOW);
    delay(500);
    mostrarContadores();
  }
}

// --- FUNCIONES DE SOPORTE ---

float leerFrecuencia(int s2, int s3) {
  digitalWrite(S2, s2);
  digitalWrite(S3, s3);
  // pulseIn para que no se bloquee si el sensor falla
  long lectura = pulseIn(sensorOut, LOW, 100000); 
  if (lectura <= 0) return 1000.0; // Si falla, devolvemos un valor alto (poca intensidad)
  return (float)lectura;
}

void actualizarLCD(String l1, String l2) {
  lcd.clear();
  lcd.print(l1);
  lcd.setCursor(0, 1);
  lcd.print(l2);
}

void mostrarContadores() {
  lcd.clear();
  lcd.print("R:"); lcd.print(totalRojos);
  lcd.print(" A:"); lcd.print(totalAzules);
  lcd.print(" V:"); lcd.print(totalVerdes);
  lcd.setCursor(0, 1);
  lcd.print("ESPERANDO PIEZA");
}

void ejecutarGolpe(Servo &s) {
  s.write(GOLPE);
  delay(1000);
  s.write(REPOSO);
}

// --- FUNCIONES PARA PASSIVE BUZZER ---

void sonidoRojo() {
  tone(BUZZER, 2000, 200); // Agudo
}

void sonidoAzul() {
  tone(BUZZER, 1500, 100); delay(150);
  tone(BUZZER, 1500, 100); // Doble pitido
}

void sonidoVerde() {
  tone(BUZZER, 1000, 600); // Pitido más largo y medio
}

Vídeo de Demostración

Nota: En el vídeo se puede observar la secuencia de escaneo, el pitido de confirmación y el movimiento síncrono de los brazos según el color detectado.


Dificultades Encontradas durante el desarrollo

El desarrollo de este prototipo presentó varios retos técnicos que requirieron soluciones creativas:

  • Modificación de piezas: Originalmente el proyecto se iba a realizar con el sensor de visión ESP32-CAM, pero debido a las dificultades que presentaba, se ha tomado la decisión de intercambiar esa pieza por el TCS3200, modificando parte del comportamiento, pero manteniendo el objetivo de cómo funciona un clasificador de objetos.
  • Alcance del Sensor: Inicialmente se planteó un escaneo a 23 cm de distancia, pero se comprobó que el TCS3200 pierde precisión a más de 3 cm debido a la dispersión de luz. Se resolvió mediante un sistema de escaneo manual cercano.
  • Gestión de Energía: Los servos MG995 generan picos de consumo que reiniciaban el LCD. Se solucionó separando las líneas de alimentación y unificando las tierras (GND).
  • Contraste del LCD: La ausencia de un potenciómetro dificultó la legibilidad. Se ajustó mediante el cálculo de una resistencia fija óptima para estabilizar el voltaje del Pin V0.
  • Buzzer Pasivo: La diferencia entre un buzzer activo y uno pasivo obligó a cambiar la lógica de digitalWrite por la función tone() para generar sonido real.

El Desafío del Software: Lógica Anti-Daltonismo

Uno de los mayores retos fue la sensibilidad del sensor hacia el rojo. Para solucionar esto, implementamos una inversión de frecuencias. El sistema suma la intensidad de los tres canales y calcula cuánto peso tiene cada uno sobre el total:

Esto permite que S.I.C.C.O. identifique el rojo o el azul basándose en su proporción lumínica, no en su brillo absoluto. Gracias a esta técnica, logramos que el sistema discrimine con éxito entre piezas rojas, azules y verdes (siendo estas últimas contabilizadas pero no clasificadas).


Posibles Mejoras (Futuro del Proyecto)

Aunque S.I.C.C.O. es funcional, el diseño permite escalar hacia una versión más industrial:

  1. Implementación de Visión Artificial: Sustituir el sensor TCS3200 por una cámara (ESP32-CAM) para permitir el escaneo a larga distancia sin intervención manual.
  2. Uso de Módulo I2C para LCD: Para reducir el cableado de 6 pines a solo 2, liberando puertos para más sensores.
  3. Cinta Transportadora Inteligente: Sincronizar el motor de la cinta con el Arduino mediante un controlador (L298N) para paradas de emergencia automáticas.

Conclusiones

En conclusión, S.I.C.C.O. demuestra cómo la ingeniería de software compensa las limitaciones del hardware. Efectivamente, mediante algoritmos de compensación, se ha logrado un sistema fiable y escalable.

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *