Sistema de sonar marítimo
Implementación
El hardware de nuestro sistema de sonar marítimo consta principalmente de los siguientes componentes:
- Sensor HC-SR04: sensor de ultrasonido que emite ondas para medir la distancia a objetos mediante el eco.
- Buzzer: genera una alarma sonora que cambia de velocidad según la distancia a la que se encuentra el objeto.
- Servomotor SG90: hace que el sensor pueda girar para realizar el barrido del radar en diferentes ángulos.
- Arduino Uno: procesa el código y lee las señales del sensor y da ordenes al servomotor y al zumbador.
- Pila de 9V: proporciona energía extra para que el motor no reinicie la placa Arduino al moverse.
- Cables puente y Dupont: se realizan las conexiones entre los componentes.
- Protoboard: conectamos todos los componentes, sirve de puente entre ellos y el Arduino.
Para realizar nuestro sonar hemos realizados las siguientes conexiones:
- Alimentación principal
- Linea positiva (+): pin 5v del Arduino
- Linea negativa (-): pin GND del Arduino
- Sensor HC-SR04
- TRIG: Pin digital 10 del Arduino
- Echo: Pin digital 11 del Arduino
- VCC: línea roja (+) de la protoboard
- GND: línea azul (-) de la protoboard
- Servomotor SG90
- Cable amarillo: Pin digital 9 del Arduino
- Cable marrón: línea azul (-) de la protoboard
- Cable rojo: línea roja (+) de la protoboard
- Buzzer
- Pata larga: Pin digital 8 del Arduino
- Pata corta: línea azul (-) de la protoboard

Pasos dados
- Idea inicial
La idea pasó de un sensor estático que captaba el movimiento a un sistema dinámico de barrido angular para detectar obstáculos en un radio de 180º. Por el camino, pensamos en la implementación de un detector de fuego, pero fue rápidamente removido.
- Selección de materiales
Nos dimos cuenta de que no disponíamos de un motor lo suficientemente estable para realizar nuestro proyecto, por lo que tuvimos que comprar un servomotor.
- Hardware y código
Conforme fuimos conectando el hardware, también utilizamos códigos de prueba para comprobar que cada uno de los componentes funcionaba por separado y juntos cuando se empezaban a conectar todos. No encontramos ningún problema con los cables, no había ninguno defectuoso.
- Problemas de potencia
Como se explicará más en detalle más adelante, el servomotor utilizaba más potencia de la que prestaba el Arduino, por lo que añadimos una pila de 9V.
- Processing
Para darle un toque más profesional a nuestro proyecto, desarrollamos mediante la aplicación Processing un sonar que utilizaba las señales que le mandaban los pines en la placa de Arduino para pintarlo de una manera más representativa en la pantalla.
- Maquetación e integración
Para añadirle algo de decoración y complejidad, construimos una maqueta de un barco que completara nuestro proyecto y simulara cómo funcionaría en una situación real.

Reparto de tareas
El reparto de tareas ha sido prácticamente equitativo entre todos los integrantes del grupo, aunque cada uno se ha implicado más en un aspecto distinto.

Álvaro ha participado en un mayor porcentaje en el hardware, aunque también ha estado implicado en las otras tareas. Lo mismo para Mark, participando algo más en la programación del código y Leonardo con el montaje del proyecto.
Costes de los materiales
| Concepto / Componente | Cantidad | Coste Real (€) | Procedencia / Notas |
| Pila de 9V | 1 | 3.49 € | Adquirido por el alumno (Mejora de alimentación). |
| Servomotor SG90 | 1 | 4.00 € | Adquirido por el alumno (Nota: Se compró un pack de 2 uds. por 8.00 €, imputando la mitad al prototipo). |
| Placa Arduino Uno R3 | 1 | 0.00 € | Proporcionado por la Universidad (Starter Kit). |
| Sensor Ultrasónico HC-SR04 | 1 | 0.00 € | Proporcionado por la Universidad (Starter Kit). |
| Zumbador (Buzzer activo) | 1 | 0.00 € | Proporcionado por la Universidad (Starter Kit). |
| Protoboard y Cables Dupont | 1 set | 0.00 € | Proporcionado por la Universidad (Starter Kit). |
| Chasis (Cartón) y Adhesivos | 1 | 0.00 € | Material reciclado y fungible propio. |
| COSTE TOTAL DEL PROTOTIPO | 7.49 € |
Problemas y soluciones encontradas
- Problemas de voltaje y alimentación
Al alimentar el circuito solo con el USB al Arduino, el servomotor provocaba picos de corriente que causaban que nuestra placa se reiniciara y hacía que el ordenador desconectara el puerto por seguridad.
Para solucionarlo, conectamos una pila de 9V a la placa. Con ella, la placa pudo suministrar corriente a los elementos de nuestro circuito, evitando así los reinicios.
- Step Motor
El motor proporcionado en el kit no era lo suficientemente correcto para poder tener todo el ángulo que debía hacer nuestro sensor. Además, su superficie de contacto no era la necesaria para poder pegarlo.
La solución que encontramos fue la compra de un Servomotor SG90 que permite una mejora en el control preciso de la posición angular y mejorando así la superficie para pegar nuestro sensor.
- Problemas y evolución del código
Inicialmente, el código usaba la función delay() para mover el servomotor y esperar el eco del sensor. Esto «congelaba» el procesador, impidiendo que el buzzer pitara correctamente mientras el motor giraba.
Lo que hicimos fue reescribir el código y utilizarla función millis() con la que el procesador comprueba el tiempo transcurrido y decide si debe mover el motor, medir la distancia o activar el sonido del buzzer de forma independiente.
Casos de uso
- Escaneo de zona despejada
El radar escanea los alrededores de la proa del barco, para asi asegurarse de que la ruta está libre de obstáculos, a la vez el servomotor realiza desde 15º hasta 165º de barrido continuo y fluido, el sensor HR-SRC04 es quien se encarga de medir las distancias constantemente, si no detecta objetos a menos de 40cm el sistema se mantiene en silencio. Como resultado la pantalla del ordenador (Processing), se puede visualizar como la línea verde se mueve sin ninguna alerta visual
- Detección temprana de obstáculos
Un objeto entra en el rango de detección del HR-SRC04 (3-40cm) simulando así un riesgo de colisión
El sensor detecta la distancia exacta del objeto, a continuación, el Arduino envía los datos, en este caso ángulo y distancia por el puerto serie. Al detectar el objeto, el zumbador entonces emite un sonido espaciado, a menor distancia, el sonido se escucha con menor espaciado.
Con los datos recibidos del Arduino, el software Processing dibuja un punto rojo en las coordenadas exactas de la pantalla, así alertando visualmente. También indica a la distancia a la que se encuentra dicho objeto
- Alarma crítica de colisión inminente
Se detecta que un objeto se acerca peligrosamente al barco, el sensor detecta que la distancia disminuye drásticamente, gracias al millis(), el Arduino calcula un intervalo de espera más corto, en consecuencia, el zumbador aumenta la frecuencia de los pitidos (suena más rápido), el radar sigue girando sin congelarse, por lo tanto, la posición en la pantalla se va actualizando constantemente (punto rojo).
El proyecto implementa lo que se llama Sistema Embebido de Bucle Cerrado y Multitare, esto permite que los Casos de Uso 2 y 3 (pitar y moverse) ocurran simultáneamente sin que el motor se atasque
Código
Se ha decidido explicar el código con comentarios.
Arduino:
#include <Servo.h> // Librería para usar las funciones del Servomotor
// Configuración de pines digitales del buzzer, servo y las patillas trigger y echo del sensor ultrasonido
const int buzzerPin = 8;
const int servoPin = 9;
const int trigPin = 10;
const int echoPin = 11;
Servo myServo; // Objeto tipo Servo que hace referencia al Servomotor
int angle = 15; // Ángulo al que se moverá el servo
int direction = 1; // Dirección del servo
int distance; // Distancia desde el sensor hasta un objeto
long duration; // Duración del pulso del sensor para poder calcular la distancia
unsigned long previousMillisServo = 0; // Última vez que se usó el servo
unsigned long previousMillisBuzzer = 0; // Última vez que se usó el buzzer
const int servoInterval = 30; // Tiempo de intervalos de uso del servo
void setup() {
pinMode(trigPin, OUTPUT); // Trig del sensor como salida
pinMode(echoPin, INPUT); // Echo del sensor como entrada
pinMode(buzzerPin, OUTPUT); // Buzzer como salida
Serial.begin(9600); // Iniciamos comunicación con el ordenador
myServo.attach(servoPin); // Le decimos al objeto donde está el pin físico del servo
}
// Bucle infinito
void loop() {
unsigned long currentMillis = millis(); // Obtener el tiempo actual desde que se encendió el arduino
// Entramos al if si ha pasado suficiente tiempo desde el último uao del servo
if (currentMillis – previousMillisServo >= servoInterval) {
previousMillisServo = currentMillis; // Actualizamos última vez
myServo.write(angle); // Ordenar al servo a qué ángulo ir
distance = calculateDistance(); // Calcular distancia
// Imprimos el ángulo y la distancia con ese formato
Serial.print(angle);
Serial.print(«,»);
Serial.print(distance);
Serial.print(«.»);
angle += direction; // Actualizamos el siguiente ángulo
// Si el ángulo sobrepasa esos límites cambiamos la dirección para que no choque con nuestro modelo físico
if (angle >= 165 || angle <= 15) {
direction *= -1;
}
}
gestionarAlarma(distance); // Si se detecta un objeto el buzzer suena
}
int calculateDistance() {
digitalWrite(trigPin, LOW); // Comprobar que trig está apagado
delayMicroseconds(5); // Tiempo de estabilización
digitalWrite(trigPin, HIGH); // Encender trig para mandar un pulso untrasónido
delayMicroseconds(10); // Especificación del componente del tiempo de espera para que el Trigger considere la orden
digitalWrite(trigPin, LOW); // Apagar trig
duration = pulseIn(echoPin, HIGH); // Fumcion que devuelve el tiempo que ha durado el pulso
distance = (duration / 2) / 29.1; // Dividimos entre 2 porque el pulso va y vuelve, 29.1 es la constante microsegundos por centímetro
return distance; // Devolver la distancia
}
void gestionarAlarma(int dist) {
// Comprobar que detectamos un objeto en ese rango, fuera de ese rango el sensor HC-SR04 suele fallar
if (dist > 3 && dist <= 40) {
int intervaloEspera = map(dist, 3, 40, 100, 800); // Convertir la distancia entre el intervalo de cada tono del buzzer (a menor distancia más rápido suena)
unsigned long currentMillis = millis();
// Si ha pasado suficiente tiempo desde la última vez que se usó el buzzer mandamos un tono
if (currentMillis – previousMillisBuzzer >= intervaloEspera) {
previousMillisBuzzer = currentMillis; // Actualizar última vez
tone(buzzerPin, 1500, 60);
}
}
}
Processing:
Import processing.serial.*; // Librería para poder comunicarse con puertos usb
Serial miPuerto; // Objeto tipo Serial que controlará la comunicación
String datos = “”; // String para guardar los datos recibidos
Int angulo = 0; // Ángulo del objeto físico
Int distancia = 0; // Distancia hacia el objeto físico
Void setup() {
Size(800, 500); // Definir tamaño de la pantalla en píxeles
Smooth(); // Para que las líneas no se vean pixeladas
String nombrePuerto = “COM3”; // Nombre del puerto Windows por el que nos comunicaremos
miPuerto = new Serial(this, nombrePuerto, 9600); // Inicialización del Serial con 9600 baudios como en el código arduino
miPuerto.bufferUntil(‘.’); // Leer los datos entrantes hasta encontrar un ‘.’
}
// Función principal de animación, se ejecuta continuamente
Void draw() {
Fill(0, 15); // Rellenar con color negro y 15 de opacidad
noStroke(); // Sin bordes
rect(0, 0, width, height); // Dibuja un rectángulo en toda la pantalla
pushMatrix(); // guarda el sistema de coordenadas actuales
translate(400, 450); // Cambiamos el origen del sistema de coordenadas. Estaba en (0,0)
noFill(); // Sin rellenar
strokeWeight(2); // Bordes con grosor de 2cm
stroke(0, 255, 0); // Color verde
// Dibujar dos semicírculos típicos de un radar
arc(0, 0, 700, 700, PI, TWO_PI);
arc(0, 0, 400, 400, PI, TWO_PI);
float rad = radians(angulo); // Convertimos el ángulo recibido a radianes
stroke(0, 255, 0);
line(0, 0, 350 * cos(rad), -350 * sin(rad)); // Dibujar línea que recorra el ángulo actual
// Si detectamos un objeto entre esa distancia:
if (distancia < 40 && distancia > 2) {
fill(255, 0, 0); // Rellenar con color rojo
noStroke();
float x = map(distancia, 0, 40, 0, 350) * cos(rad); // Convertimos centímetros a píxeles
float y = -map(distancia, 0, 40, 0, 350) * sin(rad);
ellipse(x, y, 20, 20); // Dibujamos un punto 20×20
}
popMatrix(); // Restauramos las coordenadas para imprimir por pantalla sin problemas
fill(0, 255, 0);
textSize(20); // Tamaño de fuente
text(“Radar de Barco – Activo”, 20, 30);
text(“Distancia: “ + distancia + “ cm”, 20, 60);
}
// Función que se ejecuta cuando arduino envía datos
Void serialEvent(Serial p) {
Datos = p.readStringUntil(‘.’); // Leer hasta encontrar un ‘.’
If (datos ¡= null) { // Si recibe datos
Datos = datos.substring(0, datos.length() – 1); // Borramos el ‘.’
String[] lista = split(datos, ‘,’); // Separamos los datos por la ‘,’
If (lista.length == 2) { // Si los datos se han recibido correctamente
Angulo = int(lista[0]); // Obtenemos el ángulo
Distancia = int(lista[1]); // Obtenemos la distancia
}
}
}
En definitiva, el código Arduino contiene la lógica de los siguientes componentes:
Servomotor SG90: se mueve constantemente para permitir al sensor detectar objetos
Sensor HC-SR04: manda pulsos ultrasonido para detectar objetos
Buzzer: emite tonos en función de la distancia, a menor distancia suena en intervalos más rápidos. Esto sirve para que las personas encargadas de controlar la seguridad del barco/submarino puedan recibir feedback auditivo, canal de comunicación fundamental en un sonar.
Por otro lado, el código Processing se encarga de permitir al usuario visualizar la información en un radar, lo que proporciona un cierto grado de confianza extra, ya que se puede ver a los componentes realizando su trabajo