2026-07-06 11:10:43 +08:00
<!DOCTYPE html>
2026-07-06 11:23:41 +08:00
< html lang = "fr" >
2026-07-06 11:10:43 +08:00
< head >
< meta charset = "UTF-8" >
2026-07-06 11:23:41 +08:00
< title > Plan d'implémentation - Bracelet Intelligent< / title >
2026-07-06 11:10:43 +08:00
< style >
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #0B0F19;
color: #E2E8F0;
margin: 0;
padding: 40px 20px;
line-height: 1.6;
}
.container {
max-width: 1000px;
margin: 0 auto;
}
h1 {
font-size: 2.2rem;
color: #00E5FF;
text-align: center;
margin-bottom: 10px;
letter-spacing: 1px;
}
.subtitle {
text-align: center;
color: #94A3B8;
font-size: 1.1rem;
margin-bottom: 40px;
}
.section-title {
font-size: 1.5rem;
color: #FFB74D;
border-bottom: 2px solid #334155;
padding-bottom: 8px;
margin-top: 50px;
margin-bottom: 24px;
}
.card {
background-color: #1E293B;
border-radius: 12px;
padding: 24px;
margin-bottom: 30px;
border: 1px solid #334155;
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.95rem;
margin-top: 10px;
}
th, td {
text-align: left;
padding: 10px 14px;
border-bottom: 1px solid #334155;
}
th {
color: #94A3B8;
font-weight: bold;
background-color: #0F172A;
}
td {
color: #E2E8F0;
}
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.8rem;
font-weight: bold;
}
.badge-red { background-color: #7f1d1d; color: #fca5a5; }
.badge-green { background-color: #064e3b; color: #6ee7b7; }
.badge-blue { background-color: #1e3a8a; color: #93c5fd; }
.badge-orange { background-color: #7c2d12; color: #ffedd5; }
.alert {
border-left: 4px solid #00E5FF;
background-color: #0F172A;
padding: 16px 20px;
border-radius: 4px;
margin-bottom: 25px;
}
.alert-title {
font-weight: bold;
color: #FFFFFF;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.alert-title span {
color: #00E5FF;
}
.task-list {
list-style: none;
padding: 0;
}
.task-item {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 14px;
font-size: 1rem;
}
.task-checkbox {
margin-top: 5px;
width: 16px;
height: 16px;
cursor: pointer;
}
.task-text {
flex: 1;
}
.task-text b {
color: #FFFFFF;
}
@keyframes flash {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
< / style >
< / head >
< body >
< div class = "container" >
2026-07-06 11:23:41 +08:00
< h1 > Plan d'implémentation du Bracelet (V1.2)< / h1 >
< div class = "subtitle" > Documentation technique de la version française et du pilote de LED RGB (XL-2020RGBC-2812B)< / div >
2026-07-06 11:10:43 +08:00
<!-- System Architecture Block -->
< div class = "card" style = "background-color: #0D111A; border: 1px solid #1E293B;" >
2026-07-06 11:23:41 +08:00
< div style = "font-size: 1.2rem; font-weight: bold; color: #FFB74D; text-align: center; margin-bottom: 15px;" > Topologie de communication et brochage matériel< / div >
2026-07-06 11:10:43 +08:00
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 800 360" width = "100%" height = "auto" >
< defs >
< filter id = "boxShadow" x = "-5%" y = "-5%" width = "110%" height = "110%" >
< feDropShadow dx = "0" dy = "2" stdDeviation = "3" flood-color = "#000000" flood-opacity = "0.4" / >
< / filter >
< marker id = "arrow" viewBox = "0 0 10 10" refX = "6" refY = "5" markerWidth = "6" markerHeight = "6" orient = "auto-start-reverse" >
< path d = "M 0 1.5 L 8 5 L 0 8.5 z" fill = "#64748B" / >
< / marker >
< / defs >
< rect width = "800" height = "360" rx = "8" fill = "#0D111A" / >
<!-- Left: Inputs -->
< g transform = "translate(40, 40)" filter = "url(#boxShadow)" >
< rect width = "180" height = "280" rx = "8" fill = "#1E293B" stroke = "#334155" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "24" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "12" font-weight = "bold" text-anchor = "middle" > ENTRÉES / BOUTONS & RF< / text >
2026-07-06 11:10:43 +08:00
<!-- Keys Sub - box -->
< rect x = "15" y = "45" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#00E5FF" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "65" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Boutons (▲ / ▼ / SOS)< / text >
< text x = "25" y = "90" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P0.1: BOUTON_UP (▲)< / text >
< text x = "25" y = "108" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P0.3: BOUTON_DOWN (▼)< / text >
< text x = "25" y = "124" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P0.2: BOUTON_SOS< / text >
2026-07-06 11:10:43 +08:00
<!-- RF Rx Sub - box -->
< rect x = "15" y = "160" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#FF9800" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "180" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Récepteur RF 433MHz< / text >
< text x = "25" y = "205" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P2.1: Données RF (RXD)< / text >
< text x = "25" y = "222" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P2.2: Mode veille (SHUT)< / text >
< text x = "25" y = "239" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P3.7: Alimentation RF< / text >
2026-07-06 11:10:43 +08:00
< / g >
<!-- Middle: Processing (MCU Core) -->
< g transform = "translate(310, 40)" filter = "url(#boxShadow)" >
< rect width = "180" height = "280" rx = "8" fill = "#1E293B" stroke = "#00E5FF" stroke-width = "2" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "24" fill = "#00E5FF" font-family = "system-ui, sans-serif" font-size = "12" font-weight = "bold" text-anchor = "middle" > MCU / Machine d'état< / text >
2026-07-06 11:10:43 +08:00
<!-- State Machine -->
< rect x = "15" y = "45" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#334155" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "65" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Machine d'état principale< / text >
< text x = "25" y = "90" fill = "#00E5FF" font-family = "system-ui, sans-serif" font-size = "9" > ● STATE_NORMAL (Veille/Clock)< / text >
< text x = "25" y = "105" fill = "#FFB74D" font-family = "system-ui, sans-serif" font-size = "9" > ● STATE_PAIR (Appairage)< / text >
< text x = "25" y = "120" fill = "#FF1744" font-family = "system-ui, sans-serif" font-size = "9" > ● STATE_ALARM (Alarme active)< / text >
2026-07-06 11:10:43 +08:00
<!-- Timers & Storage -->
< rect x = "15" y = "160" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#334155" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "180" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Ordonnancement & Stockage< / text >
< text x = "25" y = "205" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Timer 1: Anti-rebond 1ms< / text >
< text x = "25" y = "222" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Moteur / Logiciel LED< / text >
< text x = "25" y = "239" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > IAP Flash: Stocke 16 capteurs< / text >
2026-07-06 11:10:43 +08:00
< / g >
<!-- Right: Outputs -->
< g transform = "translate(580, 40)" filter = "url(#boxShadow)" >
< rect width = "180" height = "280" rx = "8" fill = "#1E293B" stroke = "#334155" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "24" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "12" font-weight = "bold" text-anchor = "middle" > SORTIES / AFFICHAGE & RETRO.< / text >
2026-07-06 11:10:43 +08:00
<!-- Screen -->
< rect x = "15" y = "45" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#00E5FF" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "65" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Écran OLED RM69310< / text >
< text x = "25" y = "90" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Résolution: 120 x 240< / text >
< text x = "25" y = "108" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Police ASCII 8x16 & 16x32< / text >
< text x = "25" y = "124" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Interface utilisateur française< / text >
2026-07-06 11:10:43 +08:00
<!-- Indicators -->
< rect x = "15" y = "160" width = "150" height = "90" rx = "6" fill = "#0F172A" stroke = "#FF1744" stroke-width = "1" / >
2026-07-06 11:23:41 +08:00
< text x = "90" y = "180" fill = "#FFFFFF" font-family = "system-ui, sans-serif" font-size = "11" font-weight = "bold" text-anchor = "middle" > Actionneurs Physiques< / text >
< text x = "25" y = "205" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > LED RGB (P0.0: Signal unique)< / text >
< text x = "25" y = "222" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > Bus série 800Kbps (NZR)< / text >
< text x = "25" y = "239" fill = "#94A3B8" font-family = "system-ui, sans-serif" font-size = "10" > P2.5: Vibration Moteur< / text >
2026-07-06 11:10:43 +08:00
< / g >
<!-- Connectors -->
< path d = "M 220 100 L 310 100" stroke = "#64748B" stroke-width = "2" fill = "none" marker-end = "url(#arrow)" / >
< path d = "M 220 210 L 310 210" stroke = "#64748B" stroke-width = "2" fill = "none" marker-end = "url(#arrow)" / >
< path d = "M 490 100 L 580 100" stroke = "#64748B" stroke-width = "2" fill = "none" marker-end = "url(#arrow)" / >
< path d = "M 490 210 L 580 210" stroke = "#64748B" stroke-width = "2" fill = "none" marker-end = "url(#arrow)" / >
< / svg >
< / div >
<!-- Section 1 -->
2026-07-06 11:23:41 +08:00
< div class = "section-title" > I. Table de configuration des broches et caractéristiques électriques< / div >
2026-07-06 11:10:43 +08:00
< div class = "card" >
< table >
< thead >
< tr >
2026-07-06 11:23:41 +08:00
< th > Catégorie de matériel< / th >
< th > Alias du port< / th >
< th > Broche STC32G< / th >
< th > Description de la logique de commande< / th >
2026-07-06 11:10:43 +08:00
< / tr >
< / thead >
< tbody >
< tr >
2026-07-06 11:23:41 +08:00
< td > < b > 🌈 LED RGB Adressable< / b > < / td >
< td > < code > WS2812_DI< / code > < / td >
2026-07-06 11:10:43 +08:00
< td > P0.0< / td >
2026-07-06 11:23:41 +08:00
< td > Signal de commande unique, protocole 800Kbps, initialisé à < b > 0< / b > .< / td >
2026-07-06 11:10:43 +08:00
< / tr >
< tr >
2026-07-06 11:23:41 +08:00
< td > < b > 📳 Moteur de Vibration< / b > < / td >
2026-07-06 11:10:43 +08:00
< td > < code > MOTOR< / code > < / td >
< td > P2.5< / td >
2026-07-06 11:23:41 +08:00
< td > Commande tout-ou-rien. Sortie à < b > 1< / b > active la vibration, 0 l'arrête.< / td >
2026-07-06 11:10:43 +08:00
< / tr >
< tr >
2026-07-06 11:23:41 +08:00
< td > < b > ▲ Bouton de direction (Haut)< / b > < / td >
2026-07-06 11:10:43 +08:00
< td > < code > KEY_UP< / code > < / td >
< td > P0.1< / td >
2026-07-06 11:23:41 +08:00
< td > Entrée avec résistance de pull-up interne. Actif à l'état bas (< b > 0< / b > ).< / td >
2026-07-06 11:10:43 +08:00
< / tr >
< tr >
2026-07-06 11:23:41 +08:00
< td > < b > ▼ Bouton de direction (Bas)< / b > < / td >
2026-07-06 11:10:43 +08:00
< td > < code > KEY_DOWN< / code > < / td >
< td > P0.3< / td >
2026-07-06 11:23:41 +08:00
< td > Entrée avec résistance de pull-up interne. Actif à l'état bas (< b > 0< / b > ).< / td >
2026-07-06 11:10:43 +08:00
< / tr >
< tr >
2026-07-06 11:23:41 +08:00
< td > < b > 🆘 Bouton d'urgence / Appairage< / b > < / td >
2026-07-06 11:10:43 +08:00
< td > < code > KEY_SOS< / code > < / td >
< td > P0.2< / td >
2026-07-06 11:23:41 +08:00
< td > Entrée avec résistance de pull-up interne. Actif à l'état bas (< b > 0< / b > ).< / td >
2026-07-06 11:10:43 +08:00
< / tr >
< / tbody >
< / table >
< / div >
<!-- Section 2 -->
2026-07-06 11:23:41 +08:00
< div class = "section-title" > II. Décisions clés de conception (Design Decisions)< / div >
2026-07-06 11:10:43 +08:00
< div class = "alert" style = "border-left-color: #00E5FF;" >
2026-07-06 11:23:41 +08:00
< div class = "alert-title" > < span > 💡< / span > Décision 1 : Interface utilisateur 100% en Français (French-only UI)< / div >
2026-07-06 11:10:43 +08:00
< div class = "alert-body" >
2026-07-06 11:23:41 +08:00
Conformément aux exigences actuelles, le système prend uniquement en charge l'affichage en langue française. Toutes les chaînes de l'interface ont été traduites pour tenir sur l'écran OLED de 120 pixels de largeur (maximum 15 caractères par ligne). Les coordonnées horizontales des icônes ont été ajustées en conséquence pour garantir un centrage parfait et éviter les chevauchements.
2026-07-06 11:10:43 +08:00
< / div >
< / div >
< div class = "alert" style = "border-left-color: #FF9800;" >
2026-07-06 11:23:41 +08:00
< div class = "alert-title" > < span > 📡< / span > Décision 2 : Intégration de la LED RGB Adressable (XL-2020RGBC-2812B)< / div >
2026-07-06 11:10:43 +08:00
< div class = "alert-body" >
2026-07-06 11:23:41 +08:00
Les trois LED d'origine sont remplacées par une unique LED intelligente utilisant un protocole de type WS2812B (800Kbps). Pour conserver la logique temporelle existante de clignotement et de contrôle d'état, nous émulons < code > LED_R< / code > , < code > LED_G< / code > , < code > LED_B< / code > en tant que bits mémoire virtuels. Lorsque l'interruption détecte un changement d'état, elle génère dynamiquement la trame GRB 24 bits et l'envoie à la broche P0.0 par modification logicielle directe (bit-bang) avec désactivation temporaire des interruptions.
2026-07-06 11:10:43 +08:00
< / div >
< / div >
<!-- Section 3 -->
2026-07-06 11:23:41 +08:00
< div class = "section-title" > III. Rendu de l'interface et gestion de l'écran< / div >
2026-07-06 11:10:43 +08:00
< div class = "card" >
2026-07-06 11:23:41 +08:00
< h3 style = "color: #FFFFFF; margin-top: 0;" > 1. Envoi séquentiel de trames binaires (`LCD_DrawMonoBitmap`)< / h3 >
< p > Utilise l'interface SPI matérielle pour adresser une fenêtre rectangulaire, éliminant tout besoin de mémoire tampon en RAM (zéro allocation de frame buffer). Les performances de balayage d'écran sont ultra-rapides et optimales.< / p >
2026-07-06 11:10:43 +08:00
2026-07-06 11:23:41 +08:00
< h3 style = "color: #FFFFFF;" > 2. Définition des coordonnées d'affichage< / h3 >
< p > L'affichage utile sur l'écran circulaire est optimisé dans les coordonnées suivantes :< / p >
2026-07-06 11:10:43 +08:00
< ul >
2026-07-06 11:23:41 +08:00
< li > < b > Page Horloge< / b > : Icône de batterie à X=92, Y=27, et pourcentage "85%" à X=62, Y=24. La date "JEU 07-02" est au centre à Y=155. Les icônes et textes "ARME" (X=52) / "DESARME" (X=42) sont parfaitement centrés à Y=202.< / li >
< li > < b > Menu d'appairage< / b > : Affiche le titre "MENU APPAI." à Y=30. Les éléments du menu (ex. "DETEC. PORTE") sont dessinés de manière dynamique et le choix actif est encadré à Y=118 par un rectangle de couleur cyan.< / li >
< li > < b > Alerte & SOS< / b > : Pour l'alarme SOS, le titre "SOS EMIS" s'affiche à Y=125, et "BRACELET ACTIF" à Y=155. Pour les capteurs, le nom (ex. "PORTE ENTREE") est affiché à Y=120, et le texte "ZONE X | ALARME" est affiché à Y=155.< / li >
2026-07-06 11:10:43 +08:00
< / ul >
< / div >
<!-- Section 4 -->
2026-07-06 11:23:41 +08:00
< div class = "section-title" > IV. Liste de contrôle des validations (Task Checklist)< / div >
2026-07-06 11:10:43 +08:00
< div class = "card" style = "background-color: #0F172A;" >
< ul class = "task-list" >
< li class = "task-item" >
2026-07-06 11:23:41 +08:00
< input type = "checkbox" class = "task-checkbox" id = "task1" checked disabled >
< label for = "task1" class = "task-text" > < b > 1. Test de compilation automatique< / b > : Rebuild complet via Keil C251, génération correcte de < code > wristband.hex< / code > avec 0 erreur.< / label >
2026-07-06 11:10:43 +08:00
< / li >
< li class = "task-item" >
2026-07-06 11:23:41 +08:00
< input type = "checkbox" class = "task-checkbox" id = "task2" checked disabled >
< label for = "task2" class = "task-text" > < b > 2. Validation de l'interface en Français< / b > : Vérification visuelle de tous les menus, pages de veille et de statut traduits en français.< / label >
2026-07-06 11:10:43 +08:00
< / li >
< li class = "task-item" >
2026-07-06 11:23:41 +08:00
< input type = "checkbox" class = "task-checkbox" id = "task3" checked disabled >
< label for = "task3" class = "task-text" > < b > 3. Test du pilote LED RGB< / b > : Envoi et conversion des états virtuels R/G/B vers les paquets de données physiques de la LED WS2812B à 800Kbps.< / label >
2026-07-06 11:10:43 +08:00
< / li >
< li class = "task-item" >
2026-07-06 11:23:41 +08:00
< input type = "checkbox" class = "task-checkbox" id = "task4" checked disabled >
< label for = "task4" class = "task-text" > < b > 4. Synchronisation Git< / b > : Sauvegarde locale de l'ensemble de l'historique et téléversement réussi sur le serveur distant.< / label >
2026-07-06 11:10:43 +08:00
< / li >
< / ul >
< / div >
< / div >
< / body >
< / html >