TTs whisper

This commit is contained in:
2026-06-18 13:45:32 +02:00
parent 0e7fbbfdca
commit 9a23863320
57 changed files with 10430 additions and 253 deletions

147
raspi/tests/test_blocks.py Normal file
View File

@@ -0,0 +1,147 @@
"""
test_blocks.py — Tests individuals del mòdul blocks.py.
Executa des del directori Rasp/: python tests/test_blocks.py
Descomenta la funció que vols provar al final del fitxer.
Assegura't que el venv està activat i pigpiod en marxa (sudo pigpiod -s 1).
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import time
import pigpio
from blocks import (
blocks_setup,
servo_move_to, OPEN_POSITION, EJECT_POSITION, MIN_SERVO_US, MAX_SERVO_US,
read_block_color, read_color_raw,
_COLORS,
BK, RD, GN, BU, YE, OG, VT,
)
_COLOR_NAMES = {
BK: "Negre (BK)",
RD: "Vermell (RD)",
GN: "Verd (GN)",
BU: "Blau (BU)",
YE: "Groc (YE)",
OG: "Taronja (OG)",
VT: "Violeta (VT)",
}
def _setup():
pi = pigpio.pi()
if not pi.connected:
print("ERROR: pigpiod no està en marxa. Executa: sudo pigpiod -s 1")
sys.exit(1)
blocks_setup(pi)
return pi
def _teardown(pi):
pi.stop()
# ==================
# TEST 1 — Servo
# ==================
def test_servo():
"""
Mou el servo a les posicions principals: oberta, expulsió i torna a oberta.
Hauries de veure/sentir el servo moure's suaument entre posicions.
"""
print("=== TEST SERVO ===")
pi = _setup()
print(f"Movent a OPEN_POSITION ({OPEN_POSITION} µs)...")
servo_move_to(OPEN_POSITION)
time.sleep(1.0)
print("Open: OK")
print(f"Movent a EJECT_POSITION ({EJECT_POSITION} µs)...")
servo_move_to(EJECT_POSITION)
time.sleep(1.0)
print("Eject: OK")
print(f"Tornant a OPEN_POSITION...")
servo_move_to(OPEN_POSITION)
time.sleep(1.0)
print("Torna a open: OK")
print(f"Provant posició mínima ({MIN_SERVO_US} µs)...")
servo_move_to(MIN_SERVO_US)
time.sleep(1.0)
print(f"Tornant a OPEN_POSITION...")
servo_move_to(OPEN_POSITION)
time.sleep(1.0)
_teardown(pi)
print("Test servo completat.\n")
# ==================
# TEST 2 — Sensor de color TCS34725
# ==================
def test_color_sensor():
"""
Llegeix el color 15 vegades cada segon.
Posa davant del sensor els blocs de colors per verificar que els reconeix.
"""
print("=== TEST SENSOR DE COLOR TCS34725 ===")
pi = _setup()
print("Llegint color durant 15 segons (posa els blocs davant del sensor)...")
for i in range(15):
color_id = read_block_color()
name = _COLOR_NAMES.get(color_id, "Desconegut")
print(f" Lectura {i+1:2d}: {name}")
time.sleep(1.0)
_teardown(pi)
print("Test sensor de color completat.\n")
# ==================
# TEST 3 — Calibració del sensor de color (valors RGB crus)
# ==================
def test_color_raw():
"""
Mostra valors RGB crus i la classificació actual durant 30 segons.
Útil per calibrar la taula _COLORS a blocks.py.
Format: R=xxx G=xxx B=xxx → classificat com 'XX' (diff=xx)
Si el diff és gran (>10), els valors de referència necessiten ajust.
"""
print("=== TEST COLOR RAW (calibració) ===")
pi = _setup()
print("Llegint valors RGB crus durant 30 segons (posa cada bloc davant del sensor)...")
print(f" {'R':>5} {'G':>5} {'B':>5} classificat diff")
for i in range(30):
r, g, b = read_color_raw()
best_name = "??"
best_diff = 9999
for ref in _COLORS:
diff = abs(r - ref["r"]) + abs(g - ref["g"]) + abs(b - ref["b"])
if diff < best_diff:
best_diff = diff
best_name = ref["name"]
print(f" R={r:3d} G={g:3d} B={b:3d}{best_name} (diff={best_diff})")
time.sleep(1.0)
_teardown(pi)
print("Test color raw completat.\n")
# ==================
# Execució
# ==================
if __name__ == "__main__":
# Descomenta el test que vols executar:
test_servo()
# test_color_sensor()
# test_color_raw() # Per calibrar la taula de colors

156
raspi/tests/test_eyes.py Normal file
View File

@@ -0,0 +1,156 @@
"""
test_eyes.py — Tests individuals del mòdul eyes.py.
Executa des del directori Rasp/: python tests/test_eyes.py
Descomenta la funció que vols provar al final del fitxer.
Assegura't que el venv està activat i pigpiod en marxa (sudo pigpiod -s 1).
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import time
import pigpio
from eyes import (
eyes_setup, eyes_cleanup,
eyes_turn_on, eyes_turn_off,
eyes_gesture_mode_on, eyes_gesture_mode_off, eyes_listening,
EYES_OPEN, EYES_FW, EYES_DOWN, EYES_GESTURE,
WHITE, RED, GREEN, BLUE, YELLOW, ORANGE, PURPLE, CYAN, BLACK,
)
def _setup():
pi = pigpio.pi()
if not pi.connected:
print("ERROR: pigpiod no està en marxa. Executa: sudo pigpiod -s 1")
sys.exit(1)
eyes_setup(pi)
return pi
def _teardown(pi):
eyes_cleanup()
pi.stop()
# ==================
# TEST 1 — Formes i colors bàsics
# ==================
def test_shapes():
"""
Mostra totes les formes existents en colors diferents.
Hauries de veure les formes als ulls LED del robot.
"""
print("=== TEST FORMES I COLORS ===")
pi = _setup()
print("EYES_OPEN en blanc...")
eyes_turn_on(EYES_OPEN, WHITE)
time.sleep(2.0)
print("EYES_FW en vermell...")
eyes_turn_on(EYES_FW, RED)
time.sleep(2.0)
print("EYES_DOWN en blau...")
eyes_turn_on(EYES_DOWN, BLUE)
time.sleep(2.0)
print("EYES_OPEN en verd...")
eyes_turn_on(EYES_OPEN, GREEN)
time.sleep(2.0)
print("Apagant...")
eyes_turn_off()
time.sleep(1.0)
_teardown(pi)
print("Test formes completat.\n")
# ==================
# TEST 2 — Animació de repeat i direcció
# ==================
def test_animation():
"""
Prova l'animació amb repeat i les dues direccions.
Hauries de veure els LEDs encenent-se un per un en ordre normal i invers.
"""
print("=== TEST ANIMACIÓ ===")
pi = _setup()
print("EYES_OPEN groc, repeat=2, endavant...")
eyes_turn_on(EYES_OPEN, YELLOW, repeat=2, forward=True)
time.sleep(1.0)
print("EYES_FW taronja, repeat=2, enrere...")
eyes_turn_on(EYES_FW, ORANGE, repeat=2, forward=False)
time.sleep(1.0)
eyes_turn_off()
_teardown(pi)
print("Test animació completat.\n")
# ==================
# TEST 3 — Animacions mode gestos (TFG)
# ==================
def test_gesture_animations():
"""
Prova les animacions específiques del mode gestos.
Hauries de veure: doble parpelleig cian, tornada a blanc, marc cian.
"""
print("=== TEST ANIMACIONS MODE GESTOS ===")
pi = _setup()
print("Activant mode gestos (doble parpelleig cian)...")
eyes_gesture_mode_on()
time.sleep(2.0)
print("Escoltant gest (marc cian)...")
eyes_listening()
time.sleep(2.0)
print("Desactivant mode gestos (torna a blanc)...")
eyes_gesture_mode_off()
time.sleep(2.0)
eyes_turn_off()
_teardown(pi)
print("Test animacions gestos completat.\n")
# ==================
# TEST 4 — Parpelleig (breathing)
# ==================
def test_breathing():
"""
Verifica que el thread de parpelleig funciona correctament.
Hauries de veure la brillantor dels LEDs pujant i baixant suaument.
"""
print("=== TEST PARPELLEIG (BREATHING) ===")
pi = _setup()
print("EYES_OPEN blanc — observa el parpelleig durant 10 segons...")
eyes_turn_on(EYES_OPEN, WHITE)
time.sleep(10.0)
eyes_turn_off()
_teardown(pi)
print("Test parpelleig completat.\n")
# ==================
# Execució
# ==================
if __name__ == "__main__":
# Descomenta el test que vols executar:
test_shapes()
# test_animation()
# test_gesture_animations()
# test_breathing()

View File

@@ -0,0 +1,94 @@
"""
test_gesture.py — Tests del mòdul gesture.py (sensor PAJ7620U2).
Executa des del directori Rasp/: python tests/test_gesture.py
Descomenta la funció que vols provar al final del fitxer.
Assegura't que el venv està activat i pigpiod en marxa (sudo pigpiod -s 1).
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import time
from gesture import (
gesture_setup, gesture_cleanup,
read_gesture,
GS_NONE, GS_FORWARD, GS_LEFT, GS_RIGHT,
GS_UP, GS_DOWN, GS_CLOCKWISE, GS_ANTICLOCKWISE, GS_WAVE,
)
_GESTURE_NAMES = {
GS_NONE: "Cap (GS_NONE)",
GS_FORWARD: "Endavant (GS_FORWARD)",
GS_LEFT: "Esquerra (GS_LEFT)",
GS_RIGHT: "Dreta (GS_RIGHT)",
GS_UP: "Amunt (GS_UP)",
GS_DOWN: "Avall (GS_DOWN)",
GS_CLOCKWISE: "Horari (GS_CLOCKWISE)",
GS_ANTICLOCKWISE: "Antihorari (GS_ANTICLOCKWISE)",
GS_WAVE: "Wave (GS_WAVE)",
}
# ==================
# TEST 1 — Connexió i inicialització
# ==================
def test_connection():
"""
Comprova que el sensor PAJ7620U2 és accessible via I2C.
Ha de mostrar 'Gesture sensor init OK' sense errors.
"""
print("=== TEST CONNEXIÓ PAJ7620U2 ===")
gesture_setup()
time.sleep(0.5)
gesture_cleanup()
print("Test connexió completat.\n")
# ==================
# TEST 2 — Lectura de gestos
# ==================
def test_read_gestures():
"""
Llegeix gestos durant 30 segons i els mostra per pantalla.
Fes gestos davant del sensor per verificar que els detecta correctament:
- Mà cap endavant/enrere → GS_FORWARD
- Mà cap a l'esquerra → GS_LEFT
- Mà cap a la dreta → GS_RIGHT
- Mà cap amunt → GS_UP
- Mà cap avall → GS_DOWN
- Rotació horària → GS_CLOCKWISE
- Rotació antihorària → GS_ANTICLOCKWISE
- Sacsejada (wave) → GS_WAVE
"""
print("=== TEST LECTURA GESTOS PAJ7620U2 ===")
print("Fes gestos davant del sensor durant 30 segons...")
gesture_setup()
time.sleep(0.5)
inici = time.time()
while time.time() - inici < 30:
gest = read_gesture()
if gest != GS_NONE:
nom = _GESTURE_NAMES.get(gest, f"Desconegut ({gest})")
print(f" Gest detectat: {nom}")
time.sleep(0.05)
gesture_cleanup()
print("Test lectura gestos completat.\n")
# ==================
# Execució
# ==================
if __name__ == "__main__":
# Descomenta el test que vols executar:
test_connection()
# test_read_gestures()

238
raspi/tests/test_motion.py Normal file
View File

@@ -0,0 +1,238 @@
"""
test_motion.py — Tests individuals del mòdul motion.py.
Executa des del directori Rasp/: python tests/test_motion.py
Descomenta la funció que vols provar al final del fitxer.
Assegura't que el venv està activat i pigpiod en marxa (sudo pigpiod -s 1).
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
import time
import pigpio
import motion
from motion import (
motion_setup, motion_setup_steppers, motion_setup_sensors, motion_cleanup,
enable_wheels, enable_arms, enable_syringe,
arms_home, syringe_home,
distance_to_object,
ON, OFF, CW, CCW,
)
def _pi_connect():
pi = pigpio.pi()
if not pi.connected:
print("ERROR: pigpiod no està en marxa. Executa: sudo pigpiod -s 1")
sys.exit(1)
return pi
def _setup_motors():
"""Setup mínim per a tests de motors (sense sensors I2C)."""
pi = _pi_connect()
motion_setup_steppers(pi)
return pi
def _setup_sensors():
"""Setup mínim per a tests de sensors I2C (sense steppers)."""
pi = _pi_connect()
motion_setup_sensors(pi)
return pi
def _teardown_motors(pi):
motion_cleanup()
pi.stop()
def _teardown_sensors(pi):
pi.stop()
# ==================
# TEST 1 — Motors pas a pas (rodes)
# ==================
def test_motor_unic():
"""
Prova únicament la roda DRETA: 200 passos endavant i enrere.
Primer test a fer — verifica que un sol motor funciona correctament.
Hauries de veure la roda girar ~1/5 de volta (reducció 1:5).
"""
print("=== TEST MOTOR ÚNIC (RODA DRETA) ===")
pi = _setup_motors()
PASSOS = 200
print(f"Movent roda DRETA {PASSOS} passos endavant...")
enable_wheels(ON)
motion.wheel_R.move_to(PASSOS)
while motion.wheel_R.is_running():
time.sleep(0.05)
print("Roda dreta endavant: OK")
time.sleep(0.5)
print(f"Movent roda DRETA {PASSOS} passos enrere...")
motion.wheel_R.move_to(0)
while motion.wheel_R.is_running():
time.sleep(0.05)
print("Roda dreta enrere: OK")
enable_wheels(OFF)
_teardown_motors(pi)
print("Test motor únic completat.\n")
def test_motors():
"""
Prova les dues rodes: avança 200 passos i torna enrere.
Executa test_motor_unic() primer per verificar que un motor funciona.
Hauries de veure cada roda girar ~1/5 de volta (reducció 1:5).
"""
print("=== TEST MOTORS (RODES) ===")
pi = _setup_motors()
PASSOS = 200
print(f"Movent roda DRETA {PASSOS} passos endavant...")
enable_wheels(ON)
motion.wheel_R.move_to(PASSOS)
while motion.wheel_R.is_running():
time.sleep(0.05)
print("Roda dreta: OK")
time.sleep(0.5)
print(f"Movent roda DRETA {PASSOS} passos enrere...")
motion.wheel_R.move_to(0)
while motion.wheel_R.is_running():
time.sleep(0.05)
print("Roda dreta enrere: OK")
time.sleep(0.5)
print(f"Movent roda ESQUERRA {PASSOS} passos endavant...")
motion.wheel_L.move_to(PASSOS)
while motion.wheel_L.is_running():
time.sleep(0.05)
print("Roda esquerra: OK")
time.sleep(0.5)
print(f"Movent roda ESQUERRA {PASSOS} passos enrere...")
motion.wheel_L.move_to(0)
while motion.wheel_L.is_running():
time.sleep(0.05)
print("Roda esquerra enrere: OK")
enable_wheels(OFF)
_teardown_motors(pi)
print("Test motors completat.\n")
# ==================
# TEST 2 — Homing (finals de carrera)
# ==================
def test_homing_brac():
"""
Executa el homing únicament dels BRAÇOS.
Primer test de homing — verifica que un sol conjunt de finals de carrera funciona.
ATENCIÓ: assegura't que els braços tinguin espai per moure's.
"""
print("=== TEST HOMING BRAÇOS ===")
pi = _setup_motors()
print("Iniciant homing dels BRAÇOS...")
arms_home()
print("Homing braços: OK")
_teardown_motors(pi)
print("Test homing braços completat.\n")
def test_homing():
"""
Executa el homing complet: braços i xeringa.
Executa test_homing_brac() primer per verificar els finals de carrera dels braços.
ATENCIÓ: assegura't que els braços i la xeringa tinguin espai per moure's.
"""
print("=== TEST HOMING COMPLET ===")
pi = _setup_motors()
print("Iniciant homing dels BRAÇOS...")
arms_home()
print("Homing braços: OK")
time.sleep(1.0)
print("Iniciant homing de la XERINGA...")
syringe_home()
print("Homing xeringa: OK")
_teardown_motors(pi)
print("Test homing completat.\n")
# ==================
# TEST 3 — Sensor de distància VL53L0X
# ==================
def test_distance_sensor():
"""
Llegeix la distància 10 vegades cada 500ms.
Posa la mà davant del sensor per verificar que canvia el valor.
"""
print("=== TEST SENSOR DISTÀNCIA VL53L0X ===")
pi = _setup_sensors()
print("Llegint distància durant 5 segons (posa la mà davant del sensor)...")
for i in range(10):
dist = distance_to_object()
if dist == 65535:
print(f" Lectura {i+1:2d}: fora de rang")
else:
print(f" Lectura {i+1:2d}: {dist} mm")
time.sleep(0.5)
_teardown_sensors(pi)
print("Test sensor distància completat.\n")
# ==================
# TEST 4 — Sensors de línia ADS1115
# ==================
def test_line_sensors():
"""
Llegeix els dos sensors de línia 10 vegades cada 500ms.
Posa el sensor sobre superfícies de diferent color per veure la variació.
Valor alt (~9700+) = negre. Valor baix = blanc/clar.
"""
print("=== TEST SENSORS DE LÍNIA ADS1115 ===")
pi = _setup_sensors()
print("Llegint sensors de línia durant 5 segons...")
print(" (posa els sensors sobre blanc i negre per veure la diferència)")
for i in range(10):
r = motion._chan_r.value
l = motion._chan_l.value
print(f" Lectura {i+1:2d}: DRETA={r:5d} ESQUERRA={l:5d} error={r-l:+6d}")
time.sleep(0.5)
_teardown_sensors(pi)
print("Test sensors de línia completat.\n")
# ==================
# Execució
# ==================
if __name__ == "__main__":
# Descomenta el test que vols executar:
test_motor_unic() # Primer: prova un sol motor
# test_motors() # Segon: prova les dues rodes
# test_homing_brac() # Primer homing: només els braços
# test_homing() # Homing complet: braços i xeringa
# test_distance_sensor()
# test_line_sensors()

View File

@@ -0,0 +1,53 @@
"""
test_simple_motor.py — Test mínim de la roda dreta per diagnosticar problemes.
Executa des del directori Rasp/tests/: python3 test_simple_motor.py
Diferències respecte a test_motion.py:
- Usa pi.write() directe en lloc de gpio_trigger()
- Bucle bloquejant amb time.sleep() en lloc de thread
- Sense acceleració, velocitat constant
"""
import pigpio
import time
STEP = 25 # STEP_R_W
DIR = 23 # DIR_R_W
EN = 6 # EN_W (actiu LOW)
pi = pigpio.pi()
if not pi.connected:
print("ERROR: pigpiod no està en marxa")
exit(1)
pi.set_mode(STEP, pigpio.OUTPUT)
pi.set_mode(DIR, pigpio.OUTPUT)
pi.set_mode(EN, pigpio.OUTPUT)
pi.write(EN, 0) # Activa el driver (LOW = ON)
pi.write(DIR, 1) # Endavant
# 500 passos/s → període = 1/500 = 2ms → mig període = 1ms
DELAY = 0.001
print("Movent 200 passos endavant...")
for _ in range(200):
pi.write(STEP, 1)
time.sleep(DELAY)
pi.write(STEP, 0)
time.sleep(DELAY)
print("Fet. Esperant 1s...")
time.sleep(1)
pi.write(DIR, 0) # Enrere
print("Movent 200 passos enrere...")
for _ in range(200):
pi.write(STEP, 1)
time.sleep(DELAY)
pi.write(STEP, 0)
time.sleep(DELAY)
print("Fet.")
pi.write(EN, 1) # Desactiva el driver
pi.stop()