Raspberry Pi

Capteur MQTT Pico W sur batterie avec lightsleep et cycles de veille

Transformez un Raspberry Pi Pico W en capteur MQTT sur batterie qui se réveille, mesure, publie puis se rendort. Lightsleep MicroPython, coupure du Wi-Fi, lecture de la tension batterie et pièges qui vident les piles.

Raspberry Pi Pico W sur un support de piles, se réveillant périodiquement pour envoyer une mesure MQTT à un broker cloud
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Un capteur Pico W sur batterie MQTT ne fonctionne que si la carte passe presque toute sa vie endormie et seulement quelques secondes éveillée. Dans ce tutoriel, vous allez construire un nœud capteur en MicroPython qui se réveille sur minuterie, lit un capteur et sa propre tension d'alimentation, publie un message en QoS 1 vers un broker MQTT, coupe la radio et retourne en lightsleep. Vous verrez aussi quels choix de conception influent réellement sur l'autonomie et lesquels sont des efforts perdus.

Pourquoi l'alimentation sur batterie est difficile sur le Pico W

Le Pico W a été conçu comme une carte microcontrôleur bon marché et polyvalente, pas comme une plateforme de capteurs ultra-basse consommation. Le RP2040 lui-même est assez efficace, mais trois éléments jouent contre vous sur batterie :

  • La puce Wi-Fi CYW43439 consomme bien plus de courant pendant l'association et l'émission que le microcontrôleur pendant ses calculs. Chaque seconde de radio allumée coûte plus que des minutes de veille.
  • Le régulateur buck-boost intégré a un courant de repos qui ne disparaît jamais, même quand le RP2040 dort.
  • Les modes de veille de MicroPython sont limités par rapport à des puces comme l'ESP32. machine.lightsleep() arrête les horloges et conserve la RAM, ce qui est utile, mais la carte consomme encore nettement plus qu'un nœud conçu pour la basse consommation.

La conséquence pratique est simple : l'autonomie dépend surtout de la fréquence des réveils et de la durée de connexion Wi-Fi. Optimiser le code Python qui lit un capteur ne change presque rien. Passer d'un intervalle de publication de 30 secondes à 5 minutes, ou réduire le temps de connexion de huit à trois secondes, change beaucoup.

Si vous n'avez encore jamais connecté de Pico W à MQTT, commencez par le guide Raspberry Pi Pico W MQTT et revenez ici une fois qu'une publication de base fonctionne.

La conception du cycle de veille

Chaque réveil suit le même court script. Le garder strictement linéaire (pas de tâches de fond, pas de connexion persistante) est ce qui le rend prévisible.

  1. Sortir du lightsleep (ou d'un démarrage à froid après une coupure).
  2. Lire la tension batterie avant d'allumer le Wi-Fi.
  3. Lire le capteur.
  4. Allumer le Wi-Fi avec une configuration statique et un délai d'expiration strict.
  5. Se connecter au broker, publier un message en QoS 1 et attendre l'accusé de réception.
  6. Se déconnecter proprement, éteindre la radio et la désinitialiser.
  7. Passer en lightsleep pendant l'intervalle configuré, puis recommencer.
Choix de conception Effet sur l'autonomie Recommandation
Intervalle de publication Facteur le plus important 5 à 15 minutes pour des données de climat intérieur
Temps de connexion Wi-Fi Deuxième facteur Bon signal, WPA2, délai d'expiration court
Garder MQTT connecté pendant la veille La radio reste partiellement active Jamais sur batterie
Publication en QoS 1 Un aller-retour supplémentaire Cela vaut le coup, vous savez que le message est arrivé
Lightsleep ou time.sleep() actif Le lightsleep arrête les horloges Toujours le lightsleep entre deux cycles
LED clignotante d'état Consommation faible mais permanente À désactiver en production
Puce de minuterie externe (TPL5110 ou similaire) Coupe totalement l'alimentation de la carte Meilleure option pour plusieurs mois d'autonomie

Matériel et câblage

Il vous faut un Pico W (ou un Pico 2 W), un capteur et une source d'alimentation sur VSYS. Une configuration courante consiste en trois piles AA ou AAA en série alimentant directement VSYS, ou un seul accumulateur LiPo via une carte de protection. Ne dépassez pas la limite VSYS indiquée dans la fiche technique officielle, et ne branchez jamais de piles sur VBUS quand l'USB est connecté sans diode.

Côté capteur, toute pièce I2C à faible courant de veille convient. Cet exemple utilise un BME280 sur I2C0 (GP4 = SDA, GP5 = SCL), mais la logique du cycle de veille est indépendante du capteur, que vous mesuriez le jardin ou une pièce de la maison connectée.

Le Pico W peut mesurer sa propre tension d'alimentation sur ADC3, relié à VSYS par un diviseur 1:3. Sur le Pico W, cette broche (GP29) est partagée avec l'horloge SPI de la puce Wi-Fi : vous devez donc la lire radio éteinte et avec GP25 au niveau haut. C'est pourquoi la lecture de tension a lieu en premier dans le cycle.

Préparer MicroPython et la bibliothèque MQTT

Flashez une version récente de MicroPython pour le Pico W depuis la documentation officielle Raspberry Pi, puis installez la bibliothèque umqtt.simple et un pilote BME280 avec mpremote :

pip install mpremote
mpremote mip install umqtt.simple
mpremote cp bme280.py :bme280.py

Créez un fichier secrets.py sur la carte pour garder les identifiants hors du script principal :

# secrets.py
WIFI_SSID = "your-ssid"
WIFI_PASSWORD = "your-wifi-password"

MQTT_HOST = "broker.connectmq.com"
MQTT_PORT = 1883
MQTT_CLIENT_ID = "pico-bat-7f3a91"   # must be non-empty and unique
MQTT_USER = None                     # set YOUR_USERNAME for a private broker
MQTT_PASSWORD = None                 # set YOUR_PASSWORD for a private broker
TOPIC = "connectmq/demo/7f3a91/garden/climate"

INTERVAL_S = 600                     # 10 minutes between readings

Le serveur MQTT public gratuit broker.connectmq.com accepte les connexions anonymes avec n'importe quel client ID non vide. Tout ce qui y est publié est lisible par tous : utilisez un préfixe de topic aléatoire et n'envoyez jamais de données personnelles. Le guide du serveur MQTT public gratuit en détaille les limites.

Le script complet MQTT sur batterie

Enregistrez-le sous main.py. Il s'exécute automatiquement à chaque démarrage, et comme la boucle utilise le lightsleep au lieu d'une réinitialisation, l'état en RAM, comme le compteur de cycles, survit entre les réveils.

# main.py - battery-powered Pico W MQTT sensor
import time
import json
import network
import machine
from machine import Pin, ADC, I2C
from umqtt.simple import MQTTClient
import bme280
import secrets

led = Pin("LED", Pin.OUT)
led.off()

i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100_000)
cycle = 0


def read_vsys():
    """Read VSYS on the Pico W. Must run while the Wi-Fi chip is off."""
    Pin(25, Pin.OUT).value(1)          # deselect the CYW43 SPI bus
    Pin(29, Pin.IN, None)              # release the shared pin for the ADC
    adc = ADC(3)
    total = 0
    for _ in range(8):
        total += adc.read_u16()
        time.sleep_ms(2)
    raw = total / 8
    return round(raw * 3.3 * 3 / 65535, 3)


def read_sensor():
    sensor = bme280.BME280(i2c=i2c)
    t, p, h = sensor.read_compensated_data()
    # The driver returns hundredths of a degree, Pa*256 and %RH*1024
    return round(t / 100, 2), round(h / 1024, 1), round(p / 25600, 1)


def wifi_up(timeout_ms=10_000):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(secrets.WIFI_SSID, secrets.WIFI_PASSWORD)
    start = time.ticks_ms()
    while not wlan.isconnected():
        if time.ticks_diff(time.ticks_ms(), start) > timeout_ms:
            return wlan, False
        time.sleep_ms(100)
    return wlan, True


def wifi_down(wlan):
    try:
        wlan.disconnect()
    except OSError:
        pass
    wlan.active(False)
    wlan.deinit()


def publish(payload):
    client = MQTTClient(
        secrets.MQTT_CLIENT_ID,
        secrets.MQTT_HOST,
        port=secrets.MQTT_PORT,
        user=secrets.MQTT_USER,
        password=secrets.MQTT_PASSWORD,
        keepalive=30,
    )
    client.connect()
    # QoS 1: publish() blocks until the broker returns PUBACK
    client.publish(secrets.TOPIC, payload, qos=1)
    client.disconnect()


while True:
    cycle += 1
    vbat = read_vsys()
    try:
        temp_c, rh, hpa = read_sensor()
    except OSError:
        temp_c, rh, hpa = None, None, None

    awake_start = time.ticks_ms()
    wlan, ok = wifi_up()
    if ok:
        msg = json.dumps({
            "t": temp_c, "rh": rh, "hpa": hpa,
            "vbat": vbat, "cycle": cycle,
            "rssi": wlan.status("rssi"),
            "awake_ms": time.ticks_diff(time.ticks_ms(), awake_start),
        })
        try:
            publish(msg)
        except OSError as exc:
            print("MQTT failed:", exc)
    wifi_down(wlan)

    # Back off harder when the battery is low to protect the cells
    sleep_s = secrets.INTERVAL_S if vbat > 3.3 else secrets.INTERVAL_S * 3
    machine.lightsleep(sleep_s * 1000)

Certains détails sont délibérés. Le script indique awake_ms et rssi dans chaque message pour que vous puissiez voir, côté broker, si un nœud met trop de temps à se connecter. La branche batterie faible triple l'intervalle au lieu de tout arrêter, ce qui laisse le temps de changer les piles sans perdre le nœud. Et deinit() après active(False) garantit que le pilote CYW43 libère la radio avant que la carte ne s'endorme.

Tester les messages MQTT du Pico W sur batterie

Avant de passer sur piles, testez sur USB avec un intervalle court, par exemple 30 secondes. Abonnez-vous depuis votre ordinateur :

mosquitto_sub -h broker.connectmq.com -p 1883 -i laptop-7f3a91 \
  -t 'connectmq/demo/7f3a91/#' -v

Vous devriez voir un message JSON par cycle. Surveillez le champ awake_ms. Sur un réseau sain, il se stabilise dans une plage étroite et reproductible. S'il varie fortement, le problème vient du point d'accès, pas de votre code.

Notez que lorsque le Pico W dort en étant branché en USB, le REPL série se déconnecte. C'est normal. Pour reprendre la main, débranchez, maintenez BOOTSEL si nécessaire, ou utilisez mpremote juste après la mise sous tension, avant que main.py n'entre dans sa première veille. Une astuce utile consiste à ajouter tout en haut de main.py une fenêtre de deux secondes qui renvoie au REPL si un bouton relié à une broche GPIO est maintenu.

Gagner encore en autonomie sur le Pico W

Une fois le cycle de base fonctionnel, ces améliorations offrent le meilleur rendement :

  • Allongez d'abord l'intervalle. Diviser par deux le nombre de réveils divise à peu près par deux l'énergie radio, le premier poste de consommation.
  • Regroupez les mesures. Lisez le capteur chaque minute pendant le lightsleep, conservez les valeurs dans une liste et publiez-les toutes dans un seul message toutes les dix minutes. Vous payez le Wi-Fi une fois au lieu de dix.
  • Améliorez la liaison Wi-Fi. Placez le nœud là où le signal est fort. Un signal faible signifie des retransmissions, des débits plus lents et un temps d'éveil plus long.
  • Utilisez une minuterie d'alimentation externe. Une puce de minuterie qui coupe l'alimentation de toute la carte et la rétablit selon un planning supprime totalement les courants du régulateur et de veille. Dans ce montage, le script s'exécute une fois depuis un démarrage à froid, publie, puis signale à la minuterie de couper. Vous perdez la RAM entre les cycles : stockez les compteurs en flash avec parcimonie ou laissez le broker conserver l'état grâce aux retained messages.
  • Désactivez tout ce qui clignote. Les LED d'état du Pico et des cartes de capteurs consomment en permanence. Retirez ou coupez la LED d'alimentation des cartes de capteurs quand c'est possible.

Production : passer à des identifiants privés et à TLS

Le serveur public est idéal pour le développement, mais un capteur déployé doit utiliser vos propres identifiants. Sur un broker MQTT managé comme ConnectMQ, vous créez un broker dans le portail et recevez un nom d'utilisateur, un mot de passe et un client ID générés. Placez-les dans secrets.py en remplaçant YOUR_USERNAME, YOUR_PASSWORD et YOUR_CLIENT_ID. Le client ID est lié aux identifiants émis : chaque nœud a donc besoin de celui généré pour lui.

TLS sur le port 8883 ajoute une négociation à chaque réveil, ce qui allonge le temps d'éveil et coûte donc de la batterie. Pour des capteurs sur un réseau domestique de confiance, certains acceptent le TCP en clair ; pour tout ce qui sort d'un bâtiment, le chiffrement vaut ce coût. Le tutoriel Pico W MQTT sur TLS montre la configuration du contexte SSL en MicroPython. Mesurez awake_ms avant et après pour connaître l'impact réel sur votre nœud.

Les retained messages sont utiles ici aussi. Si vous publiez la dernière mesure avec le flag retain, un tableau de bord ouvert des heures plus tard affiche immédiatement la valeur la plus récente au lieu d'attendre jusqu'à dix minutes le prochain réveil. ConnectMQ prend en charge les retained messages sur toutes les offres, et le tableau de bord et l'explorateur de topics en direct du portail permettent de voir arriver les messages de chaque nœud sans écrire d'abonné.

Dépannage

Symptôme Cause probable Solution
vbat proche de zéro ou aléatoire Lecture ADC avec le Wi-Fi actif Lire VSYS avant wlan.active(True)
Le nœud publie une fois puis s'arrête Wi-Fi non désinitialisé avant le lightsleep Appeler active(False) et deinit()
OSError: -2 à la connexion Échec DNS ou Wi-Fi pas complètement opérationnel Vérifier isconnected() et réessayer une fois
awake_ms ne cesse d'augmenter Signal faible ou point d'accès chargé Déplacer le nœud ou le point d'accès
La batterie se vide bien plus vite que prévu LED, veille du capteur ou consommation du régulateur Retirer les LED, vérifier le mode veille du capteur, ajouter une minuterie d'alimentation

Démarrez avec ConnectMQ

Quand votre prototype Pico W est prêt à quitter l'établi, créez un broker privé dans le portail ConnectMQ sur app.connectmq.com. L'offre gratuite Serverless ne demande aucune carte bancaire, prend en charge le QoS 1 et jusqu'à 25 connexions, ce qui couvre largement une petite flotte de capteurs sur batterie. Pour d'autres projets Pi, le tutoriel Raspberry Pi MQTT rassemble toute la série.

Questions fréquentes

Combien de temps un Pico W tient-il sur batterie avec MQTT ?

Cela dépend surtout de l'intervalle de publication, du temps de connexion Wi-Fi et des piles utilisées : mesurez votre propre nœud plutôt que de vous fier à un chiffre unique. Journaliser awake_ms et vbat pendant quelques jours donne une tendance fiable à extrapoler.

Le Pico W peut-il rester connecté à MQTT pendant sa veille ?

Pas d'une manière compatible avec une batterie. Maintenir la session MQTT exige que la radio reste associée, ce qui vide vite les piles : reconnectez-vous plutôt à chaque réveil.

Faut-il utiliser le QoS 0 ou le QoS 1 pour un capteur sur batterie ?

Le QoS 1 est généralement le meilleur choix, car publish() attend l'accusé de réception du broker avant que vous coupiez la radio. L'aller-retour supplémentaire est faible comparé au coût de la connexion Wi-Fi.

machine.deepsleep est-il meilleur que le lightsleep sur le Pico W ?

Sur le portage MicroPython du RP2040, la différence est modeste, et le deepsleep réinitialise la carte, ce qui fait perdre l'état en RAM. Pour la plus grande autonomie, une minuterie externe qui coupe complètement l'alimentation surpasse les deux.

Articles liés

Journal d'accès RFID MQTT sur Raspberry Pi avec le lecteur RC522

Câblez un lecteur RFID RC522 sur un Raspberry Pi, lisez les badges en Python, vérifiez-les dans une liste blanche locale et publiez chaque tentative d'accès sous forme d'événement MQTT exploitable par vos outils de journalisation, tableaux de bord et alertes.

8 min de lecture

Installer Mosquitto sur Raspberry Pi comme broker MQTT local sécurisé

Installez Mosquitto sur un Raspberry Pi, sécurisez-le avec des mots de passe et une configuration de listener raisonnable, testez-le avec mosquitto_pub et mosquitto_sub, et découvrez quand un broker local doit faire un pont vers un broker cloud.

9 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.