Cruce de semáforos con detección de infracciones

Materiales utilizados:

  • Cable USB
  • Placa Arduino UNO
  • Protoboard
  • Jumpers (M-M y M-H)
  • 2 semáforos (LED RYG)
  • 3 sensores ultrasónicos (HC-SR04)
  • Buffer

Adicionales:

  • Cartón
  • Palitos de madera
  • Pintura
  • Celofán
  • Silicona
  • Coches de juguete

Contexto:

En primer lugar, hicimos una “brain storming” para sacar ideas sobre posibles proyectos para la asignatura. Después de varios días de decisión, decidimos consultarlo con el profesor para que nos diera la confirmación sobre la idea y poder comenzar el proyecto con seguridad. La idea final fue la de construir un cruce de semáforos, como cualquier otro que podríamos encontrar en nuestras ciudades, pero intentándolo hacer mucho más seguro tanto para peatones como conductores, añadiendo en una de las carreteras un radar de semáforo justo después del semáforo que detecta si un vehículo se lo salta en rojo, y en la otra carretera un radar de velocidad para saber a que velocidad entraría el coche en el cruce (si fuese a más de 30 km/h se consideraría una infracción). Aunque pueda parecer una idea sencilla, nos pareció bastante interesante desarrollar un proyecto de este estilo ya que es muy común en todas las ciudades los atropellos a personas o accidentes entre coches por saltarse semáforos en rojo o por circular a una velocidad imprudente.

Empezamos nuestro proyecto con los materiales proporcionados en clase, siendo conscientes de que necesitaríamos más. Empezamos conectando en la placa tres leds con sus respectivas resistencias de 330 ohmios, para crear el “semáforo casero”. Tras debatir esta idea, nos dimos cuenta que iba a ser bastante tedioso para, en un futuro, llevar tantos cables a la maqueta, por lo que decidimos buscar algún prototipo parecido a un semáforo en Amazon, y decidimos a comprarlos, lo que nos facilitó un montón la práctica.

Tras probar el primero, comenzamos con el funcionamiento del segundo, y tras conseguir enchufarlo, modificamos el código para que funcionaran de forma simultánea, como en la vida real, respetando los estados, y añadiendo un breve tiempo en el que ambos están en estado rojo, para añadirle coherencia y lógica al proyecto.

Nos surgió la idea de hacer una especie de radar y decidimos realizarlo. Probamos con el material de clase y encontramos el sensor HC-SR04, y decidimos implementarlo como un radar de movimiento, de la forma en que si un coche era detectado por ese radar cuando su respectivo semáforo se encontraba en rojo, devolvía una infracción. Lo probamos en la placa con su código y pusimos también un zumbador, para hacerlo mas sólido y consistente. Por lo tanto, cuando ese radar detecta un objeto (en este caso un coche) pasando por el semáforo en rojo, lanza el mensaje de infracción detectada y activa un sonido en el zumbador.

Tras esta primera implementación con sus respectivas pruebas, nos dimos cuenta que el radar también detectaba el coche a una distancia lejana, fuera de las medidas de la carretera, por lo que tuvimos que modificar el rango de detección y ajustarlo a la dimensión de la anchura de la carretera.

Después de esto, nos quedaba el semáforo numero 2 un poco vacío, por lo que decidimos ponerle también otro sistema de detección de infracciones con los sensores HC-SR04, pero como en el kit de clase solo viene uno, tuvimos que comprarlo por Amazon. También decidimos comprar más cables siendo previsores, porque los necesitaríamos al final en el montado de la maqueta.

Nos decidimos por realizar un sistema de detección de velocidad, ya que si un sensor detectaba el momento en el que aparecía un objeto en su rango de onda, también seria interesante añadir otro sensor a una distancia determinada del anterior. Cada uno guarda el instante en el que detecta el coche, y con esta distancia y diferencia de tiempo podríamos calcular la velocidad a la que el coche había pasado por ambos radares.

Como ya habíamos ajustado la distancia del rango del radar del semáforo, lo hicimos automáticamente también con estos dos radares, pero aun así surgieron nuevos problemas. En principio, alternamos los pines de conexión del Arduino 1 con los declarados en el código, por lo que lo habíamos montado al revés y el código a veces se volvía “loco”, o nos detectaba velocidades infinitas o muy altas, etc. Tras arreglar esto, nos dimos cuenta de que, al pasarlo una vez, detectaba 3, por lo tanto, decidimos también reducir la cantidad de captura de onda a 2 veces, para que no hubiera ningún problema con cualquier otro tipo de onda, como podría ser el ruido, por lo que para saber cuándo detectar el coche, el sensor tenía que medir dos veces esa misma velocidad dentro del rango establecido.

Una vez teníamos este problema solucionado decidimos poner una pantalla OLED, en la que reproducir la velocidad de la detección de los radares del segundo carril. Con ella también tuvimos problemas, pero estos no los pudimos solucionar. En principio no estábamos muy convencidos de usarla, porque las patas estaban oxidadas y teníamos miedo de que estropeara el material.

Nos decidimos a montarla y efectivamente la pantalla se encendía, pero muchos de sus pixeles no se encendías. Tras lamentarnos por el pobre funcionamiento de esta, decidimos no implementarla, y reproducir la velocidad por la salida del programa de Arduino, también debido a que una nueva pantalla no hubiese llegado a tiempo para la entrega del proyecto.

Ya finalizado todo esto sobre la placa, cogimos dos trozos de cartón de una caja, los unimos con celofán y decidimos montar un cruce de carreteras. Una vez pintados los carriles, hicimos agujeros en las esquinas y metimos palitos de madera en los que enganchar los semáforos y los radares, de forma que quedaran inmóviles y bien acopladas a la maqueta.

Empezamos a tirar cables para alargar las conexiones a cada dispositivo, y tras varios problemas de reconexión, finalizamos con la práctica de esta asignatura, un cruce de carreteras con dos carriles; el vertical, con un semáforo, sensor HC-SR04 para detectar si un coche se salta el semáforo en rojo, y el zumbador; y el horizontal, más largo que el vertical, con un semáforo y dos sensores HC-SR04 para detectar la velocidad en la que pasan los coches, haciendo pitar el mismo zumbador si sobrepasa el límite de 30km/h.

Problemas encontrados:

Aunque ya hemos comentado anteriormente un poco los problemas que tuvimos durante la realización del proyecto, ahora vamos a explicar de forma más detallada los más relevantes, aportando también la solución para resolverlos.

  • Problemas con el funcionamiento de la distancia de detección del radar del semáforo en rojo: en este caso el problema que tuvimos fue que detectaba “como que un coche se saltaba el semáforo” hasta en la parte que ya no es carretera. Para solucionar esto solo tuvimos que hacer más pequeña la distancia en la que tenia que detectar los coches, reduciéndola a 10 cm;
  • Problemas con el calculo de la velocidad de circulación de un coche: en este caso el problema que tuvimos es que al tratarse de una maqueta las distancias son mas reducidas, por lo que a la hora de calcular la velocidad de un coche en km/h salían velocidades que no superaban los 5 km/h (velocidad alcanzada pasando el coche lo más rápido posible entre los dos sensores). Como entre un sensor y el otro hay 30 cm, para solucionar este problema pensamos en calcular la velocidad en cm/s y después convertirla a km/h además de multiplicar dicho valor por 10 para que fuese más realista;
  • Problemas con pantalla led: en este caso, el problema no hemos sabido si era solo nuestro o también del estado en el que se encontraba la pantalla como hemos comentado anteriormente por lo que decidimos no implementarla;
  • Problemas de detección de coche sin pasar ninguno: en este caso el problema creemos que es que al ser muy sensibles los sensores ultrasónicos, detectaban quizás ruido o algo que les hacia pensar que lo que había sucedido era que había pasado un coche, por lo que para solucionar lo que hicimos fue asegurarnos de que para saber que lo que pasaba era un coche tuviese que detectar la misma distancia reducida en el umbral establecido mínimo 2 veces, evitando así las falsas detecciones.

Código:

// Declaracion pines semaforos
int vA = 8, aA = 9, rA = 10;
int vB = 11, aB = 12, rB = 13;

// Pines SENSOR INFRACCION 1: semaforo en rojo
int trigA = 6;
int echoA = 7;

// Pines SENSORES INFRACCION 2: radar velocidad
int trig1 = 4;
int echo1 = 5;

int trig2 = 2;
int echo2 = 3;

// Pin BUZZER
int buzzer = A0;

bool buzzerActivo = false;
unsigned long tiempoBuzzer = 0;
const int duracionBuzzer = 1500;

const int tTodoRojo = 2000;

// Variables SENSOR INFRACCION 1
bool cocheDetectado = false;
float distancia;

// Variables SENSOR INFRACCION 2
unsigned long tiempoInicio = 0;

int estadoRadar = 0;

// FILTRO para evitar ruido
int contS1 = 0;
int contS2 = 0;
const int filtro = 2;

bool s1 = false;
bool s2 = false;

float distanciaEntreSensores = 30.0;
float limiteVelocidad = 30.0;    // en km/h simulados

// ------------------- TIEMPOS -------------------
unsigned long tiempoAnteriorSemaforo = 0;
unsigned long tiempoAnteriorSensor = 0;

int estado = 0;

const int tVerde = 10000;
const int tAmarillo = 2000;
const int intervaloSensor = 100;


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

  pinMode(vA, OUTPUT);
  pinMode(aA, OUTPUT);
  pinMode(rA, OUTPUT);

  pinMode(vB, OUTPUT);
  pinMode(aB, OUTPUT);
  pinMode(rB, OUTPUT);

  pinMode(trigA, OUTPUT);
  pinMode(echoA, INPUT);

  pinMode(trig1, OUTPUT);
  pinMode(echo1, INPUT);

  pinMode(trig2, OUTPUT);
  pinMode(echo2, INPUT);

  pinMode(buzzer, OUTPUT);
}

// FUNCION DISTANCIA
float medirDistancia(int trig, int echo) {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);

  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  long duracion = pulseIn(echo, HIGH, 30000);
  return duracion * 0.034 / 2;
}


void loop() {

  unsigned long tiempoActual = millis();

  // PARTE SEMAFOROS
  switch (estado) {

    case 0: // A VERDE - B ROJO
      digitalWrite(vA, HIGH);
      digitalWrite(aA, LOW);
      digitalWrite(rA, LOW);

      digitalWrite(vB, LOW);
      digitalWrite(aB, LOW);
      digitalWrite(rB, HIGH);

      if (tiempoActual - tiempoAnteriorSemaforo >= tVerde) {
        estado = 1;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;

    case 1: // A AMARILLO - B ROJO
      digitalWrite(vA, LOW);
      digitalWrite(aA, HIGH);
      digitalWrite(rA, LOW);

      digitalWrite(vB, LOW);
      digitalWrite(aB, LOW);
      digitalWrite(rB, HIGH);

      if (tiempoActual - tiempoAnteriorSemaforo >= tAmarillo) {
        estado = 4;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;

    case 4: // TODO ROJO
      digitalWrite(vA, LOW);
      digitalWrite(aA, LOW);
      digitalWrite(rA, HIGH);

      digitalWrite(vB, LOW);
      digitalWrite(aB, LOW);
      digitalWrite(rB, HIGH);

      if (tiempoActual - tiempoAnteriorSemaforo >= tTodoRojo) {
        estado = 2;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;

    case 2: // B VERDE - A ROJO
      digitalWrite(vA, LOW);
      digitalWrite(aA, LOW);
      digitalWrite(rA, HIGH);

      digitalWrite(vB, HIGH);
      digitalWrite(aB, LOW);
      digitalWrite(rB, LOW);

      if (tiempoActual - tiempoAnteriorSemaforo >= tVerde) {
        estado = 3;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;

    case 3: // B AMARILLO - A ROJO
      digitalWrite(vA, LOW);
      digitalWrite(aA, LOW);
      digitalWrite(rA, HIGH);

      digitalWrite(vB, LOW);
      digitalWrite(aB, HIGH);
      digitalWrite(rB, LOW);

      if (tiempoActual - tiempoAnteriorSemaforo >= tAmarillo) {
        estado = 5;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;

    case 5: // TODO ROJO
      digitalWrite(vA, LOW);
      digitalWrite(aA, LOW);
      digitalWrite(rA, HIGH);

      digitalWrite(vB, LOW);
      digitalWrite(aB, LOW);
      digitalWrite(rB, HIGH);

      if (tiempoActual - tiempoAnteriorSemaforo >= tTodoRojo) {
        estado = 0;
        tiempoAnteriorSemaforo = tiempoActual;
      }
      break;
  }

  // PARTE SENSOR INFRACCION SEMAFORO
  if (tiempoActual - tiempoAnteriorSensor >= intervaloSensor) {

    tiempoAnteriorSensor = tiempoActual;
    distancia = medirDistancia(trigA, echoA);

    if (distancia > 2 && distancia < 100) {

      if (distancia < 10 && !cocheDetectado) {

        cocheDetectado = true;

        if (estado == 2 || estado == 3 || estado == 4 || estado == 5) {
          Serial.println("INFRACCION: semaforo en rojo");

          tone(buzzer, 5000); 
          buzzerActivo = true;
          tiempoBuzzer = millis();
        }
      }

      if (distancia > 20 && cocheDetectado) {
        cocheDetectado = false;
      }
    }
  }

  // PARTE RADAR VELOCIDAD
  float d1 = medirDistancia(trig1, echo1);
  float d2 = medirDistancia(trig2, echo2);

  // FILTRO SENSOR 1
  if (d1 < 10) contS1++;
  else contS1 = 0;

  s1 = (contS1 >= filtro);

  // FILTRO SENSOR 2
  if (d2 < 10) contS2++;
  else contS2 = 0;

  s2 = (contS2 >= filtro);

  switch (estadoRadar) {

    case 0: // esperar S1
      if (s1) {
        tiempoInicio = millis();
        estadoRadar = 1;
        Serial.println("Inicio medicion");
      }
      break;

    case 1: // esperar S2
      if (s2) {

        unsigned long tiempoFin = millis();
        float tiempo = (tiempoFin - tiempoInicio) / 1000.0;

        if (tiempo > 0.05 && tiempo < 5) {

          float velocidadCms = distanciaEntreSensores / tiempo;
          float velocidadKmh = velocidadCms * 0.036 * 10;

          Serial.print("Velocidad: ");
          Serial.print(velocidadKmh);
          Serial.println(" km/h");

          if (velocidadKmh > limiteVelocidad) {
            Serial.println("INFRACCION: exceso de velocidad");

            tone(buzzer, 3000); 
            buzzerActivo = true;
            tiempoBuzzer = millis();
          }

        } else {
          Serial.println("Medicion descartada");
        }
        
        estadoRadar = 2;
      }
      break;

    case 2: // esperar que se vaya el coche
      if (!s1 && !s2) {
        estadoRadar = 0;
      }
      break;
  }

  if (buzzerActivo && millis() - tiempoBuzzer >= duracionBuzzer) {
    noTone(buzzer);
    buzzerActivo = false;
  }
}

Casos de uso:

En nuestro proyecto encontramos 3 casos de prueba:

  1. Infracción radar semáforo en rojo: en este caso lo que hacemos es probar en el primer semáforo lo que sucede cuando pasa un coche con el semáforo en verde, amarillo y en rojo, por los dos carriles de la carretera y haciendo también pruebas por la parte de lo que sería la cera de peatones para así comprobar que solo detecta saltarse el semáforo en los dos carriles.
  • Medición velocidad a la que circula un coche sin infracción: en este caso mostramos como por la otra carretera se calcula a la velocidad que llega un coche al cruce en el caso de un conductor responsable que respeta el límite de velocidad de 30 km/h por lo que no habrá infracción.
  • Medición velocidad a la que circula un coche con infracción: en este caso mostramos lo mismo que en la prueba 2 pero con un conductor que circula a más velocidad de la permitida por lo que se activará el zumbador mostrando la infracción.

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 *