Saltar al contenido
Nivel inicial

Un dron que recorre la superficie del agua

Imprimir las piezas

Para armar el dron acuático debemos imprimir sus piezas en la impresora 3D. El modelo se puede descargar de forma libre y gratuita. Una vez descargado, lo imprimimos; cuando estén listas todas las piezas, las ensamblamos para construir el sistema mecánico del dron.

En caso de querer realizar una modificación en el modelo, independientemente del programa de modelado que utilicemos, debemos exportar nuestras piezas en formato .stl, el formato más popular a la hora de intercambiar digitalmente modelos de objetos para ser impresos en 3D.

Las piezas son las siguientes:

  • Carcasa principal inferior (x1) y superior (x1)
  • Carcasa de motores inferior (x1) y superior (x1)
  • Placa (x8)
  • Soporte (x4)
  • Vínculo lateral (x2) y vínculo transversal (x1)
  • Rotor de paletas derecho (x1) e izquierdo (x1)
Render 3D de una de las piezas del dron: una carcasa con superficie curva, orificios de sujeción en las esquinas y una serie de muescas semicirculares en un borde para el paso de los ejes.
Una de las piezas del casco del dron, lista para imprimir en 3D (figura original del proyecto).

Ensamblar el dron

Con todas las piezas impresas, las ensamblamos para construir la estructura mecánica del dron. Los dos rotores de paletas (derecho e izquierdo) van montados sobre el eje de cada motor: son las paletas las que, al girar, empujan el agua y hacen avanzar al dron.

Es importante que los motores y toda la electrónica queden sobre la superficie del dron, por encima de la línea de flotación, y que el compartimento que los aloja los mantenga protegidos del agua. Solo las paletas de los rotores tocan el agua.

Conectar un motor con el módulo ULN2003

Para hacer que los motores del dron se muevan necesitamos un controlador de motores: el módulo ULN2003. No es posible conectar los motores DC directamente a las salidas de la placa, porque los motores requieren más potencia de la que la placa puede entregar. El ULN2003 recibe la señal de baja potencia de una salida digital y deja pasar hacia el motor la corriente de las pilas.

Primero probaremos el funcionamiento con un solo motor, para entender cómo funciona el conjunto. Realizamos las conexiones como se ve en la figura.

Esquema de conexión: placa Arduino UNO con una salida digital que va a una entrada del módulo ULN2003; el módulo alimentado por las pilas comanda un único motor DC conectado a una de sus salidas; masa común entre la placa y las pilas.
Conexión de un solo motor a través del módulo ULN2003 (figura original del proyecto). La señal de la placa entra al módulo y este entrega a el motor la potencia de las pilas.

El motor recibe su energía del portapilas de 6 pilas AA, no de la placa: por eso el sistema puede mover motores sin sobrecargar el Arduino. La placa solo aporta la señal de control, y la masa (GND) se comparte entre la placa y las pilas para que ambos lados “hablen” del mismo cero.

En el Arduino UNO, la señal de control del primer motor sale del pin 5 (la constante PIN_MOTOR_IZQ en el código de los pasos siguientes) hacia una de las entradas del ULN2003.

En el ESP32 el armado es el mismo, pero la salida es un GPIO: el número exacto está en la constante PIN_MOTOR_IZQ al comienzo del código. Evitá los GPIO 0, 2, 12 y 15, que intervienen en el arranque de la placa.

Conectar el segundo motor

Ahora agregamos el segundo motor para poder desplazar el dron. Cada motor comanda un lado del dron (izquierdo y derecho) y se conecta a una entrada y una salida propias del módulo ULN2003, como se ve en la figura.

Esquema de conexión: placa Arduino UNO con dos salidas digitales que van a dos entradas del módulo ULN2003; el módulo comanda dos motores DC, uno por cada salida; ambos motores y la placa comparten la alimentación de las pilas y la masa.
Conexión de los dos motores a través del módulo ULN2003 (figura original del proyecto): uno para el lado izquierdo y otro para el derecho.

En el Arduino UNO, el motor izquierdo se comanda desde el pin 5 (PIN_MOTOR_IZQ) y el motor derecho desde el pin 6 (PIN_MOTOR_DER).

En el ESP32, los dos motores se comandan desde los GPIO indicados en las constantes PIN_MOTOR_IZQ y PIN_MOTOR_DER al comienzo del código.

La lógica del movimiento: avanzar, girar y frenar

Antes de programar el recorrido conviene entender cómo se mueve el dron. Como el módulo ULN2003 comanda cada motor en un solo sentido (encendido o apagado, sin marcha atrás), todos los movimientos se construyen combinando el encendido de los dos motores:

  • Avanzar: los dos motores encendidos. Las dos paletas empujan el agua y el dron va hacia adelante.
  • Girar: se frena uno de los motores y se deja andando el otro. El dron pivotea hacia el lado del motor frenado. Para girar hacia un lado, frenamos el motor de ese lado; para girar hacia el otro, frenamos el motor contrario.
  • Frenar: los dos motores apagados. El dron se detiene.

Programar el recorrido de barrido

Para que el dron pueda recolectar muestras de todo el lago, establecemos un recorrido que le permita abarcar la mayor superficie posible: una trayectoria de barrido en la que avanza, gira, avanza en sentido contrario, y así va cubriendo franjas paralelas hasta completar el área. La distancia que recorre en cada tramo depende del tiempo que le asignemos a cada movimiento antes de cambiar al siguiente.

La programación la realizaremos directamente en el lenguaje de Arduino (C++), usando el Arduino IDE en su versión 2.x, que se descarga gratis desde arduino.cc/en/software. Un programa de Arduino se llama sketch y tiene dos bloques: la función setup(), que se ejecuta una sola vez al inicializarse el dispositivo, y la función loop(), que se ejecuta repetidamente después. Los comentarios (todo lo que sigue a //) no tienen efecto en el programa: están para que el código sea más fácil de interpretar.

El programa es una secuencia de acciones de las que ya conocemos: encender los dos motores para avanzar, frenar uno para girar y esperar un tiempo entre cada cambio. Las constantes con los pines de los motores están al comienzo, y los tiempos de cada tramo se pueden ajustar para adaptar el recorrido a tu batea o pileta de pruebas.

Ver el código completo · dron-recorrido.ino
dron-recorrido.ino Arduino UNO
// Dron acuático — Nivel inicial: recorrido programado.
// El dron barre un área cerrada de la superficie del lago siguiendo una
// trayectoria fija cargada de antemano en la placa (no usa sensores).
// Dos motores DC mueven las paletas; se conducen con un módulo ULN2003.
//
// CÓMO GIRA (dirección diferencial, estilo "tanque"): el ULN2003 es un
// driver UNIDIRECCIONAL de encendido/apagado — puede prender un motor pero
// NO invertir su giro. Por eso el dron no tiene marcha atrás ni giro en el
// lugar: avanza con los dos motores andando y GIRA frenando uno y dejando
// andar el otro (el motor que sigue empujando arrastra al dron hacia el
// lado del motor frenado). Para giro en el lugar o marcha atrás haría falta
// un puente H (p. ej. L298N), como sugiere el cierre del proyecto original.
//
// SEGURIDAD (agua + electrónica): los motores son de baja tensión (5 V,
// alimentados con 6 pilas AA) y trabajan en la SUPERFICIE del agua, no
// sumergidos. Aun así, agua y electricidad no se llevan bien: la placa, el
// ULN2003, las pilas y el cableado van sobre la cubierta del dron, POR
// ENCIMA de la línea de flotación y protegidos de salpicaduras. No hay 220 V
// en ningún punto del proyecto.
//
// Plataforma: Arduino UNO.
// Conexión: entrada IN del ULN2003 del motor IZQUIERDO → pin 5,
//           entrada IN del motor DERECHO → pin 6.
//
// Basado en: Fragmento de código "Programar el movimiento del dron acuático"
// (Paso 9) — Dron Acuático, Saberes Digitales (INET/EDUCAR 2019).
// Modernización: se reemplazó el código generado por mBlock3 (_delay, _loop,
// angle_rad/deg, motores prendidos "a mano" con digitalWrite sueltos) por
// C++ idiomático con constantes nombradas y funciones de movimiento
// (avanzar / girarDerecha / girarIzquierda / frenar). El recorrido se
// ejecuta UNA vez en setup() y el dron queda detenido: es una trayectoria
// de barrido de un área cerrada, repetirla lo sacaría del área.

// Entradas del módulo ULN2003 que gobiernan cada motor.
const int PIN_MOTOR_IZQ = 5;
const int PIN_MOTOR_DER = 6;

// El ULN2003 es on/off: HIGH pone el motor a andar, LOW lo frena.
const int MOTOR_ANDANDO = HIGH;
const int MOTOR_FRENADO = LOW;

// Tiempos del recorrido (calibrar en la maqueta: dependen de la potencia de
// los motores y del rozamiento del agua). AVANCE = tramo recto entre giros;
// GIRO = cuánto dura el frenado de un motor para describir ~90°.
const unsigned long TIEMPO_AVANCE_MS = 3000;
const unsigned long TIEMPO_GIRO_MS   = 700;

// Avanzar: los dos motores andando, el dron va derecho hacia adelante.
void avanzar(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_ANDANDO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_ANDANDO);
  delay(ms);
}

// Girar a la derecha: frena el motor derecho y deja andar el izquierdo.
// El empuje del lado izquierdo hace pivotar el dron hacia la derecha.
void girarDerecha(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_ANDANDO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_FRENADO);
  delay(ms);
}

// Girar a la izquierda: el accionar exactamente opuesto al giro a derecha.
void girarIzquierda(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_FRENADO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_ANDANDO);
  delay(ms);
}

// Frenar: los dos motores apagados, el dron se detiene.
void frenar() {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_FRENADO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_FRENADO);
}

void setup() {
  pinMode(PIN_MOTOR_IZQ, OUTPUT);
  pinMode(PIN_MOTOR_DER, OUTPUT);
  frenar(); // arrancamos detenidos hasta empezar el recorrido

  // Recorrido de barrido en "S" (boustrofedón) que cubre un área cerrada:
  // avanzar, dos giros a la derecha, avanzar, dos giros a la izquierda...
  // Es la secuencia de 14 pasos del croquis del original, ya coherente.
  avanzar(TIEMPO_AVANCE_MS);       // 1. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 2. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 3. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 4. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 5. Avanzar
  girarIzquierda(TIEMPO_GIRO_MS);  // 6. Girar a la izquierda
  avanzar(TIEMPO_AVANCE_MS);       // 7. Avanzar
  girarIzquierda(TIEMPO_GIRO_MS);  // 8. Girar a la izquierda
  avanzar(TIEMPO_AVANCE_MS);       // 9. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 10. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 11. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 12. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 13. Avanzar
  frenar();                        // 14. Frenar
}

void loop() {
  // Recorrido terminado: el dron queda quieto con los motores apagados.
}
dron-recorrido.ino ESP32
// Dron acuático — Nivel inicial: recorrido programado.
// El dron barre un área cerrada de la superficie del lago siguiendo una
// trayectoria fija cargada de antemano en la placa (no usa sensores).
// Dos motores DC mueven las paletas; se conducen con un módulo ULN2003.
//
// CÓMO GIRA (dirección diferencial, estilo "tanque"): el ULN2003 es un
// driver UNIDIRECCIONAL de encendido/apagado — puede prender un motor pero
// NO invertir su giro. Por eso el dron no tiene marcha atrás ni giro en el
// lugar: avanza con los dos motores andando y GIRA frenando uno y dejando
// andar el otro (el motor que sigue empujando arrastra al dron hacia el
// lado del motor frenado). Para giro en el lugar o marcha atrás haría falta
// un puente H (p. ej. L298N), como sugiere el cierre del proyecto original.
//
// SEGURIDAD (agua + electrónica): los motores son de baja tensión (5 V,
// alimentados con 6 pilas AA) y trabajan en la SUPERFICIE del agua, no
// sumergidos. Aun así, agua y electricidad no se llevan bien: la placa, el
// ULN2003, las pilas y el cableado van sobre la cubierta del dron, POR
// ENCIMA de la línea de flotación y protegidos de salpicaduras. No hay 220 V
// en ningún punto del proyecto.
//
// NOTA DE ALIMENTACIÓN (ESP32): el ESP32 trabaja a 3,3 V, pero sus salidas
// digitales alcanzan de sobra para excitar las entradas IN del ULN2003 (el
// driver es el que maneja los 5 V de los motores). Alimentá el ULN2003 y los
// motores desde las 6 pilas AA (5 V), NO desde el pin 3V3 de la placa, y uní
// las masas (GND del ESP32 con GND de las pilas).
//
// Plataforma: ESP32 (DevKit v1).
// Conexión: entrada IN del ULN2003 del motor IZQUIERDO → GPIO 26,
//           entrada IN del motor DERECHO → GPIO 27.
//
// Basado en: Fragmento de código "Programar el movimiento del dron acuático"
// (Paso 9) — Dron Acuático, Saberes Digitales (INET/EDUCAR 2019).
// Modernización: se reemplazó el código generado por mBlock3 (_delay, _loop,
// angle_rad/deg, motores prendidos "a mano" con digitalWrite sueltos) por
// C++ idiomático con constantes nombradas y funciones de movimiento
// (avanzar / girarDerecha / girarIzquierda / frenar). El recorrido se
// ejecuta UNA vez en setup() y el dron queda detenido: es una trayectoria
// de barrido de un área cerrada, repetirla lo sacaría del área. Se portó del
// UNO (pines 5/6) al ESP32 (GPIO 26/27).

// Entradas del módulo ULN2003 que gobiernan cada motor.
const int PIN_MOTOR_IZQ = 26;
const int PIN_MOTOR_DER = 27;

// El ULN2003 es on/off: HIGH pone el motor a andar, LOW lo frena.
const int MOTOR_ANDANDO = HIGH;
const int MOTOR_FRENADO = LOW;

// Tiempos del recorrido (calibrar en la maqueta: dependen de la potencia de
// los motores y del rozamiento del agua). AVANCE = tramo recto entre giros;
// GIRO = cuánto dura el frenado de un motor para describir ~90°.
const unsigned long TIEMPO_AVANCE_MS = 3000;
const unsigned long TIEMPO_GIRO_MS   = 700;

// Avanzar: los dos motores andando, el dron va derecho hacia adelante.
void avanzar(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_ANDANDO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_ANDANDO);
  delay(ms);
}

// Girar a la derecha: frena el motor derecho y deja andar el izquierdo.
// El empuje del lado izquierdo hace pivotar el dron hacia la derecha.
void girarDerecha(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_ANDANDO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_FRENADO);
  delay(ms);
}

// Girar a la izquierda: el accionar exactamente opuesto al giro a derecha.
void girarIzquierda(unsigned long ms) {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_FRENADO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_ANDANDO);
  delay(ms);
}

// Frenar: los dos motores apagados, el dron se detiene.
void frenar() {
  digitalWrite(PIN_MOTOR_IZQ, MOTOR_FRENADO);
  digitalWrite(PIN_MOTOR_DER, MOTOR_FRENADO);
}

void setup() {
  pinMode(PIN_MOTOR_IZQ, OUTPUT);
  pinMode(PIN_MOTOR_DER, OUTPUT);
  frenar(); // arrancamos detenidos hasta empezar el recorrido

  // Recorrido de barrido en "S" (boustrofedón) que cubre un área cerrada:
  // avanzar, dos giros a la derecha, avanzar, dos giros a la izquierda...
  // Es la secuencia de 14 pasos del croquis del original, ya coherente.
  avanzar(TIEMPO_AVANCE_MS);       // 1. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 2. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 3. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 4. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 5. Avanzar
  girarIzquierda(TIEMPO_GIRO_MS);  // 6. Girar a la izquierda
  avanzar(TIEMPO_AVANCE_MS);       // 7. Avanzar
  girarIzquierda(TIEMPO_GIRO_MS);  // 8. Girar a la izquierda
  avanzar(TIEMPO_AVANCE_MS);       // 9. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 10. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 11. Avanzar
  girarDerecha(TIEMPO_GIRO_MS);    // 12. Girar a la derecha
  avanzar(TIEMPO_AVANCE_MS);       // 13. Avanzar
  frenar();                        // 14. Frenar
}

void loop() {
  // Recorrido terminado: el dron queda quieto con los motores apagados.
}
El recorrido de barrido: el dron avanza, gira, vuelve a avanzar y frena, siguiendo una trayectoria que cubre el área en franjas.

Podés ver el recorrido completo —el dron avanzando y girando para barrer el área— en el simulador, antes de probarlo en el agua:

Simulación del comportamiento

La misma máquina de estados del firmware, portada a TypeScript, maneja el comportamiento del dispositivo. No se ejecuta el binario real: la ejecución del .hex con avr8js está en el roadmap.

Simulación lista. Presioná «Iniciar» para arrancar la secuencia.

Subir el código y navegar

Para subir el código de nuestro programa a la placa, necesitamos:

  1. Conectar la placa a la computadora con el cable USB.
  2. Chequear que en el selector de placa del Arduino IDE esté seleccionada la placa correcta.
  3. Seleccionar el puerto al que está conectada la placa.
  4. Cliquear el botón Subir (la flecha →) en la parte superior de la interfaz.

En el Arduino IDE 2.x, la placa y el puerto se eligen juntos en el menú desplegable de la barra superior: al conectar la placa suele aparecer directamente como opción. Si no aparece, entrá a “Select other board and port” y buscala por nombre.

Para el Arduino UNO: usá el cable USB tipo B, elegí la placa Arduino UNO y el puerto que se agregó al conectarla (en Windows es un puerto COM numerado; en Linux suele llamarse /dev/ttyACM0 o similar).

Para el ESP32 hay dos pasos previos que se hacen una sola vez: instalar el soporte de placas ESP32 desde el gestor de placas del IDE (buscá “esp32” e instalá el paquete de Espressif) y, si el puerto no aparece, instalar el driver del conversor USB-serie de tu placa (generalmente CP210x o CH340). Después, elegí la placa ESP32 Dev Module (o “DOIT ESP32 DEVKIT V1”) y el puerto correspondiente. Si al subir el IDE queda esperando en “Connecting…”, mantené apretado el botón BOOT de la placa hasta que empiece la carga.

Al terminar de subir, veremos el mensaje de carga completada en la barra inferior del IDE.

Cierre del nivel

Al terminar este nivel, el dron de los investigadores navega solo: impreso en 3D y ensamblado, avanza con sus dos motores comandados por el ULN2003 y gira frenando uno de ellos, siguiendo una trayectoria de barrido que vos programaste y cargaste desde el Arduino IDE 2.x. Ya entendés la relación entre el tiempo de cada tramo y la distancia recorrida, la base de cualquier navegación por tiempo. En el nivel avanzado, el dron va a dejar de ser “ciego”: sensores ultrasónicos le van a permitir detectar las boyas que los guardaparques dejan en el lago, esquivarlas y volver a su recorrido.

Evidencia de cierre

Al terminar este nivel, esto tiene que estar funcionando:

  • El dron está impreso y ensamblado, con los dos motores montados sobre la superficie y la electrónica y las pilas protegidas del agua.
  • El módulo ULN2003 comanda los dos motores DC: con ambos encendidos el dron avanza, y frenando uno de ellos gira hacia ese lado.
  • El dron ejecuta una trayectoria de barrido predeterminada (avanzar, girar, avanzar, frenar) cargada en la placa desde el Arduino IDE 2.x.