Esp32 : deep sleep et SPIFFS

destroyedlolo:
ben par rapport auEst-il vraiment obligatoire d'y stocker TOUTES les variables globales ?
Normalement, seul les variables de contextes ont ce besoin :slight_smile:

c’est quoi une “variable de contexte” selon vous?...

Bonsoir
Merci de toutes vos réponses. J'ai en effet sauvegardé mes 'variables de contexte', c'est à dire celles que je dois pouvoir utiliser après un réveil, dans la RAM RTC comme l'indique Al1 dans la réponse 22.

Ça, ça marche.
J'ai ensuite testé la mise en sommeil et le réveil par timer et par les touches tactiles de l'ESP32.

Ça, ça marche aussi.
Maintenant, je me bats avec le réveil par une interruption externe : un bouton d'abord. Ça marche. C'est dommage que ce soit incompatible du réveil par les touches tactiles, j'aurais bien aimé avoir les deux...

Reste à implémenter le réveil par la détection d'un mouvement avec un accéléromètre MPU6050... Et là, ça marche pas, je rame... Rien de probant sur le net. Si vous avez des pistes, je suis preneur.

Bonsoir lesept

Pas encore résolu la question du seuil de mouvement et de la durée de mouvement pour obtenir une interruption en sortie du MPU6050 :wink: ?

Je ne connais pas bien la puce, sa datasheet et la ou les librairies mais une idée vient :
l'interruption par 'détection du mouvement' est elle possible DMP désactivée ?

En effet, question pertinente. Je me suis posé la même, mais pas eu le temps de tester...

EDIT : ton lien est faux... Peux-tu vérifier ?

lien corrigé, c'était encore la malédiction du http://http://http//.....""""""

Au fait, dois-je ou puis-je mettre la pin qui reçoit l'interruption en pullup ou pulldown ?

la doc du mpu dit que la sortie INT peut être configurée en 'totem pole' ou 'open drain'
Un pull up ne peut pas faire de mal !
On voit sur le web des schémas avec un pull up externe.

Bonsoir
J'ai pas mal cherché, et j'ai finalement un code qui marche...

// Bus 2 : l'accéléro
#define SDA2 5
#define SCL2 4

#include <Wire.h>
#include "I2Cdev.h"
#include <MPU6050.h>

RTC_DATA_ATTR int bootCount = 0;
MPU6050 accelgyro;
/*
  Method to print the reason by which ESP32 has been awaken from sleep
*/
void print_wakeup_reason() {
  esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();
  switch (wakeup_reason)
  {
    case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case 3  : Serial.println("Wakeup caused by timer"); break;
    case 4  : Serial.println("Wakeup caused by touchpad"); break;
    case 5  : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
  }
}

bool InitAccelero () {
  Wire.begin(SDA2, SCL2);
  accelgyro.initialize();
  bool Success  = accelgyro.testConnection(); // verify connection
  if (Success) {
    Serial.println("MPU6050 connection successful");
  }
  else Serial.println("MPU6050 connection failed");
  return Success;
}

void setup() {
  Serial.begin(115200);
  bool AcceleroSuccess = InitAccelero ();

  // instructions from : https://lukelectro.wordpress.com/2016/08/11/how-to-enable-motion-detection-interrupt-on-mpu6050/
  accelgyro.resetGyroscopePath();
  accelgyro.resetAccelerometerPath();
  accelgyro.setInterruptDrive(0);
  accelgyro.setInterruptMode(1); // 0=active-high, 1=active-low
  accelgyro.setDHPFMode(MPU6050_DHPF_5);
  accelgyro.setMotionDetectionThreshold(2); // Threshold in 2mg (ajouté by me)
  accelgyro.setMotionDetectionDuration(100); //Duration in ms
  accelgyro.setAccelerometerPowerOnDelay(1); // Set accelerometer power-on delay
  accelgyro.setFreefallDetectionCounterDecrement(1); // Set Free Fall detection counter decrement
  accelgyro.setMotionDetectionCounterDecrement(1); // Set Motion detection counter decrement
  accelgyro.setIntMotionEnabled(true);

  delay(200); //Take some time to open up the Serial Monitor
  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
  delay(20);

  print_wakeup_reason(); //Print the wakeup reason for ESP32
  // Configure RTCIO as wakeup source
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0); //1 = High, 0 = Low

  //Go to sleep now
  Serial.println("Going to sleep now");
  delay(200);
  esp_deep_sleep_start();
}

void loop() { }

Les connexions :
VCC, GND, SDA sur pin 5, SCL sur pin 4 et INT sur 13.

Bravo !
Merci pour le retour

Merci mais ce n'est pas encore terminé.
J'ai donc les moyens de mettre mon système en sommeil profond et de le réveiller soit par le timer (toutes les minutes pour affichage de l'heure) soit avec un mouvement par l'accéléromètre.
Mais dans ce dernier cas j'ai alors besoin de savoir combien de temps s'est écoulé depuis la mise en sommeil pour régler le timer avant de remettre en sommeil.
Comment puis je connaître ce temps écoulé ?

tu veux savoir combien de temps à dormi un 'ESP32 , réveillé par une interruption.c'est ça ?.
..... pas de pb en ajoutant un circuit RTC !!

Sinon il faudrait, au reveil, pouvoir lire la valeur du compteur interne 'RTC' , celui qui est capable de réveiller l'ESP
Je ne sais pas si ce compteur est accessible en lecture depui le code exécuté au réveil. Il faut chercher.

(millis () étant remis à zéro au reveil on ne peut s'en servir pour ce que tu veux faire)

Je préférerais éviter la RTC, mon idée était bien de le le contenu de ce registre

En demandant l'heure qu'il est à la RTC avant de s'endormir et en le notant dans la mémoire de la RTC puis en comparant avec l'heure qu'il est au réveil ? (ça semble fixé maintenant)

Bonne nouvelle JML !! Merci pour le lien.
ça commence à mériter le terme de RTC ... si en plus on fait tourner ça avec un quartz de 32 kHZ
Reste à tester ça sous IDE Arduino

J'ai trouvé un exemple :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "sys/time.h"

#include "sdkconfig.h"

#include "esp_deep_sleep.h"

#define GPIO_DEEP_SLEEP_DURATION     10  // sleep 10 seconds and then wake up
RTC_DATA_ATTR static time_t last;        // remember last boot in RTC Memory

void app_main() {
	struct timeval now;

	printf("start ESP32\n");

	gettimeofday(&now, NULL);

	printf("deep sleep (%lds since last reset, %lds since last boot)\n",now.tv_sec,now.tv_sec-last);

	last = now.tv_sec;
	esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);

}

Le code se réveille toutes les 10 secondes et affiche le temps de sommeil, mais en secondes. Il reste juste à trouver le moyen d'obtenir des microsecondes...
Probable qu'on puisse utiliser

	last = now.tv_usec;

ou convertir les temps en microsecondes comme

now.tv_sec * 1000000 + now.tv_usec

Je teste ça dès que j'ai un moment...

Voila le résultat :

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5       /* Time ESP32 will go to sleep (in seconds) */

#include "sys/time.h"

RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR static time_t last;        // remember last boot in RTC Memory
RTC_DATA_ATTR static time_t lastus;        // remember last boot in RTC Memory


void setup() {
  Serial.begin(115200);

  struct timeval now;
  gettimeofday(&now, NULL);
  long temps = now.tv_sec * 1000000 + now.tv_usec - (last * 1000000 + lastus);
  Serial.println(temps);

  //Configure Timer as wakeup source
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

  delay(1); //delayMicroseconds(400);
  last = now.tv_sec;
  lastus = now.tv_usec;
  esp_deep_sleep_start();
}

void loop() { }

Pour un temps de sommeil demandé de 5 secondes, j'obtiens des réveils avec un temps mesuré autour de 5 secondes et 129 ms

rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
20144
ets Jun 8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
5129085
ets Jun 8 2016 00:22:57

rst:0x5 (DEEPSLEEP_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
5129022

Ces 129 ms supplémentaires semblent dépendre des instructions qui se trouvent entre les instructions liées au temps : gettimeofday et affectation des variables last et lastus

Par exemple si je mets
  esp_sleep_enable_timer_wakeup(5000000);il y a une multiplication en moins et je passe à 128,9 ms. Par contre si j'ajoute les instructions de configuration de mon accéléromètre, je passe à 528 ms...

Et déplacer le Serial.begin après le gettimeofday ne change rien !

Enfin, le delay(1) sert à attendre que le port série envoie la donnée (temps), si on optimise avec delayMicroseconds(400) on passe à 128,5 ms.

Ce temps additionnel est indépendant de la durée du temps de sommeil : si je mets 10 ou 30 secondes, les résultats sont similaires.

pas si mal !!

par acquis de conscience je mettrais

#define uS_TO_S_FACTOR 1000000ul  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5u       /* Time ESP32 will go to sleep (in seconds) */

histoire de forcer les types dans les calculs lors de la phase de précompilation

Mouais
J'ai prévu un réveil chaque minute. Si à chaque fois j'accumule 500 ms je vais vite prendre du retard... 12 minutes par jour, c'est dur.
Il va falloir caractériser finement pour recaler et éviter trop de dérive. Heureusement que je pensais remettre l'heure à jour pendant la nuit...

Une certaine (je ne sais pas l'estimer) incertitude sur les durées d'activité est inévitable avec l'ESP32 sous IDE Arduino+IDF Espressif en raison de RTOS. Ton code , le sept, est compilée en tâche(s) parmi d'autres.

Pourl'ESP8266 Espressif a fait é SDK : le 'nonos' , sans RTOS et l'autre avec RTOS.
l'IDE ARduino repose sur le premier
Pour l'ESP32 c'est RTOS pour tout le monde.

Pour le temps de sommeil il faut faire avec l'imprécision de l'oscillateur TC de la RTC