Go Down

Topic: Esp32 : deep sleep et SPIFFS  (Read 1 time) previous topic - next topic

al1fch

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.

lesept

#31
Nov 22, 2018, 11:34 pm Last Edit: Nov 22, 2018, 11:50 pm by lesept
Bonsoir
J'ai pas mal cherché, et j'ai finalement un code qui marche...

Code: [Select]
// 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.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

al1fch


lesept

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é ?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

al1fch

#34
Nov 23, 2018, 08:14 pm Last Edit: Nov 23, 2018, 08:15 pm by al1fch
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)

lesept

Je préférerais éviter la RTC, mon idée était bien de le le contenu de ce registre
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

J-M-L

#36
Nov 23, 2018, 08:18 pm Last Edit: Nov 23, 2018, 08:22 pm by J-M-L
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)
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

al1fch

#37
Nov 23, 2018, 08:30 pm Last Edit: Nov 23, 2018, 08:34 pm by al1fch
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

lesept

#38
Nov 23, 2018, 10:06 pm Last Edit: Nov 23, 2018, 10:46 pm by lesept
J'ai trouvé un exemple :

Code: [Select]
#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
Code: [Select]
last = now.tv_usec;
ou convertir les temps en microsecondes comme
Code: [Select]
now.tv_sec * 1000000 + now.tv_usec
Je teste ça dès que j'ai un moment...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

lesept

Voila le résultat :
Code: [Select]
#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

Quote
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
Code: [Select]
  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.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

J-M-L

pas si mal !!

par acquis de conscience je mettrais
Code: [Select]
#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
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

lesept

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...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

al1fch

#42
Nov 24, 2018, 01:35 pm Last Edit: Nov 24, 2018, 01:38 pm by al1fch
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


Go Up