Optimiser la conso électrique du ESP32

De Wiki de Mémoire Vive
Version datée du 6 août 2025 à 11:29 par Denis (discussion | contributions)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

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

Avec le ESP32, on est à 40mA environ en fonctionnement, et on passe à 20mA avec un ESP32 C3.

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);