Optimiser la conso électrique du ESP32

De Wiki de Mémoire Vive
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.

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>

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

ESPHome

#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

RTC_DATA_ATTR int tour_count = 0;

const int cadence_window_ms = 3000;
unsigned long pedal_times[20];  // tableau circulaire
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;
}

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

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

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

    // Calcul de la cadence sur les 3 dernières secondes
    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();
  }

  // Si plus de 10s d'inactivité → deep sleep
  if (now - last_activity_time > 10000) {
    display.clearDisplay();
    display.display();
    display.ssd1306_command(SSD1306_DISPLAYOFF);

    esp_sleep_enable_ext0_wakeup(GPIO_NUM_25, 0);  // Réveil sur LOW (aimant)
    delay(100);
    esp_deep_sleep_start();
  }

  delay(50);
}