Hello,
Je l’avais dit si je recevais les capteurs à temps et si j’avais le temps de tester. C’est le cas donc « I came back ». Pour vous présenter le lave linge notificator, la version la moins puissante du Terminator ![]()
Quelques composants de bases seront nécessaires mais pour une quinzaine d’euros, vous aurez un système complet de surveillance du lave linge sur vibrations et ouverture de porte. Avec démarrage et mise en veille automatique. Vous le branchez une fois et c’est tout.
Alors bien entendu on peut tout à fait faire la même chose avec des capteurs de vibrations et d’ouverture zigbee ( ou autre ) et l’automation qui va bien, sans à avoir à gérer le deepsleep ( mais la gestion des piles que j’exècre ) et pas certain que ça revienne beaucoup moins cher au final.
Comme j’aime à le dire, pourquoi mettre un NAS quand on peut mettre une baie de 250kg ![]()
Place au projet.
Il est parfois compliqué de trouver du matériel avec relevé de consommation supportant des pointes de plus de 10A, toutes les prises que j’ai pu tester sautent pendant le cycle avec des pics au dela de 10A du coup je suis resté sur des prises OSRAM sans suivi conso mais qui supportent la charge. Pour palier à ce problème j’ai envisagé une autre approche en suivant les vibrations générées par le lave linge.
Si porte ouverte le T00.001 s’endort et attend le moindre frémissement de la machine pour se remettre en mode surveillance.
Il lance le timer 1 et un décompte digne des plus grand films d’action jusqu’à lancer « Alerte! », le buzzer bip, si pendant ce timer 1 il y a des vibrations, le timer reset.
Si pas de vibrations, il lance le timer 2 de 60 secondes et prépare le deep sleep et la notification à Home assistant que la machine est terminée. Si pendant ce timer2 il y a des vibrations ( j’ai mis un filet de sécurité surtout pendant la phase de réglage, si la machine n’était pas terminée ) les 2 timers reset, il se remet en surveillance, et si tout va à terme, envoie l’info à HA machine terminée et entre en sommeil, jusqu’à ce qu’il détecte à nouveau des vibrations ( idéalement le claquement de la porte de la machine.
La première phase sera d’analyser le comportement du lave linge suivant les cycles utilisés ( on ne reste pas devant la machine … on a un Esp et un capteur de vibrations, on lance un cycle, on met un history graph dessus et on s’en va
) l’analyse sera faite après coup.
Schéma de principe
rien de compliqué tout est trouvable dans les bonnes crèmeries de matériel électronique.
-
ESP32 30 pins
-
SW 420 (capteur de vibrations)
-
Capteur d’ouverture avec sa résistance de pullup de 10kΩ (peut être activé en interne)
-
(optionnel) Buzzer 6V + BC547B (ou autre NPN du même type) + résistance de 10kΩ
-
(optionnel) Led + résistance 220Ω pour avoir l’état du deepsleep et le différencier de l’état de l’esp
lien direct vers le schéma.
Le code de l’esp ( détaillé sur le github, le lien est en bas de ce topic ).
substitutions:
name: esp-test
friendly_name: esp-test
wifi_bssid: "xx.xx.xx.xx.xx.xx"
static_ip: xx.xx.xx.xx
packages:
base: !include .base1.yaml
api:
encryption:
key: xxx
esphome:
name: esp32-bluetooth-proxy-24ae54
includes:
- sleep_patch.h
on_boot:
priority: -100
then:
- delay: 1s
- light.turn_on: status_light
- logger.log: "ESP démarré - Surveillance active"
- lambda: |-
// Initialiser les variables globales pour les timers
id(last_vibration_time) = millis();
id(ready_to_sleep) = false;
id(sleep_timer_start) = 0;
id(buzzer_blinking) = false;
id(buzzer_start_time) = 0;
ESP_LOGI("boot", "Timers réinitialisés");
logger:
level: DEBUG
output:
- platform: gpio
pin: GPIO05
id: buzzer_output
- platform: gpio
pin: GPIO12
id: status_led
light:
- platform: binary
name: "LED État ESP"
output: status_led
id: status_light
text_sensor:
- platform: template
name: "Timer1 2min sans vib"
id: countdown_display
update_interval: 1s
lambda: |-
unsigned long current_time = millis();
unsigned long last_vib = id(last_vibration_time);
if (last_vib == 0) {
return {"LL en marche"};
}
unsigned long elapsed_seconds = (current_time - last_vib) / 1000;
unsigned long target_seconds = 120; // 2 minutes
if (elapsed_seconds >= target_seconds) {
return {"Alerte!"};
} else {
unsigned long remaining_seconds = target_seconds - elapsed_seconds;
unsigned long minutes = remaining_seconds / 60;
unsigned long seconds = remaining_seconds % 60;
char buffer[10];
sprintf(buffer, "%02lu:%02lu", minutes, seconds);
return {buffer};
}
- platform: template
name: "Timer2 lancement du deepsleep"
id: sleep_countdown
update_interval: 1s
lambda: |-
if (!id(ready_to_sleep)) {
return {"-"};
}
unsigned long current_time = millis();
unsigned long sleep_start = id(sleep_timer_start);
unsigned long sleep_elapsed = (current_time - sleep_start) / 1000;
if (sleep_elapsed >= 60) {
return {"Sleep!"};
} else {
unsigned long remaining = 60 - sleep_elapsed;
char buffer[10];
sprintf(buffer, "00:%02lu", remaining);
return {buffer};
}
binary_sensor:
- platform: gpio
pin:
number: 4
mode: INPUT_PULLUP
name: "Hublot Machine"
device_class: door
id: hublot_sensor
- platform: gpio
pin:
number: 32
mode: INPUT_PULLUP
inverted: false
name: "Vibration Machine"
device_class: vibration
id: vibration_sensor
on_press:
- logger.log: "Machine en marche - Reset timers"
- globals.set:
id: last_vibration_time
value: '0'
- globals.set:
id: ready_to_sleep
value: 'false'
- globals.set:
id: sleep_timer_start
value: '0'
- component.update: countdown_display
- component.update: sleep_countdown
on_release:
- logger.log: "Machine arrêtée - Démarrage timer 1"
- globals.set:
id: last_vibration_time
value: !lambda 'return millis();'
- component.update: countdown_display
- platform: template
name: "Machine Terminée"
id: machine_terminee
lambda: |-
if (!id(ready_to_sleep)) {
return false;
}
unsigned long elapsed = (millis() - id(sleep_timer_start)) / 1000;
return elapsed >= 60;
globals:
- id: last_vibration_time
type: unsigned long
initial_value: '0'
- id: ready_to_sleep
type: bool
initial_value: 'false'
- id: sleep_timer_start
type: unsigned long
initial_value: '0'
- id: buzzer_blinking
type: bool
initial_value: 'false'
- id: buzzer_start_time
type: unsigned long
initial_value: '0'
interval:
# Logique des timers et buzzer uniquement
- interval: 2s
then:
- lambda: |-
unsigned long current_time = millis();
unsigned long last_vib = id(last_vibration_time);
if (last_vib == 0) {
id(last_vibration_time) = current_time;
return;
}
unsigned long elapsed_seconds = (current_time - last_vib) / 1000;
// Timer 1: 2 minutes sans vibration → buzzer
if (elapsed_seconds >= 120 && !id(ready_to_sleep)) {
ESP_LOGW("alert", "2 minutes sans vibration - Activation buzzer");
id(buzzer_blinking) = true;
id(buzzer_start_time) = current_time;
id(ready_to_sleep) = true;
id(sleep_timer_start) = current_time;
}
// Pas de deep sleep automatique - géré par HA
# Clignotement du buzzer
- interval: 250ms
then:
- lambda: |-
if (id(buzzer_blinking)) {
unsigned long now = millis();
if (now - id(buzzer_start_time) >= 5000) {
id(buzzer_output).turn_off();
id(buzzer_blinking) = false;
} else {
if ((now / 250) % 2 == 0) {
id(buzzer_output).turn_on();
} else {
id(buzzer_output).turn_off();
}
}
}
switch:
- platform: template
name: "Deep Sleep"
id: deep_sleep_switch
turn_on_action:
- logger.log: "ESP en deep sleep (porte ignorée)"
- lambda: |-
// Configurer le réveil uniquement sur vibrations
esp_sleep_enable_ext0_wakeup(GPIO_NUM_32, 1); // HIGH = vibration détectée
ESP_LOGI("sleep", "Activation Deep Sleep avec réveil sur vibration...");
esp_deep_sleep_start();
- switch.turn_off: deep_sleep_switch
Le code de l’automation, soit porte ouverte soit machine terminée déclenchent le sleep
alias: ESP - Deep Sleep après fin de machine ou ouverture porte
description: Met l'ESP en sommeil quand la machine est terminée OU la porte est ouverte
triggers:
- entity_id: binary_sensor.esp32_bluetooth_proxy_24ae54_machine_terminee
to: "on"
trigger: state
- entity_id: binary_sensor.esp_test_hublot_machine
to: "on"
trigger: state
actions:
- target:
entity_id: switch.esp32_bluetooth_proxy_24ae54_deep_sleep
action: switch.turn_on
mode: single
quelques logs et gifs en rafale



J’ai tout laissé dedans pour débug facilement éventuellement mais ça fonctionne pour moi comme je l’ai pensé.
A quoi ça ressemble assemblé?
Pensez à bien éloigner le buzzer du boitier principal, à la base il était dans le boitier principal, mais générait trop de vibrations et de bugs de réveil, j’ai dû le déporter.
Et avec l’article que nous avons partagé @Gael et moi
soyez notifié quelque soit la pièce ou vous vous trouvez si vous avez mis en place les notifications dynamiques Notifications dynamiques en fonction de la pièce occupée toutes mes notifcations passent par le diffuseur contextuel
Retrouvez tout ce qui manque sur le github du projet
et n’hésitez pas à partager vos créations ![]()
cdt

