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
|
||||
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)
|
||||
AVG_WINDOW = 3 # correspond à la accelWindow/gyroWindow/audioWindow envoyée au XIAO (60ms @ 20Hz)
|
||||
# Fenêtre en samples correspondant à la Window du XIAO (60ms / 50ms debug rate = ~1.2 → 3 samples)
|
||||
# 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 ────────────────────────────────────────────────
|
||||
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_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_a2, = axes[0].plot(X, list(accel_buf), color=CA2, 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'Moyenne ({AVG_WINDOW} pts / 60ms)')
|
||||
line_m2, = axes[2].plot(X, list(audio_buf), color=CM2, 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'Pic maintenu ({AVG_WINDOW} pts / 60ms) ← logique XIAO')
|
||||
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='|',
|
||||
markersize=20, markeredgewidth=2.5) # barres verticales
|
||||
|
||||
@ -276,10 +278,12 @@ def update_spans(spans, trig_list):
|
||||
for i, span in enumerate(spans):
|
||||
span.set_alpha(0.25 if i < len(tl) and tl[i] else 0)
|
||||
|
||||
def rolling_avg(arr, window):
|
||||
"""Moyenne glissante simple — même logique que le XIAO"""
|
||||
kernel = np.ones(window) / window
|
||||
return np.convolve(arr, kernel, mode='same')
|
||||
def rolling_max(arr, window):
|
||||
"""Max glissant — simule le trigger qui reste actif pendant 'window' samples (logique XIAO)"""
|
||||
from numpy.lib.stride_tricks import sliding_window_view
|
||||
pad = window - 1
|
||||
padded = np.pad(arr, (pad, 0), mode='edge')
|
||||
return np.max(sliding_window_view(padded, window), axis=1)
|
||||
|
||||
def update(frame):
|
||||
# Snapshot des buffers (rapide)
|
||||
@ -288,10 +292,10 @@ def update(frame):
|
||||
m = np.array(audio_buf, dtype=float)
|
||||
s = np.array(shot_buf)
|
||||
|
||||
# Moyennes glissantes (même fenêtre que le XIAO)
|
||||
a_avg = rolling_avg(a, AVG_WINDOW)
|
||||
g_avg = rolling_avg(g, AVG_WINDOW)
|
||||
m_avg = rolling_avg(m, AVG_WINDOW)
|
||||
# Pic maintenu sur la fenêtre (même logique que le trigger XIAO)
|
||||
a_avg = rolling_max(a, AVG_WINDOW)
|
||||
g_avg = rolling_max(g, AVG_WINDOW)
|
||||
m_avg = rolling_max(m, AVG_WINDOW)
|
||||
|
||||
# Mise à jour des données des lignes
|
||||
line_a.set_ydata(a)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user