Python: calibration tool — ligne orange pic dernier tir + titre simplifié
Ajoute une ligne horizontale orange sur chaque graphe indiquant le niveau atteint au moment du dernier tir détecté, avec % du seuil dans le titre. Permet de comprendre pourquoi un tir est déclenché même si le pic BLE (20Hz) ne semble pas dépasser le seuil (résolution temporelle limitée). Supprime le pic 1s (remplacé par le pic dernier tir, plus pertinent). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f23ddf9a82
commit
f33fd5b216
@ -34,6 +34,8 @@ thresholds = {"accel": 2.5, "gyro": 200.0, "audio": 3000} # PDM : 0-32767
|
||||
min_sensors = 3 # Nb de capteurs requis simultanément (1-3) — NUM6=+1 NUM4=-1
|
||||
shot_count = 0
|
||||
shot_pending = False # Flag : un tir reçu, à enregistrer dans shot_buf au prochain debug tick
|
||||
# Pic max au moment du dernier tir (mis à jour au moment où shot_pending devient True)
|
||||
last_shot_peak = {"accel": 0.0, "gyro": 0.0, "audio": 0}
|
||||
ble_status = "🔍 Connexion..."
|
||||
ble_running = True
|
||||
audio_max_global = 1000 # Tracks le max absolu jamais vu
|
||||
@ -66,10 +68,14 @@ def debug_callback(sender, data):
|
||||
shot_pending = False
|
||||
|
||||
def shot_callback(sender, data):
|
||||
global shot_count, shot_pending
|
||||
global shot_count, shot_pending, last_shot_peak
|
||||
if data[0] == 1:
|
||||
shot_count += 1
|
||||
shot_pending = True
|
||||
# Capturer le pic courant au moment exact du tir (meilleure approximation possible en BLE)
|
||||
last_shot_peak["accel"] = accel_buf[-1] if accel_buf else 0.0
|
||||
last_shot_peak["gyro"] = gyro_buf[-1] if gyro_buf else 0.0
|
||||
last_shot_peak["audio"] = audio_buf[-1] if audio_buf else 0
|
||||
|
||||
async def find_device():
|
||||
"""Scan par nom (toutes les 0.5s pendant 30s max).
|
||||
@ -235,11 +241,16 @@ thr_a = axes[0].axhline(thresholds["accel"], color=CT, ls='--', lw=1.5, label='S
|
||||
thr_g = axes[1].axhline(thresholds["gyro"], color=CT, ls='--', lw=1.5, label='Seuil (trigger XIAO)')
|
||||
thr_m = axes[2].axhline(thresholds["audio"], color=CT, ls='--', lw=1.5, label='Seuil (trigger XIAO)')
|
||||
|
||||
# Légendes — incluent le fond rouge = trigger actif
|
||||
# Ligne horizontale orange = pic au moment du dernier tir (invisible au départ)
|
||||
peak_a = axes[0].axhline(0, color=CS, ls='-', lw=1.5, alpha=0.0, label='Pic dernier tir')
|
||||
peak_g = axes[1].axhline(0, color=CS, ls='-', lw=1.5, alpha=0.0, label='Pic dernier tir')
|
||||
peak_m = axes[2].axhline(0, color=CS, ls='-', lw=1.5, alpha=0.0, label='Pic dernier tir')
|
||||
|
||||
# Légendes
|
||||
for ax in axes[:3]:
|
||||
ax.legend(loc='upper left', fontsize=7, facecolor=PANEL, edgecolor='#444466',
|
||||
labelcolor=TEXT, framealpha=0.8,
|
||||
handles=[ax.get_lines()[0], ax.get_lines()[1],
|
||||
handles=[ax.get_lines()[0], ax.get_lines()[1], ax.get_lines()[2],
|
||||
plt.Rectangle((0,0),1,1, fc=CT, alpha=0.25, label='Trigger actif (XIAO)')])
|
||||
|
||||
from matplotlib.patches import Rectangle
|
||||
@ -279,17 +290,25 @@ def update(frame):
|
||||
m = np.array(audio_buf, dtype=float)
|
||||
s = np.array(shot_buf)
|
||||
|
||||
# Pic max sur la dernière seconde (pour affichage dans le titre)
|
||||
a_peak = float(a[-PEAK_WINDOW:].max())
|
||||
g_peak = float(g[-PEAK_WINDOW:].max())
|
||||
m_peak = float(m[-PEAK_WINDOW:].max())
|
||||
|
||||
# Mise à jour des données des lignes
|
||||
# Mise à jour des données des lignes brutes
|
||||
line_a.set_ydata(a)
|
||||
line_g.set_ydata(g)
|
||||
line_m.set_ydata(m)
|
||||
line_s.set_ydata(s)
|
||||
|
||||
# Ligne orange = pic au moment du dernier tir (visible seulement si un tir a eu lieu)
|
||||
if shot_count > 0:
|
||||
peak_a.set_ydata([last_shot_peak["accel"]] * 2)
|
||||
peak_g.set_ydata([last_shot_peak["gyro"]] * 2)
|
||||
peak_m.set_ydata([last_shot_peak["audio"]] * 2)
|
||||
peak_a.set_alpha(0.9)
|
||||
peak_g.set_alpha(0.9)
|
||||
peak_m.set_alpha(0.9)
|
||||
else:
|
||||
peak_a.set_alpha(0.0)
|
||||
peak_g.set_alpha(0.0)
|
||||
peak_m.set_alpha(0.0)
|
||||
|
||||
# Mise à jour des seuils
|
||||
thr_a.set_ydata([thresholds["accel"], thresholds["accel"]])
|
||||
thr_g.set_ydata([thresholds["gyro"], thresholds["gyro"]])
|
||||
@ -310,22 +329,22 @@ def update(frame):
|
||||
for i, span in enumerate(shot_spans):
|
||||
span.set_alpha(0.85 if i < len(sl) and sl[i] > 0 else 0)
|
||||
|
||||
# Titres avec valeurs courantes
|
||||
a_ratio = a_peak / thresholds['accel'] * 100
|
||||
g_ratio = g_peak / thresholds['gyro'] * 100
|
||||
m_ratio = m_peak / thresholds['audio'] * 100
|
||||
# Titres avec valeurs courantes + pic dernier tir
|
||||
pa = last_shot_peak["accel"] if shot_count > 0 else None
|
||||
pg = last_shot_peak["gyro"] if shot_count > 0 else None
|
||||
pm = last_shot_peak["audio"] if shot_count > 0 else None
|
||||
titles[0].set_text(
|
||||
f"Accelerometre "
|
||||
f"val: {a[-1]:.2f} G pic(1s): {a_peak:.2f} G seuil: {thresholds['accel']:.1f} G "
|
||||
f"({a_ratio:.0f}% du seuil) [NUM7=+0.1 NUM1=-0.1]")
|
||||
f"Accelerometre val: {a[-1]:.2f} G seuil: {thresholds['accel']:.1f} G"
|
||||
+ (f" ── pic dernier tir: {pa:.2f} G ({pa/thresholds['accel']*100:.0f}%)" if pa else "")
|
||||
+ f" [NUM7=+0.1 NUM1=-0.1]")
|
||||
titles[1].set_text(
|
||||
f"Gyroscope "
|
||||
f"val: {g[-1]:.0f} dps pic(1s): {g_peak:.0f} dps seuil: {thresholds['gyro']:.0f} dps "
|
||||
f"({g_ratio:.0f}% du seuil) [NUM8=+10 NUM2=-10]")
|
||||
f"Gyroscope val: {g[-1]:.0f} dps seuil: {thresholds['gyro']:.0f} dps"
|
||||
+ (f" ── pic dernier tir: {pg:.0f} dps ({pg/thresholds['gyro']*100:.0f}%)" if pg else "")
|
||||
+ f" [NUM8=+10 NUM2=-10]")
|
||||
titles[2].set_text(
|
||||
f"Microphone PDM "
|
||||
f"val: {m[-1]:.0f} pic(1s): {m_peak:.0f} seuil: {thresholds['audio']} "
|
||||
f"({m_ratio:.0f}% du seuil) [NUM9=+500 NUM3=-500]")
|
||||
f"Microphone PDM val: {m[-1]:.0f} seuil: {thresholds['audio']}"
|
||||
+ (f" ── pic dernier tir: {pm:.0f} ({pm/thresholds['audio']*100:.0f}%)" if pm else "")
|
||||
+ f" [NUM9=+500 NUM3=-500]")
|
||||
titles[3].set_text(f"Tirs detectes : {shot_count} (fenetre glissante)")
|
||||
|
||||
status_txt.set_text(
|
||||
@ -336,6 +355,7 @@ def update(frame):
|
||||
|
||||
return (line_a, line_g, line_m, line_s,
|
||||
thr_a, thr_g, thr_m,
|
||||
peak_a, peak_g, peak_m,
|
||||
*titles, status_txt, debug_txt)
|
||||
|
||||
def on_key(event):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user