Illustre les modules 10 à 12 et la synthèse (7 figures)
M10 : consommation par mode, profil de courant en deep sleep. M11 : publish/subscribe, arborescence des topics. M12 : démarche de projet, structure multi-fichiers. Synthèse : carte du parcours. Figure du chenillard (M2) déplacée après son code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -0,0 +1,61 @@
|
||||
"""Module 10 — Gestion de l'énergie."""
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
from style import BLEU, CM, ENCRE, GRIS, ORANGE, ROUGE, VERT, Figure
|
||||
|
||||
|
||||
def consommation_modes():
|
||||
fig, ax = plt.subplots(figsize=(16 * CM, 6.4 * CM))
|
||||
modes = [("Actif\n(Wi-Fi, calcul)", 80, 250, ROUGE, "moins d'1 jour"),
|
||||
("Modem-sleep", 20, 30, ORANGE, "≈ 3 jours"),
|
||||
("Light sleep", 0.7, 0.9, BLEU, "≈ 3 mois"),
|
||||
("Deep sleep", 0.010, 0.150, VERT, "plus d'1 an (théorique)")]
|
||||
for i, (nom, bas, haut, c, autonomie) in enumerate(modes):
|
||||
ax.barh(i, haut - bas, left=bas, height=0.5, color=c, alpha=0.85)
|
||||
ax.text(haut * 1.4, i, autonomie, va="center", fontsize=8.5, color=c, fontweight="bold")
|
||||
ax.set_yticks(range(len(modes)), [m[0] for m in modes])
|
||||
ax.invert_yaxis()
|
||||
ax.set_xscale("log")
|
||||
ax.set_xlim(0.005, 20000)
|
||||
ax.set_xticks([0.01, 0.1, 1, 10, 100, 1000], ["10 µA", "100 µA", "1 mA", "10 mA", "100 mA", "1 A"])
|
||||
ax.set_xlabel("courant consommé (échelle logarithmique)")
|
||||
ax.text(20000, -0.75, "autonomie avec une batterie de 2000 mAh", ha="right", fontsize=7.5,
|
||||
color=GRIS, style="italic")
|
||||
ax.grid(axis="y", visible=False)
|
||||
fig.tight_layout()
|
||||
return fig
|
||||
|
||||
|
||||
def cycle_deep_sleep():
|
||||
fig, ax = plt.subplots(figsize=(16 * CM, 6.0 * CM))
|
||||
t, i = [0], [0.05]
|
||||
for debut in (0, 60, 120):
|
||||
t += [debut, debut + 0.4, debut + 1.0, debut + 3.0]
|
||||
i += [45, 40, 160, 0.05]
|
||||
t += [150]
|
||||
i += [0.05]
|
||||
ax.step(t, i, where="post", color=BLEU, lw=1.6)
|
||||
ax.fill_between(t, 0.01, i, step="post", color=BLEU, alpha=0.12)
|
||||
ax.set_yscale("log")
|
||||
ax.set_ylim(0.01, 600)
|
||||
ax.set_yticks([0.01, 0.1, 1, 10, 100], ["10 µA", "100 µA", "1 mA", "10 mA", "100 mA"])
|
||||
ax.set_xlim(-3, 150)
|
||||
ax.set_xlabel("temps (s)")
|
||||
ax.set_ylabel("courant")
|
||||
ax.annotate("réveil : setup() repart du début\nmesure BME280, envoi Wi-Fi (≈ 3 s)", xy=(61.5, 160), xytext=(66, 260),
|
||||
fontsize=7.8, color=ROUGE, arrowprops=dict(arrowstyle="-|>", color=ROUGE, lw=0.8))
|
||||
ax.text(30, 0.5, "deep sleep (≈ 57 s)\nseule la RTC reste alimentée", ha="center", fontsize=7.8, color=VERT)
|
||||
ax.text(31.5, 0.16, "esp_sleep_enable_timer_wakeup(60 s)", ha="center", fontsize=7.3, color=ENCRE,
|
||||
family="monospace")
|
||||
ax.text(91, 2.0, "compteurReveils (RTC_DATA_ATTR)\nconservé d'un cycle à l'autre", ha="center", fontsize=7.5,
|
||||
color=GRIS, style="italic")
|
||||
ax.grid(axis="x", visible=False)
|
||||
fig.tight_layout()
|
||||
return fig
|
||||
|
||||
|
||||
FIGURES = [
|
||||
Figure("m10-consommation-modes", consommation_modes),
|
||||
Figure("m10-cycle-deep-sleep", cycle_deep_sleep),
|
||||
]
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Module 11 — IoT & Cloud : le protocole MQTT."""
|
||||
from outils import boite, fleche, toile
|
||||
from style import BLEU, ENCRE, GRIS, ORANGE, ROUGE, VERT, Figure
|
||||
|
||||
|
||||
def publish_subscribe():
|
||||
fig, ax = toile(16, 6.6)
|
||||
esp = boite(ax, 2.2, 3.3, 3.4, 2.4, couleur=BLEU)
|
||||
ax.text(2.2, 4.05, "ESP32-S3", ha="center", fontsize=10, fontweight="bold", color=BLEU)
|
||||
ax.text(2.2, 3.0, "BME280 + LED\nNeoPixel", ha="center", va="center", fontsize=8, color=ENCRE)
|
||||
broker = boite(ax, 8.0, 3.3, 3.0, 2.4, couleur=ORANGE)
|
||||
ax.text(8.0, 3.75, "Broker", ha="center", fontsize=10, fontweight="bold", color=ORANGE)
|
||||
ax.text(8.0, 3.0, "Mosquitto,\nHiveMQ…", ha="center", va="center", fontsize=8, color=ENCRE)
|
||||
dash = boite(ax, 13.8, 4.8, 3.6, 1.4, "Tableau de bord\n(Node-RED)", couleur=VERT, taille=8.5)
|
||||
ha = boite(ax, 13.8, 1.8, 3.6, 1.4, "Home Assistant", couleur=VERT, taille=8.5)
|
||||
# Publication de la température
|
||||
fleche(ax, (3.9, 3.9), (6.5, 3.9), "publish", couleur=BLEU, taille=8, fond=True)
|
||||
ax.text(5.3, 5.1, "formation/esp32s3/temperature\n« 21.5 »", ha="center", fontsize=6.8, color=BLEU,
|
||||
family="monospace")
|
||||
fleche(ax, (9.5, 3.9), (12.0, 4.6), couleur=BLEU)
|
||||
fleche(ax, (9.5, 3.7), (12.0, 2.0), couleur=BLEU)
|
||||
ax.text(12.4, 3.35, "abonnés à …/temperature\n→ reçoivent la valeur", ha="center", fontsize=7.2,
|
||||
color=GRIS, style="italic")
|
||||
# Commande en retour
|
||||
fleche(ax, (12.0, 5.2), (9.5, 4.3), couleur=ROUGE)
|
||||
fleche(ax, (6.5, 2.7), (3.9, 2.7), "message", couleur=ROUGE, taille=8, fond=True)
|
||||
ax.text(5.3, 1.45, "formation/esp32s3/commande\n« rouge »", ha="center", fontsize=6.8, color=ROUGE,
|
||||
family="monospace")
|
||||
ax.text(10.9, 5.25, "publish « rouge »", ha="center", fontsize=7.5, color=ROUGE, rotation=20)
|
||||
ax.text(8.0, 0.35, "Les appareils ne se parlent jamais directement : tout passe par le broker.",
|
||||
ha="center", fontsize=7.8, color=GRIS, style="italic")
|
||||
return fig
|
||||
|
||||
|
||||
def arborescence_topics():
|
||||
fig, ax = toile(16, 5.0)
|
||||
noeuds = {
|
||||
"maison": (1.6, 3.6), "salon": (4.9, 4.3), "cuisine": (4.9, 2.9),
|
||||
"temperature ": (8.3, 4.65), "humidite": (8.3, 3.95), "temperature ": (8.3, 2.9),
|
||||
"formation": (1.6, 1.2), "esp32s3": (4.9, 1.2),
|
||||
"temperature": (8.3, 1.55), "commande": (8.3, 0.85),
|
||||
}
|
||||
liens = [("maison", "salon"), ("maison", "cuisine"), ("salon", "temperature "), ("salon", "humidite"),
|
||||
("cuisine", "temperature "), ("formation", "esp32s3"), ("esp32s3", "temperature"),
|
||||
("esp32s3", "commande")]
|
||||
for a, b in liens:
|
||||
(x1, y1), (x2, y2) = noeuds[a], noeuds[b]
|
||||
ax.plot([x1 + 1.15, (x1 + x2) / 2 + 0.3, (x1 + x2) / 2 + 0.3, x2 - 1.15], [y1, y1, y2, y2],
|
||||
color=GRIS, lw=1.1)
|
||||
for nom, (x, y) in noeuds.items():
|
||||
c = BLEU if nom.startswith(("formation", "esp32s3")) or nom in ("temperature", "commande") else GRIS
|
||||
boite(ax, x, y, 2.3, 0.5, nom.strip(), couleur=c, taille=7.2)
|
||||
chemins = [(4.65, "maison/salon/temperature", GRIS), (2.9, "maison/cuisine/temperature", GRIS),
|
||||
(1.55, "formation/esp32s3/temperature", BLEU), (0.85, "formation/esp32s3/commande", BLEU)]
|
||||
for y, txt, c in chemins:
|
||||
ax.text(9.75, y, "→ " + txt, va="center", fontsize=7.8, color=c, family="monospace")
|
||||
ax.text(9.75, 3.95, "→ maison/salon/humidite", va="center", fontsize=7.8, color=GRIS, family="monospace")
|
||||
return fig
|
||||
|
||||
|
||||
FIGURES = [
|
||||
Figure("m11-publish-subscribe", publish_subscribe),
|
||||
Figure("m11-arborescence-topics", arborescence_topics),
|
||||
]
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Module 12 — Projet final."""
|
||||
from outils import boite, fleche, toile
|
||||
from style import BLEU, ENCRE, GRIS, ORANGE, VERT, Figure
|
||||
|
||||
|
||||
def demarche_projet():
|
||||
fig, ax = toile(16, 4.2)
|
||||
etapes = [("Besoin", "quel\nproblème ?", GRIS), ("Cahier des\ncharges", "matériel,\nmodules", BLEU),
|
||||
("MVP", "l'indispensable\nd'abord", BLEU), ("Tests", "sur une durée\nréaliste", ORANGE),
|
||||
("Bonus", "si le temps\nle permet", VERT), ("Présentation", "démo, choix,\ndifficultés", VERT)]
|
||||
xs = [1.3 + k * 2.68 for k in range(len(etapes))]
|
||||
for x, (nom, sous, c) in zip(xs, etapes):
|
||||
boite(ax, x, 2.6, 2.35, 1.1, nom, couleur=c, taille=7.2, gras=True)
|
||||
ax.text(x, 1.85, sous, ha="center", va="top", fontsize=7, color=GRIS)
|
||||
for a, b in zip(xs, xs[1:]):
|
||||
fleche(ax, (a + 1.175, 2.6), (b - 1.175, 2.6))
|
||||
fleche(ax, (xs[3], 3.15), (xs[2], 3.15), "corriger", couleur=ORANGE, taille=7.3, courbe=0.6)
|
||||
return fig
|
||||
|
||||
|
||||
def structure_projet():
|
||||
fig, ax = toile(16, 6.0)
|
||||
main = boite(ax, 8.0, 4.6, 6.2, 1.6, couleur=BLEU)
|
||||
ax.text(8.0, 5.05, "MonProjet.ino", ha="center", fontsize=9.5, fontweight="bold", color=BLEU,
|
||||
family="monospace")
|
||||
ax.text(8.0, 4.3, "setup() et loop() uniquement :\norchestrent les appels", ha="center", va="center",
|
||||
fontsize=7.8, color=ENCRE)
|
||||
onglets = [(2.8, "capteurs.ino", "lireTemperature()\nlireHumidite()", VERT),
|
||||
(8.0, "affichage.ino", "afficherEcran()\nafficherLed()", ORANGE),
|
||||
(13.2, "reseau.ino", "connecterWiFi()\npublierMQTT()", GRIS)]
|
||||
for x, nom, fonctions, c in onglets:
|
||||
boite(ax, x, 1.4, 4.2, 1.9, couleur=c)
|
||||
ax.text(x, 1.95, nom, ha="center", fontsize=9, fontweight="bold", color=c, family="monospace")
|
||||
ax.text(x, 1.1, fonctions, ha="center", va="center", fontsize=7.8, color=ENCRE, family="monospace")
|
||||
fleche(ax, (8.0 + (x - 8.0) * 0.25, main["b"][1]), (x, 2.35), couleur=c)
|
||||
ax.text(15.8, 5.6, "une fonction =\nune responsabilité", ha="right", fontsize=7.8, color=GRIS, style="italic")
|
||||
return fig
|
||||
|
||||
|
||||
FIGURES = [
|
||||
Figure("m12-demarche-projet", demarche_projet),
|
||||
Figure("m12-structure-projet", structure_projet),
|
||||
]
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Synthèse de la formation (préfixe m13 : document hors numérotation des modules)."""
|
||||
from outils import boite, fleche, toile
|
||||
from style import BLEU, GRIS, ORANGE, ROUGE, VERT, Figure
|
||||
|
||||
|
||||
def parcours_formation():
|
||||
fig, ax = toile(16, 8.8)
|
||||
colonnes = [
|
||||
(1.55, "Prise\nen main", GRIS, [("0", "Installation"), ("1", "Microcontrôleur")]),
|
||||
(4.775, "Entrées /\nsorties", BLEU, [("2", "GPIO & NeoPixel"), ("3", "PWM & ADC"), ("4", "Série & debug")]),
|
||||
(8.0, "Bus\n& temps", ORANGE, [("5", "I2C & SPI"), ("6", "Interruptions")]),
|
||||
(11.225, "Connectivité", VERT, [("7", "Wi-Fi"), ("8", "Serveur web"), ("9", "BLE"), ("11", "MQTT")]),
|
||||
(14.45, "Autonomie", ROUGE, [("10", "Énergie")]),
|
||||
]
|
||||
centres = {}
|
||||
for x, titre, c, modules in colonnes:
|
||||
ax.text(x, 8.2, titre, ha="center", va="center", fontsize=8.5, fontweight="bold", color=c)
|
||||
n = len(modules)
|
||||
for k, (num, nom) in enumerate(modules):
|
||||
y = 6.95 - k * 1.25 - (4 - n) * 0.3
|
||||
boite(ax, x, y, 2.75, 1.0, f"M{num}\n{nom}", couleur=c, taille=7.1)
|
||||
centres[num] = (x, y)
|
||||
for a, b in (("1", "2"), ("4", "5"), ("6", "7"), ("11", "10")):
|
||||
(x1, y1), (x2, y2) = centres[a], centres[b]
|
||||
fleche(ax, (x1 + 1.375, y1), (x2 - 1.375, y2), couleur=GRIS)
|
||||
projet = boite(ax, 8.0, 0.8, 9.6, 1.1, "M12 — Projet final : au moins 3 modules combinés", couleur=BLEU,
|
||||
taille=9, gras=True)
|
||||
for x, *_ in colonnes:
|
||||
cible = (min(max(x, 3.6), 12.4), projet["h"][1])
|
||||
fleche(ax, (x, 2.4), cible, couleur=GRIS, pointille=True)
|
||||
ax.text(14.45, 4.5, "la LED NeoPixel\nsert de fil rouge\ndans tous\nles modules", ha="center", va="center",
|
||||
fontsize=7.3, color=GRIS, style="italic")
|
||||
return fig
|
||||
|
||||
|
||||
FIGURES = [
|
||||
Figure("m13-parcours-formation", parcours_formation),
|
||||
]
|
||||
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 79 KiB |