Sécurisez votre chauffe-eau : Moniteur de tension thermocouple pour veilleuse pilote
Composants et fournitures
| Composant | Quantité |
|---|---|
| Raspberry Pi Zero WH | 1 |
| Arduino Nano R3 | 1 |
À propos du projet
Système de surveillance de la veilleuse du chauffe-eau à gaz
Les chauffe-eau à gaz traditionnels maintiennent une veilleuse (pilot light) 24/7. Celle-ci chauffe un thermocouple qui génère une faible tension (jusqu'à 30 mV). Cette tension maintient ouvert le robinet de gaz via le thermostat. Si la veilleuse s'éteint, la tension tombe à zéro et le robinet se ferme automatiquement – pas de fuite de gaz.
Sur mon chauffe-eau, la veilleuse s'éteint parfois (~3 fois/an). Remplacer le thermocouple n'a pas résolu le problème. Solution : surveiller la tension du thermocouple. Si elle chute à zéro, envoyer SMS et email pour rallumer la veilleuse.
Vue d'ensemble
Un Raspberry Pi Zero WH envoie les notifications (email/SMS). Comme le Pi ne peut pas mesurer de tension analogique, un Arduino Nano lit la tension du thermocouple et la transmet au Pi via une liaison série à fil unique.
L'ADC 10 bits de l'Arduino (0-1023) avec référence 1,1 V (pour meilleure résolution sur 0-30 mV) donne une lecture max ~28. Le Pi reçoit cette valeur, et si elle reste trop basse pendant 5 mesures consécutives (2,5 min), il déclenche l'alerte.
Étape 1 : Préparer le Raspberry Pi
Mettez le Pi en route sur votre réseau. Créez un script Python qui écoute les signaux de l'Arduino, décode la valeur, et envoie les notifications si tension trop basse. Code source fourni ci-dessous.
Étape 2 : Préparer l'Arduino
Flashez l'Arduino Nano avec le sketch fourni (mesure tension sur A0 toutes les 30 s, référence 1,1 V, envoi sur broche numérique 9). Les Nanos chinois bon marché peuvent demander des essais pour faire reconnaître le port série sous Windows 10.
Étape 3 : Connecter l'Arduino au thermocouple

Le thermocouple est relié au thermostat par un câble coaxial (extérieur = positif). Coupez le câble à ~13 cm du thermostat. Reculer la gaine externe pour accéder au conducteur central sans abîmer son isolation (éviter court-circuit).

Connectez :
- Conducteur central → broche A0 Arduino + thermostat (positif)
- Blindage (extérieur) → GND Arduino + thermostat (négatif)
Utilisez des fils à pinces crocodiles (30 cm) pour les connexions.

Étape 4 : Connecter l'Arduino au Raspberry Pi
L'Arduino envoie sur sa broche numérique 9 (5 V). Le Pi ne tolère que 3,3 V sur ses GPIO. Il faut un diviseur de tension (deux résistances) pour abaisser 5 V → ~2,8 V.

Formule : Vout = Vin × R2 / (R1 + R2). Choisissez R1, R2 pour Vout ≤ 3,3 V. Tous les GND (Arduino, Pi, thermostat) doivent être communs.

Une seule résistance ne suffit pas : sans courant, la tension de part et d'autre serait 5 V. Le diviseur maintient la tension réduite même sans courant.
Étape 5 : Transmission Arduino (toutes les 30 s)
Le sketch lit l'ADC, convertit en nombre (0-1023), et l'envoie sur la broche 9 via un protocole série « maison » à fil unique :
- Un chiffre = série d'impulsions positives (20 ms haut, 20 ms bas).
- Chiffre des dizaines : impulsion de départ + N impulsions (N = valeur).
- Pause 50 ms → chiffre des unités : même principe.
- Pause 50 ms → fin du nombre à 2 chiffres.
Étape 6 : Réception sur Raspberry Pi (Python)
Boucle infinie : attend front montant sur GPIO 16. Décode les intervalles :
- < 70 ms entre fronts = même chiffre (incrémente).
- > 70 ms = chiffre suivant.
- Timeout 200 ms = fin du nombre à 2 chiffres.
La valeur décodée (0-1023) est convertie en tension : voltage = reading × 1.1 / 1023.
Étape 7 : Envoi de la notification
- Seuil bas : lecture ≤ 1 (≈ 1 mV).
- Compteur
lowVoltageCountincrémenté à chaque lecture basse. Si ≥ 5 → alarme. - Envoi email/SMS via
smtplib(Gmail + mot de passe d'application). - SMS via passerelle opérateur : ex.
5555555555@vtext.com(Verizon). - Anti-spam : 1 notification max toutes les 6 heures (timestamp stocké).
Étape 8 : Tout connecter

Arduino → thermocouple + diviseur → Pi GPIO 16. Alimentez l'Arduino : il commence à mesurer et signaler toutes les 30 s.
Étape 9 : Lancer le script Python au démarrage
# Script de lancement : /home/pi/hotwater/run_HotWaterNotifier.sh
#!/bin/bash
cd /home/pi/hotwater
sudo python HotWaterNotifier.py
Ajoutez au crontab root :
sudo crontab -e
@reboot sh /home/pi/hotwater/run_HotWaterNotifier.sh >> /home/pi/hotwater/logs/HotWaterNotifier.log 2>&1
Pour test manuel : lancez le script, Ctrl+Z, bg, disown. Vérifiez avec ps aux | grep -i HotWater.

Code source
Code Arduino
/*******************************************************************************
* HotWaterHeater – Mesure tension thermocouple, signale au Raspberry Pi
******************************************************************************/
double ReferenceVoltage = 1.1;
int OUTPUT_PIN = 9;
int INTRA_DIGIT_WAIT = 20;
int BETWEEN_DIGIT_WAIT = 50;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(OUTPUT_PIN, OUTPUT);
analogReference(INTERNAL); // 1,1 V
Serial.begin(9600);
}
void loop() {
int pinInput = analogRead(A0);
double voltage = (pinInput * ReferenceVoltage) / 1023.0;
Serial.print("PinInputA0="); Serial.print(pinInput);
Serial.print(", voltageA0="); Serial.println(voltage);
sendNumberSignal(pinInput, OUTPUT_PIN, INTRA_DIGIT_WAIT, BETWEEN_DIGIT_WAIT);
delay(30000); // 30 secondes
}
void sendNumberSignal(int number, int pin, int intra, int between) {
int tens = number / 10;
int ones = number % 10;
sendPulse(pin, intra);
for (int i = 0; i < tens; i++) sendPulse(pin, intra);
delay(between);
sendPulse(pin, intra);
for (int i = 0; i < ones; i++) sendPulse(pin, intra);
delay(between);
}
void sendPulse(int pin, int wait) {
digitalWrite(pin, HIGH);
delay(wait);
digitalWrite(pin, LOW);
delay(wait);
}
Code Python (Raspberry Pi)
###############################################################################
# HotWaterNotifier.py – Surveille GPIO 16, décode signaux Arduino, alerte si tension basse
###############################################################################
import smtplib, RPi.GPIO as GPIO, os, time, datetime, logging, sys
GPIO_Alert = 16
emailWaitHours = 6
lowSensorReading = 1
maxLowVoltageCount = 5
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_Alert, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s %(levelname)-8s %(message)s',
handlers=[logging.FileHandler('HotWaterLog.txt'), logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger('HotWaterNotifier')
lastEmailSentTime = datetime.datetime(2000,1,1)
def send_email_alert():
global lastEmailSentTime
now = datetime.datetime.now()
if lastEmailSentTime is None or (now - datetime.timedelta(hours=emailWaitHours)) > lastEmailSentTime:
logger.info('Envoi alerte email...')
HOST, PORT = "smtp.gmail.com", 587
SUBJECT = "Alerte Chauffe-eau"
TO = ["votre@email.com", "5555555555@vtext.com"]
FROM = "votre@gmail.com"
PWD = "MOT_DE_PASSE_APPLICATION_GMAIL"
TEXT = "Tension faible détectée sur le chauffe-eau"
BODY = "\r\n".join([f"from: {FROM}", f"to: {', '.join(TO)}", f"Subject: {SUBJECT}", "", TEXT])
try:
s = smtplib.SMTP(HOST, PORT)
s.starttls()
s.login(FROM, PWD)
s.sendmail(FROM, TO, BODY)
s.quit()
lastEmailSentTime = now
except Exception as e:
logger.exception('Erreur envoi email')
lastEmailSentTime = now
else:
logger.info(f'Pas d\'envoi. Dernier email: {lastEmailSentTime}')
def waitReceiveNumber(pin):
lastSignal = datetime.datetime(2000,1,1)
isTens = True
first = True
tens = ones = 0
singleDigitMax = datetime.timedelta(milliseconds=70)
wholeNumberTimeout = 200
while True:
if first:
GPIO.wait_for_edge(pin, GPIO.RISING, timeout=-1)
first = False
else:
edge = GPIO.wait_for_edge(pin, GPIO.RISING, timeout=wholeNumberTimeout)
signalTime = datetime.datetime.now()
interval = signalTime - lastSignal
lastSignal = signalTime
if interval < singleDigitMax or first:
if isTens: tens += 1
else: ones += 1
elif edge is not None:
if isTens:
isTens = False
ones += 1
else:
return (tens-1)*10 + (ones-1)
else:
return (tens-1)*10 + (ones-1)
def main():
logger.info('Démarrage HotWaterNotifier')
refV = 1.1
lowCount = 0
try:
while True:
reading = waitReceiveNumber(GPIO_Alert)
voltage = (reading * refV) / 1023.0
logger.info(f'reading: {reading}, voltage: {voltage:.4f}')
if reading <= lowSensorReading:
lowCount += 1
if lowCount >= maxLowVoltageCount:
logger.info('Alerte tension basse')
send_email_alert()
lowCount = 0
else:
lowCount = 0
except KeyboardInterrupt:
logger.info('Interruption clavier')
finally:
GPIO.cleanup()
if __name__ == "__main__":
main()
Script de lancement (SH)
#!/bin/bash # run_HotWaterNotifier.sh cd /home/pi/hotwater sudo python HotWaterNotifier.py
Processus de fabrication
- Centre Énergie Domestique : Surveillance panneaux solaires PV, thermiques et températures pièces avec Raspberry Pi et Moteino
- Créer un système Ambilight spectaculaire pour moniteur avec Arduino
- Surveillance temps réel de panneau solaire avec Arduino : Acquisition de données bas coût
- Photographie Haute Vitesse : Capturez les Gouttes d'Eau avec Arduino Nano
- Moniteur d'énergie Arduino & Data Logger fiable – Guide complet (Dr. Wattson + carte SD)
- Moniteur de Fréquence Cardiaque IoT en Temps Réel avec Arduino et MAX30100
- Chauffe-eau thermodynamique optimal : solutions d'eau chaude écoénergétiques
- Comment choisir la meilleure pompe à eau chaude domestique – Conseils d'expert et guide
- Les bases des pompes à eau chaude : fonctionnement et importance