Un montage ESP32 avec capteur de courant SCT-013 est le moyen non invasif le moins cher de savoir combien consomme un circuit, car la pince se referme autour d'un câble sans rien couper. Dans ce tutoriel, vous allez réaliser le circuit de polarisation, calculer le courant RMS avec l'ADC de l'ESP32, estimer la puissance et les kWh, puis publier les résultats via MQTT vers broker.connectmq.com pour un tableau de bord énergétique.
La sécurité avant tout
Le SCT-013 lui-même est une pince à noyau ouvrant qui ne touche jamais les conducteurs sous tension, ce qui rend ce projet accessible. L'armoire dans laquelle il s'installe, c'est une autre histoire. Ouvrir un tableau électrique ou un tableau de distribution expose à des tensions mortelles. Si vous n'êtes pas qualifié, ne posez la pince que sur un câble déjà accessible, par exemple le cordon d'un appareil dont les conducteurs sont séparés dans un adaptateur prévu à cet effet, ou demandez à un électricien d'installer la pince. N'ouvrez jamais la pince d'un SCT-013-000 traversé par un courant sans résistance de charge (burden) en place : un transformateur de courant à vide peut développer une tension dangereuse sur ses fils.
Choisir la bonne variante de SCT-013
| Modèle | Sortie | Résistance de charge nécessaire | Plage | Conversion |
|---|---|---|---|---|
| SCT-013-000 | Courant, 50 mA à 100 A | Oui, externe | Jusqu'à 100 A | Dépend de votre résistance de charge |
| SCT-013-030 | Tension, 1 V RMS à 30 A | Non, intégrée | Jusqu'à 30 A | 30 A par volt |
| SCT-013-020 | Tension, 1 V RMS à 20 A | Non, intégrée | Jusqu'à 20 A | 20 A par volt |
| SCT-013-005 | Tension, 1 V RMS à 5 A | Non, intégrée | Jusqu'à 5 A | 5 A par volt |
Pour un premier montage, choisissez une version à sortie en tension dimensionnée pour le circuit. Une meilleure résolution aux faibles courants s'obtient en choisissant la plus petite plage couvrant votre charge maximale : une pince de 5 A sur le circuit d'un réfrigérateur donne des mesures bien meilleures qu'une pince de 100 A.
Si vous utilisez le SCT-013-000, ajoutez une résistance de charge aux bornes de sa sortie. Une résistance de 22 Ohm maintient la tension crête sous environ 1,6 V à 100 A RMS, ce qui convient au circuit de polarisation ci-dessous, et donne une conversion de 2000 / 22, soit environ 90,9 A par volt.
Le circuit de polarisation
La pince produit un signal alternatif qui oscille en positif et en négatif autour de zéro. L'ADC de l'ESP32 ne lit que de 0 à environ 3,1 V : le signal doit donc être décalé autour d'un point milieu continu.
- Branchez deux résistances égales (10 kOhm chacune) en série entre 3V3 et GND. Leur point de jonction se situe à environ 1,65 V.
- Branchez un condensateur électrolytique de 10 uF entre la jonction et GND pour stabiliser le point milieu.
- Reliez un fil de la pince (la pointe de la fiche jack 3,5 mm) à la jonction.
- Reliez l'autre fil (le manchon) à l'entrée ADC, GPIO 34.
Avec une sortie de 1 V RMS, le signal culmine à environ 1,41 V : l'ADC voit donc approximativement de 0,24 V à 3,06 V. Cela reste dans la plage de l'atténuation par défaut. Utilisez une broche de l'ADC1 (GPIO 32 à 39 sur un ESP32 classique) ; les broches de l'ADC2 ne peuvent pas être lues lorsque le Wi-Fi est actif.
Mesurer le courant RMS
Le code échantillonne l'ADC aussi vite que possible pendant 200 ms, ce qui couvre 10 cycles complets à 50 Hz et 12 à 60 Hz. Il calcule la moyenne (le point milieu continu, mesuré plutôt que supposé) et l'écart type autour de celle-ci, qui correspond exactement à la valeur RMS de la composante alternative. En multipliant par le facteur de conversion de la pince, on obtient des ampères.
Mesurer le point milieu à chaque passage élimine les erreurs dues à la tolérance des résistances et à la dérive de l'alimentation, et analogReadMilliVolts() applique l'étalonnage d'usine de l'ADC, ce qui aide face à la non-linéarité connue de l'ADC de l'ESP32.
Le sketch ESP32 avec capteur de courant SCT-013
#include <WiFi.h>
#include <PubSubClient.h>
#include <Preferences.h>
#include <math.h>
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* PREFIX = "connectmq/demo/sct3m8w"; // utilisez votre propre identifiant aléatoire
const uint8_t CT_PIN = 34; // broche ADC1
const float AMPS_PER_VOLT = 30.0f; // SCT-013-030 ; 90.9 pour le -000 avec une résistance de charge de 22 Ohm
const float MAINS_VOLTAGE = 230.0f; // 120.0 en Amérique du Nord
const float CALIBRATION = 1.00f; // à ajuster après comparaison avec une pince multimètre
const float NOISE_FLOOR_A = 0.08f; // les mesures inférieures sont ramenées à 0
const uint32_t WINDOW_MS = 200;
const uint32_t PUBLISH_MS = 10000;
const uint32_t SAVE_MS = 600000; // sauvegarder l'énergie toutes les 10 min
WiFiClient net;
PubSubClient mqtt(net);
Preferences prefs;
String clientId, tPower, tStatus;
double energyKwh = 0;
uint32_t lastSample = 0, lastPublish = 0, lastSave = 0;
float lastIrms = 0, sumIrms = 0;
uint32_t samplesInPeriod = 0;
float readIrms() {
uint32_t n = 0;
double sum = 0, sumSq = 0;
uint32_t start = millis();
while (millis() - start < WINDOW_MS) {
double mv = analogReadMilliVolts(CT_PIN);
sum += mv;
sumSq += mv * mv;
n++;
}
double mean = sum / n;
double variance = sumSq / n - mean * mean;
if (variance < 0) variance = 0;
double vrms = sqrt(variance) / 1000.0; // volts RMS de la composante alternative
float irms = vrms * AMPS_PER_VOLT * CALIBRATION;
return irms < NOISE_FLOOR_A ? 0.0f : irms;
}
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(300);
Serial.printf("Wi-Fi OK, IP %s\n", WiFi.localIP().toString().c_str());
}
void connectMqtt() {
while (!mqtt.connected()) {
if (mqtt.connect(clientId.c_str(), tStatus.c_str(), 1, true, "offline")) {
mqtt.publish(tStatus.c_str(), "online", true);
Serial.println("MQTT connected");
} else {
Serial.printf("MQTT failed, state %d\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
prefs.begin("energy", false);
energyKwh = prefs.getDouble("kwh", 0.0);
clientId = "esp32-sct013-" + String((uint32_t)ESP.getEfuseMac(), HEX);
tPower = String(PREFIX) + "/power";
tStatus = String(PREFIX) + "/status";
connectWifi();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setBufferSize(512);
connectMqtt();
lastSample = lastPublish = lastSave = millis();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) connectWifi();
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
// Échantillonner environ une fois par seconde et intégrer l'énergie
uint32_t now = millis();
if (now - lastSample >= 1000) {
float irms = readIrms();
float dtHours = (millis() - lastSample) / 3600000.0f;
lastSample = millis();
energyKwh += (irms * MAINS_VOLTAGE) * dtHours / 1000.0;
lastIrms = irms;
sumIrms += irms;
samplesInPeriod++;
mqtt.loop();
}
if (now - lastPublish >= PUBLISH_MS && samplesInPeriod > 0) {
lastPublish = now;
float avgIrms = sumIrms / samplesInPeriod;
sumIrms = 0;
samplesInPeriod = 0;
char payload[200];
snprintf(payload, sizeof(payload),
"{\"irms\":%.2f,\"irmsAvg\":%.2f,\"apparentPowerVA\":%.0f,"
"\"energyKwh\":%.4f,\"voltageAssumed\":%.0f}",
lastIrms, avgIrms, avgIrms * MAINS_VOLTAGE, energyKwh, MAINS_VOLTAGE);
mqtt.publish(tPower.c_str(), payload);
Serial.println(payload);
}
if (now - lastSave >= SAVE_MS) {
lastSave = now;
prefs.putDouble("kwh", energyKwh); // limiter les écritures protège la flash
}
}
Chaque fenêtre de mesure bloque la boucle pendant 200 ms, ce qui est sans conséquence pour les keep-alives MQTT, puisque le sketch appelle mqtt.loop() juste après l'échantillonnage. Si vous ajoutez d'autres pinces, lisez-les l'une après l'autre dans le même passage, ou déplacez l'échantillonnage dans sa propre tâche FreeRTOS comme le montre le guide ESP32 FreeRTOS MQTT, afin que le code réseau n'attende jamais derrière une longue série de fenêtres.
Tester et étalonner
Abonnez-vous au topic :
mosquitto_sub -h broker.connectmq.com -p 1883 -i sct-view-3m8w -t "connectmq/demo/sct3m8w/#" -v
Sans rien en marche, irms doit indiquer 0. Allumez une charge résistive connue, comme une bouilloire ou un radiateur, et comparez irms avec une pince multimètre sur le même conducteur. Ajustez CALIBRATION selon le rapport entre les deux mesures, par exemple 1,04 si l'ESP32 lit 4 % trop bas. Étalonnez vers le milieu de la plage de la pince pour la meilleure précision globale.
La zone publique du broker est lisible par tous, et les profils de consommation électrique peuvent révéler quand un logement est occupé : utilisez-la uniquement pour des essais sur l'établi. Ses limites sont listées sur la page du serveur MQTT public gratuit.
Ce que signifient les chiffres
Le sketch publie la puissance apparente en voltampères, calculée à partir du courant mesuré et d'une tension secteur supposée. Pour des charges résistives comme les bouilloires et les radiateurs, la puissance apparente est proche de la puissance active en watts. Pour les moteurs, compresseurs, alimentations et drivers de LED, le facteur de puissance est inférieur à 1 : la puissance active est donc inférieure à la valeur en VA. La tension secteur varie aussi au cours de la journée.
La puissance active nécessite également une mesure de tension, généralement via un transformateur AC-AC isolé alimentant une seconde broche ADC, plus une multiplication échantillon par échantillon. C'est une étape suivante intéressante, mais la version basée sur le seul courant suffit déjà pour voir quel appareil fonctionne et quand, repérer les consommations en veille et comparer les journées.
Liste de vérification de la précision
- Placez la pince autour d'un seul conducteur. Autour d'un câble entier, les courants de phase et de neutre s'annulent et vous lisez une valeur proche de zéro.
- Choisissez la plus petite plage de pince couvrant votre courant maximal.
- Gardez les fils analogiques courts et éloignés des antennes Wi-Fi et des alimentations à découpage.
- Mesurez le point milieu à chaque fenêtre au lieu de supposer 1,65 V.
- Appliquez un seuil de bruit pour qu'un circuit au repos indique 0, et non quelques centaines de milliampères.
- Étalonnez par rapport à un appareil de mesure fiable avec une charge résistive.
Construire un tableau de bord énergétique
Côté réception, un abonné transforme les messages en graphiques. Le consommateur MQTT de Telegraf peut analyser le JSON et l'écrire dans InfluxDB pour Grafana, Node-RED peut calculer les totaux journaliers et les coûts, et Home Assistant peut traiter energyKwh comme un capteur d'énergie via une définition de capteur MQTT ; dans une maison connectée, Jeedom et Domoticz savent aussi communiquer en MQTT. Tous se connectent au broker comme des clients MQTT normaux. Si vous surveillez plusieurs circuits ou températures à la fois, associez ce nœud au projet multisonde DS18B20, ou lisez des compteurs existants avec la passerelle ESP32 Modbus RS485.
Pour la production, créez un broker sur app.connectmq.com, passez à WiFiClientSecure sur le port 8883 avec le certificat ISRG Root X1 et connectez-vous avec YOUR_CLIENT_ID, YOUR_USERNAME et YOUR_PASSWORD. Les règles d'alerte à seuil du portail ConnectMQ peuvent alors vous avertir lorsque le courant dépasse une limite, par exemple un circuit qui approche du calibre de son disjoncteur.
Démarrer avec ConnectMQ
Les données énergétiques ont le plus de valeur lorsqu'elles sont collectées en continu et restent privées. ConnectMQ est un broker MQTT managé avec TLS, MQTT 3.1.1 et 5.0, un explorateur de topics en direct et des alertes, et l'offre gratuite Serverless ne demande pas de carte bancaire. Pointez ce sketch vers votre broker et consultez le hub tutoriel IoT ESP32 pour d'autres projets de mesure.
Questions fréquentes
Le capteur de courant SCT-013 sur ESP32 peut-il mesurer la puissance active en watts ?
Avec le seul courant, il estime la puissance apparente en VA. La puissance active nécessite aussi une mesure de tension, afin que le code puisse tenir compte du facteur de puissance.
Pourquoi ma mesure indique-t-elle un courant alors que rien n'est allumé ?
Il s'agit du bruit de l'ADC et de parasites captés. Appliquez un seuil de bruit, gardez des fils courts et vérifiez que le condensateur du point milieu est bien en place.
Quelles broches de l'ESP32 puis-je utiliser pour le SCT-013 ?
Utilisez les broches de l'ADC1 (GPIO 32 à 39 sur un ESP32 classique). Les broches de l'ADC2 ne fonctionnent pas lorsque le Wi-Fi est actif.
Ai-je besoin d'une résistance de charge ?
Uniquement pour le SCT-013-000 à sortie en courant. Les versions à sortie en tension, comme le SCT-013-030, intègrent leur résistance de charge.



