Machine d'etats LED, protection thermique, et correctif checksum RX
CORRECTIF CRITIQUE -- reception UART cassee (uart_link.c) Le decodage du checksum utilisait strtol sur s_line, qui n'est JAMAIS terminee par un '\0'. strtol lisait donc au-dela de la trame, dans les residus de la ligne precedente. Aggravant, specifique au C28x : uint8_t y fait 16 bits (pas d'adressage par octet), donc le cast (uint8_t) ne tronquait rien. Un "7D" suivi d'un "7D" residuel donnait 0x7D7D = 32125, conserve tel quel, et TOUTE trame etait rejetee. Sur une architecture a octets le cast aurait masque le probleme et le bug serait passe inapercu. Constate sur cible : cs_calc = 0x7D (correct), cs_recv = 0x7D7D. Consequence visible : plus aucune commande $C acceptee, donc timeout de liaison permanent alors que l'ESP32 emettait correctement. Remplace par parse_hex2(), borne a exactement deux chiffres, qui ne depend d'aucune terminaison et rejette un checksum malforme. Supprime au passage la dependance a stdlib. status_led.c/h -- affichage d'etat STARTUP bleu fixe (1 s minimum, sinon jamais visible) NOMINAL bleu 0,2 / 1,8 s LINK_LOST bleu 0,2 / 0,2 s (> 2 s sans trame $C valide) EMUSTOP alternance bleu/rouge 0,5 / 0,5 s OVERTEMP rouge 0,5 / 0,5 s OVERCURRENT rouge fixe Priorite : surintensite > surtemperature > EMUSTOP > liaison perdue. La surintensite passe devant EMUSTOP : en developpement EMUSTOP se declenche en permanence et ne doit jamais masquer un defaut de puissance. Limite de principe : pendant une halte CPU, plus aucun code ne tourne, les GPIO restent figes sur la phase courante du motif. L'alternance EMUSTOP est donc un indicateur a posteriori, jamais un etat live. safety.c/h -- origine du trip TZFLG.DCAEVT1 (bit 3) est distinct de TZFLG.OST (bit 2), ce qui permet de separer une surintensite reelle (comparateur) d'un arret du debugger. Les ISR ne pilotent plus les LED, elles ne font que relever la cause. Protection thermique (main.c, calib.h) Seuil 85 degC avec hysteresis de 10 degC, coupure du PWM et de HV_EN. Lente par nature, donc entierement logicielle -- aucun chemin materiel requis, contrairement a la surintensite. Pas de redemarrage automatique : rien ne reactive le PWM une fois coupe. Seuil PROVISOIRE : les NTC sont a 5 mm des MOSFET, donc elles mesurent le cuivre et non la jonction (ecart statique et retard thermique notables). A recaler quand la temperature de boitier en charge sera connue. Valide sur cible : commandes $C de nouveau acceptees, chaine NTC lue a 24,5 / 24,7 degC sur pont 10k/10k (coherent avec des resistances a 1 %). Note : un pont 10k/10k ne discrimine PAS le sens de la formule NTC, les deux formes coincidant au point d'equilibre. Verification a faire avec une resistance asymetrique (4,7 kOhm -> environ 47 degC). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
96
src/status_led.c
Normal file
96
src/status_led.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "status_led.h"
|
||||
#include "bsp_gpio.h"
|
||||
|
||||
// Durees exprimees en ticks de 10 ms. Ce sont des constantes de
|
||||
// presentation, pas de calibration materielle : elles restent ici plutot
|
||||
// que dans calib.h, qui decrit la carte.
|
||||
#define TICKS_PER_100MS 10U
|
||||
|
||||
#define STARTUP_MIN_TICKS 100U // 1 s : rend l'etat de demarrage visible
|
||||
|
||||
#define NOMINAL_PERIOD 200U // 2,0 s
|
||||
#define NOMINAL_ON 20U // 0,2 s
|
||||
|
||||
#define LINK_LOST_PERIOD 40U // 0,4 s
|
||||
#define LINK_LOST_ON 20U // 0,2 s
|
||||
|
||||
#define EMUSTOP_PERIOD 100U // 1,0 s
|
||||
#define EMUSTOP_HALF 50U // 0,5 s bleu puis 0,5 s rouge
|
||||
|
||||
#define OVERTEMP_PERIOD 100U // 1,0 s
|
||||
#define OVERTEMP_ON 50U // 0,5 s
|
||||
|
||||
static led_state_t s_state = LED_STATE_STARTUP;
|
||||
static uint16_t s_phase = 0; // position dans le motif courant
|
||||
static uint16_t s_startup_hold = STARTUP_MIN_TICKS;
|
||||
|
||||
void status_led_init(void)
|
||||
{
|
||||
s_state = LED_STATE_STARTUP;
|
||||
s_phase = 0;
|
||||
s_startup_hold = STARTUP_MIN_TICKS;
|
||||
|
||||
led_set(LED_BLUE, true);
|
||||
led_set(LED_RED, false);
|
||||
}
|
||||
|
||||
void status_led_set_state(led_state_t state)
|
||||
{
|
||||
if (s_startup_hold != 0U)
|
||||
{
|
||||
return; // duree minimale de l'etat de demarrage non ecoulee
|
||||
}
|
||||
|
||||
if (state != s_state)
|
||||
{
|
||||
s_state = state;
|
||||
s_phase = 0; // le motif repart proprement a son debut
|
||||
}
|
||||
}
|
||||
|
||||
void status_led_tick(void)
|
||||
{
|
||||
bool blue = false;
|
||||
bool red = false;
|
||||
|
||||
if (s_startup_hold != 0U)
|
||||
{
|
||||
s_startup_hold--;
|
||||
}
|
||||
|
||||
s_phase++;
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case LED_STATE_NOMINAL:
|
||||
blue = ((s_phase % NOMINAL_PERIOD) < NOMINAL_ON);
|
||||
break;
|
||||
|
||||
case LED_STATE_LINK_LOST:
|
||||
blue = ((s_phase % LINK_LOST_PERIOD) < LINK_LOST_ON);
|
||||
break;
|
||||
|
||||
case LED_STATE_EMUSTOP:
|
||||
blue = ((s_phase % EMUSTOP_PERIOD) < EMUSTOP_HALF);
|
||||
red = !blue;
|
||||
break;
|
||||
|
||||
case LED_STATE_OVERTEMP:
|
||||
red = ((s_phase % OVERTEMP_PERIOD) < OVERTEMP_ON);
|
||||
break;
|
||||
|
||||
case LED_STATE_OVERCURRENT:
|
||||
red = true;
|
||||
break;
|
||||
|
||||
case LED_STATE_STARTUP:
|
||||
default:
|
||||
blue = true;
|
||||
break;
|
||||
}
|
||||
|
||||
led_set(LED_BLUE, blue);
|
||||
led_set(LED_RED, red);
|
||||
}
|
||||
Reference in New Issue
Block a user