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

De Wiki de Mémoire Vive
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Aucun résumé des modifications
 
(2 versions intermédiaires par le même utilisateur non affichées)
Ligne 2 : Ligne 2 :


https://youtube.com/shorts/S9HAANlcVAg?si=NyX30GI7u0vbySkP
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.
ESPHome est très pratique pour des projets simples et rapidement connectés.
Ligne 17 : Ligne 19 :


== 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, OLED_RESET);
// Pins
#define HALL_SENSOR_PIN 25
#define LED_PIN 2
// Compteur
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
float cadence_rpm = 0;
void IRAM_ATTR onPedal() {
  unsigned long now = millis();
  // Éviter les rebonds ou doubles déclenchements
  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 ==
<pre>
<pre>
#include <Wire.h>
#include <Wire.h>
Ligne 143 : 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 156 : 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 185 : 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 236 : 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);