Python: calibration tool — correction logique fenêtre glissante
Remplace la moyenne glissante par un max glissant sur 3 samples (60ms), ce qui reflète fidèlement la logique réelle du XIAO : la valeur brute est comparée au seuil et le trigger reste actif 60ms (pas de moyenne). Légende mise à jour en conséquence. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6048ed9066
commit
3bb8d6c58a
@ -44,8 +44,10 @@ debug_mode = 3 # 0=OFF, 1=RAW, 2=TRIGGERS, 3=FULL (actif par défaut)
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
X = np.arange(WINDOW_SIZE) # axe X fixe, ne change jamais
|
X = np.arange(WINDOW_SIZE) # axe X fixe, ne change jamais
|
||||||
|
|
||||||
# Fenêtre de moyenne glissante en samples (60ms window / 50ms debug rate = ~1.2 → 3 samples min)
|
# Fenêtre en samples correspondant à la Window du XIAO (60ms / 50ms debug rate = ~1.2 → 3 samples)
|
||||||
AVG_WINDOW = 3 # correspond à la accelWindow/gyroWindow/audioWindow envoyée au XIAO (60ms @ 20Hz)
|
# Le XIAO ne fait PAS de moyenne : il compare la valeur brute au seuil et maintient le trigger 60ms.
|
||||||
|
# On affiche donc le MAX glissant sur 3 samples = ce que le XIAO "retient" comme pic actif.
|
||||||
|
AVG_WINDOW = 3
|
||||||
|
|
||||||
# ─── BLE ────────────────────────────────────────────────
|
# ─── BLE ────────────────────────────────────────────────
|
||||||
def debug_callback(sender, data):
|
def debug_callback(sender, data):
|
||||||
@ -231,9 +233,9 @@ axes[3].set_yticks([]) # pas de graduations Y sur la timeline
|
|||||||
line_a, = axes[0].plot(X, list(accel_buf), color=CA, lw=1.0, alpha=0.5, label='Brut')
|
line_a, = axes[0].plot(X, list(accel_buf), color=CA, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_g, = axes[1].plot(X, list(gyro_buf), color=CG, lw=1.0, alpha=0.5, label='Brut')
|
line_g, = axes[1].plot(X, list(gyro_buf), color=CG, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_m, = axes[2].plot(X, list(audio_buf), color=CM, lw=1.0, alpha=0.5, label='Brut')
|
line_m, = axes[2].plot(X, list(audio_buf), color=CM, lw=1.0, alpha=0.5, label='Brut')
|
||||||
line_a2, = axes[0].plot(X, list(accel_buf), color=CA2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
line_a2, = axes[0].plot(X, list(accel_buf), color=CA2, lw=2.0, label=f'Pic maintenu ({AVG_WINDOW} pts / 60ms) ← logique XIAO')
|
||||||
line_g2, = axes[1].plot(X, list(gyro_buf), color=CG2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
line_g2, = axes[1].plot(X, list(gyro_buf), color=CG2, lw=2.0, label=f'Pic maintenu ({AVG_WINDOW} pts / 60ms) ← logique XIAO')
|
||||||
line_m2, = axes[2].plot(X, list(audio_buf), color=CM2, lw=2.0, label=f'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
line_m2, = axes[2].plot(X, list(audio_buf), color=CM2, lw=2.0, label=f'Pic maintenu ({AVG_WINDOW} pts / 60ms) ← logique XIAO')
|
||||||
line_s, = axes[3].plot(X, list(shot_buf), color=CS, lw=0, marker='|',
|
line_s, = axes[3].plot(X, list(shot_buf), color=CS, lw=0, marker='|',
|
||||||
markersize=20, markeredgewidth=2.5) # barres verticales
|
markersize=20, markeredgewidth=2.5) # barres verticales
|
||||||
|
|
||||||
@ -276,10 +278,12 @@ def update_spans(spans, trig_list):
|
|||||||
for i, span in enumerate(spans):
|
for i, span in enumerate(spans):
|
||||||
span.set_alpha(0.25 if i < len(tl) and tl[i] else 0)
|
span.set_alpha(0.25 if i < len(tl) and tl[i] else 0)
|
||||||
|
|
||||||
def rolling_avg(arr, window):
|
def rolling_max(arr, window):
|
||||||
"""Moyenne glissante simple — même logique que le XIAO"""
|
"""Max glissant — simule le trigger qui reste actif pendant 'window' samples (logique XIAO)"""
|
||||||
kernel = np.ones(window) / window
|
from numpy.lib.stride_tricks import sliding_window_view
|
||||||
return np.convolve(arr, kernel, mode='same')
|
pad = window - 1
|
||||||
|
padded = np.pad(arr, (pad, 0), mode='edge')
|
||||||
|
return np.max(sliding_window_view(padded, window), axis=1)
|
||||||
|
|
||||||
def update(frame):
|
def update(frame):
|
||||||
# Snapshot des buffers (rapide)
|
# Snapshot des buffers (rapide)
|
||||||
@ -288,10 +292,10 @@ def update(frame):
|
|||||||
m = np.array(audio_buf, dtype=float)
|
m = np.array(audio_buf, dtype=float)
|
||||||
s = np.array(shot_buf)
|
s = np.array(shot_buf)
|
||||||
|
|
||||||
# Moyennes glissantes (même fenêtre que le XIAO)
|
# Pic maintenu sur la fenêtre (même logique que le trigger XIAO)
|
||||||
a_avg = rolling_avg(a, AVG_WINDOW)
|
a_avg = rolling_max(a, AVG_WINDOW)
|
||||||
g_avg = rolling_avg(g, AVG_WINDOW)
|
g_avg = rolling_max(g, AVG_WINDOW)
|
||||||
m_avg = rolling_avg(m, AVG_WINDOW)
|
m_avg = rolling_max(m, AVG_WINDOW)
|
||||||
|
|
||||||
# Mise à jour des données des lignes
|
# Mise à jour des données des lignes
|
||||||
line_a.set_ydata(a)
|
line_a.set_ydata(a)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user