Optimiser la conso électrique du ESP32
Les possibilités sont limitées en ESPHome mais très supérieures avec du code Arduino. Ce qui prend tout son sens lorsqu'on est avec une alimentation sur batterie.
https://youtube.com/shorts/S9HAANlcVAg?si=NyX30GI7u0vbySkP
ESPHome est très pratique pour des projets simples et rapidement connectés. Mais Arduino ouvre la voie à :
- une maîtrise totale du matériel
- une consommation minimale
- une interface UX personnalisée
et des fonctionnalités avancées (stockage, communication, veille contextuelle).
Voici 1) le code Arduino et 2) le code d'origine en ESPHome.
Arduino
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <esp_sleep.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Pins
#define HALL_SENSOR_PIN 25
#define LED_PIN 2
// Variable conservée même après deep sleep
RTC_DATA_ATTR int tour_count = 0;
const int cadence_window_ms = 3000;
unsigned long pedal_times[20];
int pedal_index = 0;
unsigned long last_pedal_time = 0;
unsigned long last_activity_time = 0;
bool pedal_detected = false;
float cadence_rpm = 0;
void IRAM_ATTR onPedal() {
pedal_detected = true; // Marque qu'une pédale a été détectée
}
void setup() {
pinMode(HALL_SENSOR_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
attachInterrupt(digitalPinToInterrupt(HALL_SENSOR_PIN), onPedal, FALLING);
Serial.begin(115200);
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
last_pedal_time = millis();
last_activity_time = millis();
}
void loop() {
unsigned long now = millis();
if (pedal_detected) {
pedal_detected = false;
last_pedal_time = now;
last_activity_time = now;
tour_count++;
// Enregistrer le moment du pédalage
pedal_times[pedal_index % 20] = now;
pedal_index++;
// Blink LED
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(LED_PIN, LOW);
// Calcul cadence (nombre de tours sur 3s)
int count = 0;
unsigned long first = 0, last = 0;
for (int i = 0; i < 20; i++) {
unsigned long t = pedal_times[i];
if (now - t < cadence_window_ms) {
if (count == 0) first = t;
last = t;
count++;
}
}
if (count >= 2) {
float elapsed_min = (last - first) / 60000.0;
cadence_rpm = (count - 1) / elapsed_min;
} else {
cadence_rpm = 0;
}
// Affichage OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Cadence:");
display.setTextSize(2);
display.setCursor(0, 10);
display.print(cadence_rpm, 0);
display.print(" tpm");
display.setTextSize(1);
display.setCursor(0, 40);
display.print("Tours:");
display.setTextSize(2);
display.setCursor(0, 50);
display.print(tour_count);
display.display();
}
// Mise en sommeil profond après 10s d'inactivité
if (now - last_activity_time > 10000) {
display.clearDisplay();
display.display();
display.ssd1306_command(SSD1306_DISPLAYOFF); // Éteint l'écran proprement
esp_sleep_enable_ext1_wakeup(1ULL << GPIO_NUM_25, ESP_EXT1_WAKEUP_ALL_LOW); // Réveil par aimant (LOW)
delay(100); // Laisse le temps au périphérique de s’éteindre proprement
esp_deep_sleep_start(); // Entrée en sommeil profond
}
delay(50); // Pause légère pour alléger la boucle
}
ESPHome
esphome:
name: esp32-velo-aff
friendly_name: ESP32-VELO-aff
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
i2c:
sda: GPIO21
scl: GPIO22
scan: true
id: bus_i2c
font:
- file: "arial.ttf"
id: font_large
size: 20
- file: "arial.ttf"
id: font_small
size: 10
output:
- platform: gpio
id: led_integree
pin:
number: GPIO2
sensor:
- platform: template
name: "Compteur Pédalage"
id: compteur_pedalage
unit_of_measurement: "tr"
accuracy_decimals: 0
update_interval: never
- platform: template
name: "Cadence Pédalage"
id: cadence_pedalage
unit_of_measurement: "tpm"
accuracy_decimals: 0
update_interval: 5s
lambda: |-
return id(cadence_rpm);
globals:
- id: compteur_pedalage_val
type: int
restore_value: no
initial_value: '0'
- id: pedal_times
type: std::vector<unsigned long>
restore_value: no
- id: cadence_rpm
type: float
restore_value: no
initial_value: '0'
binary_sensor:
- platform: gpio
name: "Capteur Effet Hall"
id: capteur_effet_hall
pin:
number: 25
mode: INPUT_PULLUP
device_class: motion
filters:
- delayed_on: 1ms
- delayed_off: 1ms
on_press:
then:
- lambda: |-
// Incrément du compteur total
id(compteur_pedalage_val) += 1;
id(compteur_pedalage).publish_state(id(compteur_pedalage_val));
// Gestion du calcul de cadence
unsigned long now = millis();
// Nettoyer les entrées trop anciennes (> 3s)
while (!id(pedal_times).empty() && (now - id(pedal_times).front() > 3000)) {
id(pedal_times).erase(id(pedal_times).begin());
}
// Ajouter le timestamp actuel
id(pedal_times).push_back(now);
// Calcul de la cadence moyenne sur les 3 dernières secondes
int count = id(pedal_times).size();
if (count >= 2) {
float elapsed_ms = id(pedal_times).back() - id(pedal_times).front();
float elapsed_min = elapsed_ms / 60000.0;
id(cadence_rpm) = (count - 1) / elapsed_min;
} else {
id(cadence_rpm) = 0;
}
- output.turn_on: led_integree
- delay: 200ms
- output.turn_off: led_integree
display:
- platform: ssd1306_i2c
model: "SSD1306_128X64"
address: 0x3C
lambda: |-
char buffer[32];
snprintf(buffer, sizeof(buffer), "Cadence:");
it.print(0, 0, id(font_small), buffer);
snprintf(buffer, sizeof(buffer), "%.0f tpm", id(cadence_pedalage).state);
it.print(0, 12, id(font_large), buffer);
snprintf(buffer, sizeof(buffer), "Tours:");
it.print(0, 34, id(font_small), buffer);
snprintf(buffer, sizeof(buffer), "%.0f", id(compteur_pedalage).state);
it.print(0, 46, id(font_large), buffer);