Un dron que recorre la superficie del agua
Recorrido del nivel
Esa barra de arriba te dice en qué paso estás. Tocala para ver el índice completo y saltar a cualquier paso.
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 .stlFormato .stlFormato de archivo que contiene la forma de un objeto sólido 3D, sin color, texturas ni propiedades físicas. Es el más usado para intercambiar e imprimir modelos 3D; funciona como la 'exportación final' de un diseño, como un PDF de un documento de texto., 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)
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.
Para el aula
Este es un buen momento para conversar sobre flotación y sobre estanqueidad: por qué la electrónica va arriba y protegida, y cómo el reparto del peso influye en que el dron flote equilibrado. No hace falta que quede perfecto: el objetivo es que floten y avancen; el ajuste fino es parte de la exploración de cada grupo.
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 ULN2003ULN2003Circuito integrado que actúa como driver de motores: convierte la señal de control de baja potencia de la placa (una salida digital) en la potencia necesaria para mover un motor DC. No invierte el giro: enciende y apaga el motor en un solo sentido.. No es posible conectar los motores DCMotor DCMotor eléctrico de dos terminales (+ y −), común en vehículos y ventiladores. Gira mientras recibe corriente y su velocidad depende de la potencia entregada. Requiere un circuito intermediario (driver) que le dé la potencia que la placa no puede entregar por sí sola. 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.
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 ESP32ESP32Placa con un microcontrolador de Espressif que trae WiFi (y Bluetooth) integrados. Se programa desde el Arduino IDE igual que un Arduino, con pines llamados GPIO. En este proyecto reemplaza al conjunto Arduino UNO + módulo OBLOQ para el nivel IoT. 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.
Verificá
Antes de energizar, repasá el circuito: la señal de la placa entra a una entrada del ULN2003, el motor queda conectado a la salida correspondiente del módulo, las pilas alimentan el módulo y la masa es común entre la placa y las pilas. Todavía no hay programa, así que el motor no se moverá.
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.
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.
¿Por qué no da marcha atrás?
Discutan en grupo: con este driver, el dron no puede retroceder. ¿Por qué? Piensen qué hace el ULN2003 con la corriente del motor (¿la puede invertir?). Después miren las extensiones de la ficha del proyecto: hay un componente, el doble puente H, que sí permitiría la marcha atrás. ¿Qué ganaría el dron pudiendo retroceder, y qué movimientos nuevos podría hacer?
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 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 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.
} 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.
Para el aula
El material original de 2019 enseñaba este paso con bloques en mBlock3, hoy discontinuado, y
el código que generaba arrastraba funciones sobrantes (_delay, _loop, angle_rad,
angle_deg) que no aportaban nada. En esta reedición ese ruido se limpió: el sketch usa
delay() estándar y constantes nombradas para los pines. La secuencia de barrido es una
oportunidad ideal para trabajar la relación entre tiempo y distancia: pedir a cada
grupo que dibuje en papel la trayectoria que espera y después la contraste con lo que hace el
dron.
Verificá
En el Arduino IDE, apretá el botón de verificar (el tilde ✓). Si abajo aparece “Compilación completada” sin mensajes en rojo, tu programa está bien escrito. Si aparece un error, revisá los punto y coma al final de cada línea y que las llaves abran y cierren.
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.