1 ¿Cómo funciona?
El sensor funciona como un murciélago: grita un sonido que no podemos oír (ultrasonido), espera a que rebote en un objeto y mide cuánto tardó en regresar.
- El Arduino manda un pulso de 10 microsegundos al pin Trig.
- El sensor, por sí solo, lanza 8 pulsos de ultrasonido a 40 kHz.
- El pin Echo se pone en HIGH y se queda así hasta que regresa el rebote.
pulseIn()mide cuántos microsegundos estuvo Echo en HIGH. Ese es el tiempo.
La fórmula
velocidad del sonido = 343 m/s = 0.0343 cm/µs
÷ 2 porque el sonido va y regresa
distancia = tiempo × 0.0343 ÷ 2 = tiempo × 0.01715
Ejemplo: si el eco tardó 1166 µs → 1166 × 0.01715 = 20 cm.
2 Conexión al Arduino UNO
| Pin del sensor | Pin del Arduino | Para qué sirve |
|---|---|---|
| VCC | 5V | Alimentación |
| Trig | 2 | Recibe el pulso de disparo (salida del Arduino) |
| Echo | 3 | Devuelve el pulso con el tiempo (entrada del Arduino) |
| GND | GND | Tierra |
⚠️ En el código original el Echo estaba en A4. Funciona, pero A4 es el pin SDA del I2C (el que usan las pantallas LCD I2C). Por eso se recomienda el pin 3.
3 Código original con comentarios
El código sí funciona en condiciones normales. Estos comentarios marcan qué está bien y qué hay que cambiar:
float tiempo; // ⚠️ CAMBIAR POR: unsigned long tiempo; (#1)
float distancia; // ✅ Correcto: la distancia sí lleva decimales
void setup() {
Serial.begin(115200); // ✅ Correcto (Monitor Serie también en 115200)
pinMode(2, OUTPUT); // ✅ Correcto: Trig es salida
pinMode(A4, INPUT); // ⚠️ CAMBIAR POR: pinMode(3, INPUT); (#2)
}
void loop() {
digitalWrite(2, LOW); // ✅ Correcto: Trig arranca en LOW
delayMicroseconds(2); // ✅ Correcto
digitalWrite(2, HIGH); // ✅ Correcto: inicia el pulso
delayMicroseconds(10); // ✅ Correcto: 10 us que pide la hoja de datos
digitalWrite(2, LOW); // ✅ Correcto: termina el pulso
tiempo = pulseIn(A4, HIGH); // ❌ CAMBIAR POR: tiempo = pulseIn(3, HIGH, 30000); (#3)
distancia = 0.01715 * tiempo; // ✅ Correcto: (343 m/s ÷ 2) en cm/us
Serial.println(distancia); // ✅ Correcto
if (distancia <=30){ // ❌ CAMBIAR POR: if (tiempo > 0 && distancia <= 30){ (#4)
Serial.println("OBJETO EN ZONA DE 30cm");
}
// ❌ AGREGAR AQUÍ: delay(60); (#5)
}
4 Tabla de cambios: qué, por qué y por cuál
| # | Línea original | Reemplazar por | ¿Por qué? | Tipo |
|---|---|---|---|---|
| 1 | float tiempo; |
unsigned long tiempo; |
pulseIn() entrega microsegundos: un número entero y siempre positivo. La documentación oficial de Arduino dice que su tipo es unsigned long. float es para números con decimales, y el tiempo nunca los trae.🧠 Es como guardar litros en una caja de kilos: cabe, pero no es su lugar. |
Mejora |
| 2 | pinMode(A4, INPUT); |
pinMode(3, INPUT); |
A4 sí sirve como pin digital, pero en el UNO es el pin SDA de la comunicación I2C. Si después se conecta una pantalla LCD I2C, choca con el sensor. 🔌 Hay que mover el cable de Echo de A4 al pin 3. |
Mejora |
| 3 | tiempo = pulseIn(A4, HIGH); |
tiempo = pulseIn(3, HIGH, 30000); |
Sin el tercer número, pulseIn espera hasta 1 segundo si no llega el eco, y el programa se congela. Con 30000 espera máximo 30 ms, que alcanza para unos 5 m, más que el máximo del sensor (4 m). |
Error |
| 4 | if (distancia <=30){ |
if (tiempo > 0 && distancia <= 30){ |
Si el eco no llega (cable flojo, sensor dañado), pulseIn devuelve 0. Entonces distancia = 0, y como 0 ≤ 30, imprime "OBJETO EN ZONA" sin que haya nada. Con tiempo > 0 se ignoran esas lecturas falsas. |
Error |
| 5 | (no existe) | delay(60); |
La hoja de datos del HC-SR04 recomienda más de 60 ms entre mediciones, para que los rebotes del pulso anterior no se confundan con el nuevo. También evita que el Monitor Serie se llene tan rápido que no se pueda leer. | Error |
❌ La falla más importante (#4), paso a paso:
Error = puede dar lecturas falsas. Mejora = funciona igual, pero es la forma correcta o evita problemas en proyectos futuros.
5 Código final, ya corregido
Igual de sencillo que el original, solo con los 5 cambios:
unsigned long tiempo; // #1: antes float
float distancia;
void setup() {
Serial.begin(115200);
pinMode(2, OUTPUT); // Trig
pinMode(3, INPUT); // #2: Echo, antes A4 (mover el cable)
}
void loop() {
digitalWrite(2, LOW);
delayMicroseconds(2);
digitalWrite(2, HIGH);
delayMicroseconds(10);
digitalWrite(2, LOW);
tiempo = pulseIn(3, HIGH, 30000); // #3: timeout de 30 ms
distancia = 0.01715 * tiempo;
Serial.println(distancia);
if (tiempo > 0 && distancia <= 30){ // #4: ignora lecturas en 0
Serial.println("OBJETO EN ZONA DE 30cm");
}
delay(60); // #5: pausa entre mediciones
}
6 Prueba para hacer en clase
Así los alumnos ven la diferencia en lugar de solo creerla:
- Sube el código original y abre el Monitor Serie en 115200.
- Desconecta el cable de Echo. Después de ~1 segundo aparece
0.00y "OBJETO EN ZONA DE 30cm" aunque no haya nada enfrente. - Reconéctalo y pon la mano a 5 cm: el Monitor Serie se llena tan rápido que casi no se puede leer.
- Ahora sube el código corregido y repite: ya no hay falsa alarma y las lecturas salen ordenadas.
✅ Conclusión: el código original funciona, pero no se protege de errores. Los cambios separan un código que "funciona en la demo" de uno confiable.