« Optimiser la conso électrique du ESP32 » : différence entre les versions

De Wiki de Mémoire Vive
Aller à la navigation Aller à la recherche
Page créée avec « 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. Voici 1) le code ESPHome et 2) le même code transposé en Arduino. == Arduino == <pre> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OL... »
 
Aucun résumé des modifications
 
(4 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
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.
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.


Voici 1) le code ESPHome et 2) le même code transposé en Arduino.
https://youtube.com/shorts/S9HAANlcVAg?si=NyX30GI7u0vbySkP


== Arduino ==
Avec le ESP32, on est à 40mA environ en fonctionnement, et on passe à 20mA avec un ESP32 C3.
<pre>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define SCREEN_WIDTH 128
ESPHome est très pratique pour des projets simples et rapidement connectés.
#define SCREEN_HEIGHT 64
Mais Arduino ouvre la voie à :
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// Pins
- une maîtrise totale du matériel
#define HALL_SENSOR_PIN 25
#define LED_PIN 2


// Compteur
- une consommation minimale
volatile int tour_count = 0;
unsigned long last_pedal_time = 0;
const int cadence_window_ms = 3000;
unsigned long pedal_times[20];  // Pour une fenêtre glissante
int pedal_index = 0;


// Cadence
- une interface UX personnalisée
float cadence_rpm = 0;


void IRAM_ATTR onPedal() {
et des fonctionnalités avancées (stockage, communication, veille contextuelle).
  unsigned long now = millis();


  // Éviter les rebonds ou doubles déclenchements
Voici 1) le code Arduino et 2) le code d'origine en ESPHome.
  if (now - last_pedal_time < 150) return;
  last_pedal_time = now;
 
  // Incrémenter le compteur
  tour_count++;
 
  // Ajouter timestamp
  pedal_times[pedal_index % 20] = now;
  pedal_index++;
 
  // LED blink
  digitalWrite(LED_PIN, HIGH);
}
 
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();
}
 
void loop() {
  static unsigned long last_update = 0;
  unsigned long now = millis();
 
  if (now - last_update > 1000) {
    last_update = now;
 
    // Nettoyer les timestamps vieux de plus de 3 sec
    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();
 
    // Éteindre LED après affichage
    digitalWrite(LED_PIN, LOW);
  }
}
 
</pre>
== ESPHome ==


== Arduino ==
<pre>
<pre>
#include <Wire.h>
#include <Wire.h>
Ligne 130 : Ligne 34 :
#define LED_PIN 2
#define LED_PIN 2


// Variable conservée même après deep sleep
RTC_DATA_ATTR int tour_count = 0;
RTC_DATA_ATTR int tour_count = 0;


const int cadence_window_ms = 3000;
const int cadence_window_ms = 3000;
unsigned long pedal_times[20]; // tableau circulaire
unsigned long pedal_times[20];
int pedal_index = 0;
int pedal_index = 0;


Ligne 143 : Ligne 48 :


void IRAM_ATTR onPedal() {
void IRAM_ATTR onPedal() {
   pedal_detected = true;
   pedal_detected = true; // Marque qu'une pédale a été détectée
}
}


Ligne 172 : Ligne 77 :
     tour_count++;
     tour_count++;


     // Stocker l'instant du pédalage
     // Enregistrer le moment du pédalage
     pedal_times[pedal_index % 20] = now;
     pedal_times[pedal_index % 20] = now;
     pedal_index++;
     pedal_index++;


     // LED blink
     // Blink LED
     digitalWrite(LED_PIN, HIGH);
     digitalWrite(LED_PIN, HIGH);
     delay(100);
     delay(100);
     digitalWrite(LED_PIN, LOW);
     digitalWrite(LED_PIN, LOW);


     // Calcul de la cadence sur les 3 dernières secondes
     // Calcul cadence (nombre de tours sur 3s)
     int count = 0;
     int count = 0;
     unsigned long first = 0, last = 0;
     unsigned long first = 0, last = 0;
Ligne 223 : Ligne 128 :
   }
   }


   // Si plus de 10s d'inactivité → deep sleep
   // Mise en sommeil profond après 10s d'inactivité
   if (now - last_activity_time > 10000) {
   if (now - last_activity_time > 10000) {
     display.clearDisplay();
     display.clearDisplay();
     display.display();
     display.display();
     display.ssd1306_command(SSD1306_DISPLAYOFF);
     display.ssd1306_command(SSD1306_DISPLAYOFF); // Éteint l'écran proprement


     esp_sleep_enable_ext0_wakeup(GPIO_NUM_25, 0);  // Réveil sur LOW (aimant)
     esp_sleep_enable_ext1_wakeup(1ULL << GPIO_NUM_25, ESP_EXT1_WAKEUP_ALL_LOW);  // Réveil par aimant (LOW)
     delay(100);
     delay(100); // Laisse le temps au périphérique de s’éteindre proprement
     esp_deep_sleep_start();
     esp_deep_sleep_start(); // Entrée en sommeil profond
   }
   }


   delay(50);
   delay(50); // Pause légère pour alléger la boucle
}
}


</pre>
== ESPHome ==
<pre>
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);
</pre>
</pre>

Dernière version du 6 août 2025 à 11:29

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