stm32-moto/Core/Src/moto_config.c

197 lines
7.0 KiB
C

/**
* @file moto_config.c
* @brief Implémentation des fonctions utilitaires pour système IMU moto
*/
#include "moto_config.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
//------------------------------------------------------------------------------
// Fonctions publiques
//------------------------------------------------------------------------------
void Moto_InitData(MotoData_t *data) {
memset(data, 0, sizeof(MotoData_t));
data->state = MOTO_STATE_NORMAL;
data->is_initializing = true;
data->last_update_time = 0;
}
void Moto_UpdateState(MotoData_t *data, float roll, float pitch, float yaw,
float gyro_x, float gyro_y, float gyro_z) {
// Mise à jour des angles bruts
data->roll = roll;
data->pitch = pitch;
data->yaw = yaw;
// Calcul de la magnitude de la vitesse angulaire
float gyro_magnitude = sqrtf(gyro_x*gyro_x + gyro_y*gyro_y + gyro_z*gyro_z);
// Détection d'état prioritaire : crash possible
if (Moto_DetectCrash(data, gyro_magnitude)) {
data->state = MOTO_STATE_POSSIBLE_CRASH;
return;
}
// Détection de wheelie/stoppie
if (pitch > MOTO_PITCH_WHEELIE_THRESHOLD) {
data->state = MOTO_STATE_WHEELIE;
} else if (pitch < MOTO_PITCH_STOPPIE_THRESHOLD) {
data->state = MOTO_STATE_STOPPIE;
}
// Détection de virage rapide
else if (fabsf(gyro_z) > MOTO_GYRO_RAPID_TURN_THRESHOLD) {
data->state = MOTO_STATE_RAPID_TURN;
}
// Détection d'inclinaison dangereuse
else if (fabsf(roll) > MOTO_ROLL_DANGER_THRESHOLD) {
data->state = MOTO_STATE_DANGER;
}
// Détection d'inclinaison d'avertissement
else if (fabsf(roll) > MOTO_ROLL_WARNING_THRESHOLD) {
data->state = MOTO_STATE_WARNING;
}
// État normal
else {
data->state = MOTO_STATE_NORMAL;
data->crash_detect_counter = 0; // Reset compteur crash
}
}
void Moto_FilterAngles(MotoData_t *data) {
// Filtre passe-bas simple pour lisser l'affichage
data->roll_filtered = MOTO_ANGLE_FILTER_ALPHA * data->roll +
(1.0f - MOTO_ANGLE_FILTER_ALPHA) * data->roll_filtered;
data->pitch_filtered = MOTO_ANGLE_FILTER_ALPHA * data->pitch +
(1.0f - MOTO_ANGLE_FILTER_ALPHA) * data->pitch_filtered;
data->yaw_filtered = MOTO_ANGLE_FILTER_ALPHA * data->yaw +
(1.0f - MOTO_ANGLE_FILTER_ALPHA) * data->yaw_filtered;
}
const char* Moto_GetStateString(MotoState_t state) {
switch (state) {
case MOTO_STATE_NORMAL: return "NORMAL ";
case MOTO_STATE_WARNING: return "ATTENTION ";
case MOTO_STATE_DANGER: return "DANGER ";
case MOTO_STATE_WHEELIE: return "WHEELIE ";
case MOTO_STATE_STOPPIE: return "STOPPIE ";
case MOTO_STATE_RAPID_TURN: return "VIRAGE RAPIDE ";
case MOTO_STATE_POSSIBLE_CRASH: return "CHUTE POSSIBLE";
default: return "INCONNU";
}
}
void Moto_UpdateStats(MotoStats_t *stats, const MotoData_t *data,
float gyro_x, float gyro_y, float gyro_z) {
stats->total_samples++;
// Mise à jour des extremums d'angles
if (data->roll > stats->max_roll) stats->max_roll = data->roll;
if (data->roll < stats->min_roll) stats->min_roll = data->roll;
if (data->pitch > stats->max_pitch) stats->max_pitch = data->pitch;
if (data->pitch < stats->min_pitch) stats->min_pitch = data->pitch;
// Mise à jour des extremums de vitesse angulaire
if (fabsf(gyro_x) > stats->max_gyro_x) stats->max_gyro_x = fabsf(gyro_x);
if (fabsf(gyro_y) > stats->max_gyro_y) stats->max_gyro_y = fabsf(gyro_y);
if (fabsf(gyro_z) > stats->max_gyro_z) stats->max_gyro_z = fabsf(gyro_z);
// Comptage des états d'alerte
if (data->state == MOTO_STATE_WARNING) stats->warning_count++;
if (data->state == MOTO_STATE_DANGER ||
data->state == MOTO_STATE_POSSIBLE_CRASH) stats->danger_count++;
}
void Moto_CalibrateMagnetometer(float *mx, float *my, float *mz) {
// Application des offsets et facteurs d'échelle
*mx = (*mx - MOTO_MAG_OFFSET_X) * MOTO_MAG_SCALE_X;
*my = (*my - MOTO_MAG_OFFSET_Y) * MOTO_MAG_SCALE_Y;
*mz = (*mz - MOTO_MAG_OFFSET_Z) * MOTO_MAG_SCALE_Z;
}
bool Moto_DetectCrash(MotoData_t *data, float gyro_magnitude) {
if (gyro_magnitude > MOTO_GYRO_CRASH_THRESHOLD) {
data->crash_detect_counter++;
// Confirme la chute si seuil dépassé pendant plusieurs échantillons
if (data->crash_detect_counter > 5) { // ~50ms à 100Hz
return true;
}
} else {
// Décrémente progressivement le compteur
if (data->crash_detect_counter > 0) {
data->crash_detect_counter--;
}
}
return false;
}
void Moto_FormatDisplay(const MotoData_t *data, int line, char *buffer) {
switch (line) {
case 0:
snprintf(buffer, 21, "R:%5.1f P:%5.1f",
data->roll_filtered, data->pitch_filtered);
break;
case 1:
snprintf(buffer, 21, "Yaw: %6.1f deg", data->yaw_filtered);
break;
case 2:
snprintf(buffer, 21, "Etat: %s", Moto_GetStateString(data->state));
break;
case 3:
if (data->is_initializing) {
snprintf(buffer, 21, "---- INIT EN COURS ----");
} else {
switch (data->state) {
case MOTO_STATE_NORMAL:
snprintf(buffer, 21, "---- EQUILIBRE ----");
break;
case MOTO_STATE_WARNING:
if (data->roll > 0) {
snprintf(buffer, 21, "INCLIN. DROITE >>>");
} else {
snprintf(buffer, 21, "<<< INCLIN. GAUCHE");
}
break;
case MOTO_STATE_DANGER:
case MOTO_STATE_POSSIBLE_CRASH:
snprintf(buffer, 21, "!!! ATTENTION !!! ");
break;
case MOTO_STATE_WHEELIE:
snprintf(buffer, 21, "^^^ WHEELIE ^^^ ");
break;
case MOTO_STATE_STOPPIE:
snprintf(buffer, 21, "vvv STOPPIE vvv ");
break;
case MOTO_STATE_RAPID_TURN:
snprintf(buffer, 21, ">>> VIRAGE <<< ");
break;
default:
snprintf(buffer, 21, "--- INCONNU --- ");
break;
}
}
break;
default:
snprintf(buffer, 21, "Ligne invalide");
break;
}
}
//------------------------------------------------------------------------------
// Fonctions utilitaires privées
//------------------------------------------------------------------------------
// Ajouter ici d'autres fonctions utilitaires si nécessaire