Proceso
1.Pruebas
Empezamos con probando los componentes individualmente viendo si funcionaban
- Probamos el altavoz mediante conectando los cables del altavoz a los polos de una bateria
- Miramos si funcioaba los ToF funcionaba con un simple codigo:
import board
import busio
import adafruit_vl53l0x
import time
# 1. Setup I2C (using your pins)
i2c = busio.I2C(board.IO47, board.IO21)
# 2. Initialize the sensor
tof = adafruit_vl53l0x.VL53L0X(i2c)
print("Sensor Ready!")
# 3. Main Loop
while True:
# Read distance in millimeters
mm = tof.range
# Print the result
print("Distance:", mm, "mm")
# Wait half a second so it doesn't spam the screen
time.sleep(0.5)
- Las primeras líneas: cargan las herramientas necesarias.
- i2c = ...: Conecta el sensor usando los pines IO47 e IO21.
- tof = ...: Activa el sensor.
- while True:: Repite forever (bucle infinito).
- tof.range: Mide la distancia.
- print(...): Muestra la distancia en la pantalla.
- time.sleep(0.5): Espera 0.5 segundos antes de medir otra vez.
2. Un ToF + Altavoz
Conecciones:
| MAX98357A Pin | ESP32-S3 Pin (IO) | Descripción |
|---|---|---|
| Vin | 5V (o 3.3V) | El 5V da más potencia al altavoz. |
| GND | GND | Tierra. |
| LRC (Left/Right Clock) | IO17 | Word Select (WS). |
| BCLK (Bit Clock) | IO16 | Bit Clock (BCK). |
| DIN (Data In) | IO18 | Data Out del ESP32. |
| Gain / SD | No conectar | Configuración por defecto. |
Codigo:
import board
import busio
import audiobusio
import synthio
import adafruit_vl53l0x
import time
# --- CONFIGURACIÓN I2C (Sensor ToF) ---
i2c = busio.I2C(board.IO47, board.IO21)
tof = adafruit_vl53l0x.VL53L0X(i2c)
# --- CONFIGURACIÓN I2S (Audio Amp) ---
# Bit Clock (BCK), Word Select (LRC), Data (DIN)
audio = audiobusio.I2SOut(board.IO16, board.IO17, board.IO18)
synth = synthio.Synthesizer(sample_rate=44100)
audio.play(synth)
# --- NOTA INICIAL ---
nota = synthio.Note(frequency=440, amplitude=0.1)
synth.press(nota)
print("🔊 Audio iniciado. Mueve la mano frente al sensor!")
while True:
dist = tof.range # Distancia en mm
# Mapeo: Si la mano está entre 50mm y 400mm
if 50 < dist < 400:
# Convertimos distancia en frecuencia (Hz)
# Cuanto más cerca (50), más agudo (800Hz)
# Cuanto más lejos (400), más grave (200Hz)
frecuencia = 800 - ((dist - 50) * 2)
nota.frequency = max(200, min(frecuencia, 800))
nota.amplitude = 0.2 # Volumen moderado
else:
nota.amplitude = 0.0 # Silencio si está muy lejos
time.sleep(0.01) # Respuesta rápida
- Lee la distancia con el sensor láser.
- Si detecta tu mano (entre 5 cm y 40 cm):
- Cambia el tono: más cerca = más agudo
- Si no detecta mano → silencio.
- Suena por el amplificador conectado por I2S.
3. Dos ToF (volument y tono) y Altavoz
- Primero escaneamos las conecciones si esta bien conectado:
import board
import busio
import digitalio
import time
# 1. Setup XSHUT for the sensor that HAS the cable
# (Make sure this matches the IO pin you plugged it into!)
xshut = digitalio.DigitalInOut(board.IO10)
xshut.direction = digitalio.Direction.OUTPUT
xshut.value = True # Wake it up!
# 2. Setup I2C (Using the "Safe" pins from before)
i2c = busio.I2C(board.IO9, board.IO8)
print("Scanning I2C Bus...")
while True:
if i2c.try_lock():
devices = i2c.scan()
i2c.unlock()
if devices:
print("Detected addresses:", [hex(d) for d in devices])
else:
print("No sensors found. Check SDA/SCL cables.")
time.sleep(1)
Donde solo aparecia 0x30
Intentamos cambiar el codigo y las conecciones ya que anteriormente habia un time of flight que no estaba conectado a un xshut:
import board
import busio
import audiobusio
import synthio
import adafruit_vl53l0x
import time
# --- 1. CONFIGURACIÓN DE HARDWARE ---
# Intentamos abrir el bus I2C una sola vez
try:
i2c = busio.I2C(board.IO5, board.IO4)
except Exception:
print("Error crítico: No se puede iniciar el bus I2C")
# --- 2. INICIALIZACIÓN DE SENSORES ---
tof_t = None
tof_v = None
print("Buscando sensores...")
# Intentar Sensor 1 (Tono)
try:
tof_t = adafruit_vl53l0x.VL53L0X(i2c, address=0x29)
print("✅ Tono: OK")
except Exception:
print("❌ Tono: NO DETECTADO")
# NOTA: Si solo tienes un sensor funcionando ahora mismo,
# el código usará ese para el tono y dejará el volumen fijo.
# --- 3. CONFIGURACIÓN DE AUDIO ---
try:
audio = audiobusio.I2SOut(board.IO15, board.IO16, board.IO17)
synth = synthio.Synthesizer(sample_rate=22050)
audio.play(synth)
nota = synthio.Note(frequency=440, amplitude=0.2)
synth.press(nota)
except Exception as e:
print("Error de Audio:", e)
# --- 4. BUCLE PRINCIPAL ---
while True:
# Lógica de Tono
if tof_t:
try:
dist = tof_t.range
if 50 < dist < 400:
f = 800 - (dist * 1.5)
nota.frequency = max(100, min(f, 1000))
# Si solo hay un sensor, el volumen se queda en 0.2
nota.amplitude = 0.2
except Exception:
print("Error leyendo Tono")
time.sleep(0.01)
Usa estos pines, son los más estables del ESP32-S3:
- Audio: DIN (17), LRC (16), BCLK (15).
- I2C (Ambos sensores): SDA (IO4), SCL (IO5).
- Energía: Todos los VIN y XSHUT a 3.3V (en filas separadas).
Ahora que funciona lo que necestimaos es conectar el Amplificador:
Conecta tu amplificador/altavoz a estos pines exactamente:
- BCLK (Bit Clock) -> IO11
- LRC (Word Select / Left-Right Clock) -> IO12
- DIN (Data In) -> IO13
- VIN -> 5V o 3.3V (según tu ampli)
- GND -> GND
import board
import busio
import audiobusio
import synthio
import adafruit_vl53l0x
import time
# --- 1. SENSORES (Pines que ya te funcionan) ---
i2c_tono = busio.I2C(board.IO13, board.IO14)
i2c_vol = busio.I2C(board.IO5, board.IO4)
tof_t = None
tof_v = None
try:
tof_t = adafruit_vl53l0x.VL53L0X(i2c_tono)
print("✅ Sensor Tono OK")
except:
print("❌ Fallo Tono")
try:
tof_v = adafruit_vl53l0x.VL53L0X(i2c_vol)
print("✅ Sensor Volumen OK")
except:
print("❌ Fallo Volumen")
# --- 2. AUDIO (Tus pines originales) ---
# BCLK -> IO1 | LRC -> IO2 | DIN -> IO3
audio = audiobusio.I2SOut(board.IO1, board.IO2, board.IO3)
synth = synthio.Synthesizer(sample_rate=22050)
audio.play(synth)
nota = synthio.Note(frequency=440, amplitude=0.0)
synth.press(nota)
print("🎶 ¡A TOCAR! Usando pines 1, 2 y 3 para audio.")
# --- 3. BUCLE ---
while True:
if tof_t:
d1 = tof_t.range
if 50 < d1 < 450:
f = 900 - (d1 * 1.5)
nota.frequency = max(150, min(f, 1000))
if tof_v:
d2 = tof_v.range
if 50 < d2 < 400:
v = 0.6 - ((d2 - 50) / 600)
nota.amplitude = max(0.0, min(v, 0.6))
else:
nota.amplitude = 0.0
else:
nota.amplitude = 0.2
time.sleep(0.01)
4. Mejorar el sonido
- El codigo suena pero con poca variacion entonces ultilizamos ahora el rago completo de audio de 16 bits desde -32767 hasta 32767, luego vemos que el volumen control no funciona entonces cambiamos el volumen por vibrato
import board
import busio
import audiobusio
import synthio
import adafruit_vl53l0x
import time
import array
import math
# --- 1. SENSORES ---
i2c_tono = busio.I2C(board.IO13, board.IO14)
i2c_vol = busio.I2C(board.IO5, board.IO4)
tof_t = tof_v = None
try:
tof_t = adafruit_vl53l0x.VL53L0X(i2c_tono)
tof_t.measurement_timing_budget = 20000
print("✅ Tono (Derecha) OK")
except: print("❌ Error Tono")
try:
tof_v = adafruit_vl53l0x.VL53L0X(i2c_vol)
tof_v.measurement_timing_budget = 20000
print("✅ Vibrato (Izquierda) OK")
except: print("❌ Error Vibrato")
# --- 2. AUDIO ---
audio = audiobusio.I2SOut(board.IO1, board.IO2, board.IO3)
synth = synthio.Synthesizer(sample_rate=22050)
audio.play(synth)
# Onda Triangular
samples = 512
waveform_triangle = array.array('h', [0] * samples)
for i in range(samples):
if i < samples // 2: waveform_triangle[i] = -32767 + (i * 128 * 2)
else: waveform_triangle[i] = 32767 - ((i - samples // 2) * 128 * 2)
nota = synthio.Note(frequency=440, amplitude=0.4, waveform=waveform_triangle)
synth.press(nota)
# Variables de control
freq_base = 440
vibrato_intensidad = 0.0
vibrato_index = 0.0
while True:
# --- MANO DERECHA (TONO) ---
if tof_t:
d1 = tof_t.range
if 40 < d1 < 500:
target_f = 1100 - (d1 * 2)
freq_base = (freq_base * 0.8) + (target_f * 0.2)
nota.amplitude = 0.4
else:
nota.amplitude = 0.0
# --- MANO IZQUIERDA (VIBRATO EXAGERADO) ---
if tof_v:
d2 = tof_v.range
# Si la mano está entre 4cm y 40cm
if 40 < d2 < 400:
# Mapeo: 0.0 (lejos) a 1.0 (cerca)
vibrato_intensidad = 1.0 - ((d2 - 40) / 360)
vibrato_intensidad = max(0.0, min(vibrato_intensidad, 1.0))
else:
vibrato_intensidad = 0.0
# --- APLICAR EFECTO ---
vibrato_index += 0.5 # Velocidad del temblor
# Multiplicamos por 60 para que la nota salte hasta 60Hz arriba y abajo (muy notable)
oscilacion = math.sin(vibrato_index) * (vibrato_intensidad * 60)
nota.frequency = max(100, freq_base + oscilacion)
# MONITOR (Para ver si el sensor funciona)
print(f"Nota: {int(freq_base)}Hz | Vibrato: {int(vibrato_intensidad*100)}% ", end="\r")
time.sleep(0.01)