La surveillance de la température en chambre froide protège les aliments, ingrédients, produits pharmaceutiques et échantillons qui peuvent être perdus en quelques heures lorsqu'un congélateur ou une chambre froide tombe en panne. Ce cas d'usage montre comment installer des capteurs MQTT dans les congélateurs et chambres froides, distinguer les vraies excursions de température des ouvertures de porte sans conséquence, détecter les capteurs qui passent hors ligne et tenir un journal des excursions présentable à un auditeur.
Ce qui peut mal tourner en chambre froide
La plupart des pertes en chambre froide ne viennent pas de pannes spectaculaires. Elles proviennent d'événements ordinaires que personne ne remarque à temps :
- Une porte restée entrouverte après une livraison de nuit.
- Un compresseur qui disjoncte par un après-midi chaud et ne redémarre pas.
- Un évaporateur qui givre, si bien que la chambre se réchauffe lentement pendant des heures.
- Une coupure de courant pendant le week-end.
- Un cycle de dégivrage qui dure trop longtemps après une modification du régulateur.
Un relevé manuel des températures, rempli deux fois par poste, ne détecte aucun de ces événements entre deux relevés. Une surveillance continue avec alertes comble ce manque. Les mêmes principes s'appliquent au transport frigorifique, traité dans l'article sur la surveillance de la chaîne du froid ; celui-ci se concentre sur les congélateurs et chambres froides fixes d'une usine, d'un entrepôt ou d'une cuisine.
L'installation
| Composant | Rôle | Exemple |
|---|---|---|
| Sonde de température | Mesure la température de l'air ou du produit | DS18B20 étanche sur câble plat passant par le joint de porte |
| Contact de porte | Explique les brèves hausses de température | Interrupteur reed sur le cadre de porte |
| Nœud capteur | Lit la sonde et la porte, publie | ESP32 monté à l'extérieur du congélateur, sur secteur |
| Broker MQTT | Reçoit les mesures et les alertes | Broker MQTT managé ConnectMQ |
| Logique d'alerte | Détection des excursions et des capteurs hors ligne | Règles de seuil du portail plus un service Python |
| Journal des excursions | Preuve pour les audits et les réclamations | Base de données alimentée par le service d'alerte |
Gardez l'ESP32 à l'extérieur de l'espace froid. L'électronique et les piles supportent mal les températures de congélation, et le Wi-Fi ne traverse pas les parois métalliques d'une chambre froide. Seul le câble de la sonde entre à l'intérieur.
Où placer la sonde
La température de l'air près de l'évaporateur varie rapidement et exagère chaque ouverture de porte. La température du produit évolue lentement et reflète ce qui compte vraiment. Un compromis courant consiste à placer la sonde dans la zone la plus chaude de la chambre, loin de la sortie de l'évaporateur, et éventuellement dans un petit flacon de glycol ou un simulant de produit qui l'amortit, afin que les mesures suivent la température du produit plutôt que les bouffées d'air. Cartographiez une fois la chambre avec quelques sondes pour trouver le point chaud avant de choisir la position définitive.
Firmware du capteur
Le sketch ci-dessous publie la température et l'état de la porte toutes les 30 secondes, et immédiatement lorsque la porte change d'état. Il définit un message Last Will afin que le broker annonce le capteur hors ligne s'il disparaît. Installez PubSubClient, OneWire et DallasTemperature. Pour le câblage du capteur, consultez le tutoriel ESP32 DS18B20 MQTT.
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* CLIENT_ID = "freezer2-6c0f3b";
const char* BASE = "connectmq/demo/6c0f3b/warehouse/freezer2";
const int PROBE_PIN = 4;
const int DOOR_PIN = 27; // interrupteur reed vers GND, porte fermée = LOW
const uint32_t PERIOD_MS = 30000;
OneWire oneWire(PROBE_PIN);
DallasTemperature probe(&oneWire);
WiFiClient net;
PubSubClient mqtt(net);
char topicTelemetry[96], topicStatus[96];
int lastDoor = -1;
uint32_t lastPub = 0;
void connectAll() {
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(250);
}
while (!mqtt.connected()) {
if (mqtt.connect(CLIENT_ID, topicStatus, 1, true, "offline")) {
mqtt.publish(topicStatus, "online", true);
} else {
delay(3000);
}
}
}
void publishReading(bool doorOpen) {
probe.requestTemperatures();
float t = probe.getTempCByIndex(0);
char payload[128];
if (t == DEVICE_DISCONNECTED_C) {
snprintf(payload, sizeof(payload), "{\"temp_c\":null,\"door_open\":%s,\"fault\":\"probe\"}",
doorOpen ? "true" : "false");
} else {
snprintf(payload, sizeof(payload), "{\"temp_c\":%.2f,\"door_open\":%s,\"rssi\":%d}",
t, doorOpen ? "true" : "false", WiFi.RSSI());
}
mqtt.publish(topicTelemetry, payload, true);
}
void setup() {
pinMode(DOOR_PIN, INPUT_PULLUP);
snprintf(topicTelemetry, sizeof(topicTelemetry), "%s/telemetry", BASE);
snprintf(topicStatus, sizeof(topicStatus), "%s/status", BASE);
probe.begin();
WiFi.mode(WIFI_STA);
mqtt.setServer("broker.connectmq.com", 1883);
connectAll();
}
void loop() {
connectAll();
mqtt.loop();
int door = digitalRead(DOOR_PIN) == HIGH; // HIGH = aimant éloigné = porte ouverte
if (door != lastDoor || millis() - lastPub >= PERIOD_MS) {
publishReading(door);
lastDoor = door;
lastPub = millis();
}
delay(200);
}
Le Last Will est le filet de sécurité qu'un relevé manuel n'a jamais eu : si le nœud perd son alimentation ou le Wi-Fi, le broker publie offline sur son topic de statut après l'expiration du keepalive. Le guide Last Will MQTT sur ESP32 explique le mécanisme.
Logique d'excursion sans alarmes intempestives
L'approche naïve, une alarme dès que la température dépasse la limite, échoue en moins d'une journée. Chaque livraison ouvre la porte, la température de l'air grimpe en flèche et le personnel apprend à ignorer l'alarme. Une bonne surveillance de la température en chambre froide combine plusieurs règles :
- Limite plus temporisation. Ne déclarez une excursion que si la température reste au-dessus de la limite pendant une durée définie, par exemple 15 minutes pour un congélateur.
- Temporisation tenant compte de la porte. Tant que la porte est ouverte, accordez un délai de grâce plus long, mais levez une alerte distincte de porte ouverte si elle le reste trop longtemps.
- Limite critique. Une température beaucoup plus élevée déclenche immédiatement, quelle que soit la temporisation.
- Capteur hors ligne et défaut de sonde. Un capteur muet ou une sonde déconnectée constituent une alerte à part entière.
- Enregistrement des excursions. Chaque excursion reçoit une heure de début, une heure de fin, une température maximale et une durée.
Les limites elles-mêmes découlent de vos produits et de votre plan de sécurité alimentaire ou qualité. Utilisez ces documents plutôt que des chiffres génériques.
Service d'excursion en Python
import json
import sqlite3
import time
import paho.mqtt.client as mqtt
PREFIX = "connectmq/demo/6c0f3b/warehouse"
LIMIT_C = -15.0 # selon les exigences de vos produits
HARD_LIMIT_C = -5.0
DELAY_S = 15 * 60
DOOR_MAX_S = 5 * 60
STALE_S = 3 * 60
db = sqlite3.connect("excursions.db", check_same_thread=False)
db.execute("""CREATE TABLE IF NOT EXISTS excursions (
unit TEXT, start_ts INTEGER, end_ts INTEGER, peak_c REAL, reason TEXT)""")
units = {}
def alert(client, unit, kind, detail):
msg = {"ts": int(time.time()), "unit": unit, "kind": kind, **detail}
client.publish(f"{PREFIX}/{unit}/alert", json.dumps(msg), qos=1, retain=True)
print("ALERT", msg)
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(f"{PREFIX}/+/telemetry", qos=1)
client.subscribe(f"{PREFIX}/+/status", qos=1)
def on_message(client, userdata, msg):
unit = msg.topic.split("/")[4]
now = time.time()
u = units.setdefault(unit, {"above_since": None, "door_since": None,
"excursion": None, "seen": now})
if msg.topic.endswith("/status"):
if msg.payload == b"offline":
alert(client, unit, "offline", {})
return
d = json.loads(msg.payload)
u["seen"] = now
if d.get("temp_c") is None:
alert(client, unit, "probe_fault", {})
return
t = d["temp_c"]
u["door_since"] = (u["door_since"] or now) if d["door_open"] else None
if u["door_since"] and now - u["door_since"] > DOOR_MAX_S:
alert(client, unit, "door_open_too_long", {"seconds": int(now - u["door_since"])})
u["door_since"] = now
if t > LIMIT_C:
u["above_since"] = u["above_since"] or now
delay = DELAY_S * (2 if d["door_open"] else 1)
exc = u["excursion"]
if exc:
exc["peak"] = max(exc["peak"], t)
elif t > HARD_LIMIT_C or now - u["above_since"] > delay:
u["excursion"] = {"start": u["above_since"], "peak": t}
alert(client, unit, "excursion_start", {"temp_c": t, "limit_c": LIMIT_C})
else:
exc = u["excursion"]
if exc:
db.execute("INSERT INTO excursions VALUES (?,?,?,?,?)",
(unit, int(exc["start"]), int(now), exc["peak"], "above_limit"))
db.commit()
alert(client, unit, "excursion_end",
{"duration_min": round((now - exc["start"]) / 60, 1), "peak_c": exc["peak"]})
u["above_since"] = None
u["excursion"] = None
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="cold-alerts-6c0f3b")
client.on_connect = on_connect
client.on_message = on_message
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()
while True:
time.sleep(30)
for unit, u in units.items():
if time.time() - u["seen"] > STALE_S:
alert(client, unit, "stale", {"seconds_silent": int(time.time() - u["seen"])})
u["seen"] = time.time()
L'heure de début d'excursion est enregistrée au moment où la température a franchi la limite pour la première fois, et non à l'expiration de la temporisation : le journal affiche ainsi la durée réelle. Pour les cas les plus simples, vous pouvez aussi créer des règles d'alerte sur seuil sur le champ temp_c directement dans le portail ConnectMQ et consulter chaque franchissement dans son journal des alertes, en gardant le service Python pour la logique de temporisation et de porte.
Faire parvenir les alertes aux bonnes personnes
Le service publie les alertes sur MQTT ; encore faut-il qu'elles atteignent un téléphone à 3 heures du matin. Comme ConnectMQ n'envoie lui-même ni e-mails ni SMS, la solution honnête est un outil externe abonné aux topics d'alerte : un flux Node-RED avec un nœud e-mail ou messagerie, les notifications Home Assistant pour les petits sites, ou quelques lignes supplémentaires dans le service Python qui appellent votre fournisseur de notifications. Définissez un circuit d'escalade : d'abord le chef d'équipe, puis l'astreinte maintenance, puis le responsable de site si personne n'acquitte.
Gérer les cycles de dégivrage
Le dégivrage automatique est l'autre source fréquente de fausses alarmes. Pendant le dégivrage, l'évaporateur chauffe et la température de l'air à proximité monte brièvement, ce qui est normal. Trois mesures l'empêchent de déclencher des excursions. D'abord, éloignez la sonde de l'évaporateur, comme décrit plus haut. Ensuite, assurez-vous que la temporisation d'excursion est plus longue qu'une période de dégivrage normale sur cette unité, ce qui se voit clairement sur une journée de données enregistrées. Enfin, si le régulateur frigorifique expose un signal de dégivrage, publiez-le avec la température et prolongez la temporisation pendant le dégivrage, exactement comme le service le fait pour les ouvertures de porte. Un dégivrage beaucoup plus long que d'habitude mérite lui-même une alerte, car il signale souvent une résistance, une sonde ou un réglage de régulateur défaillant.
Check-list de déploiement
- Cartographiez chaque chambre avec plusieurs sondes pendant une journée pour trouver le point chaud.
- Installez un nœud par unité, électronique à l'extérieur, sonde au point chaud.
- Définissez limites et temporisations à partir des exigences de vos produits et de votre plan qualité.
- Testez les alarmes : ouvrez la porte, débranchez un nœud, déconnectez une sonde et vérifiez que chaque alerte arrive.
- Étalonnez les sondes par rapport à un thermomètre de référence et consignez la vérification.
- Passez en revue le journal des excursions chaque semaine et traitez les récidivistes, comme une porte souvent laissée ouverte.
- Passez à un broker privé avec des identifiants issus du portail et TLS sur le port 8883 avant la mise en service.
De la démo à la production
Le tutoriel s'exécute sur le serveur MQTT public gratuit, où tous les topics sont visibles par n'importe qui, ce qui convient aux tests mais pas aux données d'exploitation. En production, un broker MQTT cloud offre à chaque nœud de congélateur une connexion chiffrée et authentifiée, et permet au service d'alerte, aux tableaux de bord et à l'équipe qualité de s'abonner depuis n'importe où. Les relevés de température complètent aussi le contrôle qualité IoT dans l'industrie et la traçabilité industrielle par lot, puisque les fenêtres d'excursion peuvent être reliées aux lots stockés à ce moment-là. Le guide de l'industrie intelligente intègre tout cela dans une architecture à l'échelle de l'usine.
Surveillez vos chambres froides avec ConnectMQ
ConnectMQ fournit un broker MQTT managé privé avec TLS, prise en charge du Last Will, retained messages, tableau de bord en direct et règles d'alerte sur seuil dans le portail. Créez un broker avec l'offre Serverless gratuite sur app.connectmq.com, sans carte bancaire, et connectez votre premier congélateur dès aujourd'hui.
Questions fréquentes
À quelle fréquence enregistrer la température d'une chambre froide ?
Toutes les 30 secondes à 5 minutes, en général, pour une surveillance continue. Des remontées plus fréquentes accélèrent les alertes, tandis que la temporisation d'excursion évite les alarmes intempestives.
Comment éviter une alarme à chaque ouverture de porte ?
Exigez que la température reste au-dessus de la limite pendant une temporisation avant d'alerter, prolongez cette temporisation tant que la porte est ouverte, et alertez séparément si la porte reste ouverte trop longtemps.
Que se passe-t-il si un capteur perd son alimentation ?
Grâce au message Last Will, le broker publie un statut hors ligne après l'expiration du keepalive, et le service d'alerte le traite comme une alarme.
La sonde doit-elle mesurer la température de l'air ou du produit ?
C'est la température du produit qui compte le plus. Placer la sonde dans un tampon, comme un flacon de glycol au point le plus chaud, donne des mesures qui suivent la température du produit et ignorent les brefs pics d'air.



