Esp-deep_sleep avec sgp30

Bonjour,
je souhaite mettre en place un mode sommeil sur mon projet. Cependant j'ai un problème avec mon capteur sgp30 qui ne veut m'afficher que ses valeurs par defaut.
Actuellement , j'aimerais :
-réveil
-prendre les valeurs
-sommeil
C'est un capteur de gaz ( co2 , voc )
En regardant la datasheet : Sensirion_Gas_Sensors_SGP30_Datasheet_EN-1148053.pdf (mouser.com)

For the first 15s after the “Init_air_quality” 
command the sensor is in an initialization phase during which a “Measure_air_quality” command returns fixed values of 
400 ppm CO2eq and 0 ppb TVOC.

Même en respectant les "delay" à chaque redémarrage il reprend ces valeurs initials .
En light_sleep, il fonctionne bien .


#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 <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
unsigned long delayTime;

#include <Wire.h>
#include "Adafruit_SGP30.h"

Adafruit_SGP30 sgp;

/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
    // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
    const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
    const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
    return absoluteHumidityScaled;
}

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

   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
  
  while (!Serial) { delay(10); } // Wait for serial console to open!

  Serial.println("SGP30 test");

  if (! sgp.begin()){
    Serial.println("Sensor not found :(");
    while (1);
  }
  Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);

  // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
 //sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!
    while(!Serial);    // time to get serial running
    Serial.println(F("BME280 test"));

    unsigned status;
    
    // default settings
    status = bme.begin();  
    // You can also pass in a Wire library object like &Wire2
    // status = bme.begin(0x76, &Wire2)
    if (!status) {
        Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
        Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16);
        Serial.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
        Serial.print("   ID of 0x56-0x58 represents a BMP 280,\n");
        Serial.print("        ID of 0x60 represents a BME 280.\n");
        Serial.print("        ID of 0x61 represents a BME 680.\n");
        while (1) delay(10);
    }
    
    Serial.println("-- Default Test --");
    delayTime = 1000;

    Serial.println();
}

int counter = 0;
void loop() {
  float temperature = bme.readTemperature(); // [°C]
  float humidity = bme.readHumidity(); // [%RH]
  sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
  }
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

  if (! sgp.IAQmeasureRaw()) {
    Serial.println("Raw Measurement failed");
    return;
  }
  Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
  Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");
 
  delay(1000);

  counter++;
  if (counter == 30) {
    counter = 0;

    uint16_t TVOC_base, eCO2_base;
    if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
      Serial.println("Failed to get baseline readings");
      return;
    }
    Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
    Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
  }

    printValues();
    delay(delayTime);

     Serial.println("dodo");
  Serial.flush(); 
  esp_deep_sleep_start();

}

void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" °C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

Il faut un peu se mettre au niveau des lecteurs.
C'est compliqué de décrire le capteur, de dire ce qu'il capte et de mettre un lien vers la datasheet ?
Franchement avec aussi peu de renseignement je n'ai pas envie de faire l'effort d'utiliser un moteur de recherche pour voir de quoi il retourne.

Et fournir des liens vers le matériel est demandé dans le message épinglé en tête de forum
Avec les bons renseignements un certain nombre de lecteurs peuvent aider.

Question :
As-tu fait les exemples simples de la bibliothèque pour t'assurer que le montage est correct et que le capteur fonctionne correctement ?

oui mes branchements sont bon, il fonctionne correctement sans le deep_sleep,
Comme je l'ai dit au dessus c'est des que j'ajoute ma commande deep_sleep que me programme ne fonctionne plus, j'ai essayé avec plusieurs delay, etc mais rien ne change des que je met deep_sleep, j'obtient les valeurs de base ( 400 co2 et 0 VOC)
j'ai actualisé avec le lien de la datasheet

que dit le moniteur série ? la loop est vide je suppose?

image
Je pense que mon capteur n'a pas le temps de s'initialiser donc il m'affiche les valeurs défauts.
Sauf que même si je laisse 1 minutes de delay avant la prise de mesure, il me donne les valeurs par défauts.

postez le code avec la minute de délai

#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 <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
unsigned long delayTime;

#include <Wire.h>
#include "Adafruit_SGP30.h"

Adafruit_SGP30 sgp;

/* return absolute humidity [mg/m^3] with approximation formula
* @param temperature [°C]
* @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
    // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
    const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
    const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
    return absoluteHumidityScaled;
}

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

   esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
  
  while (!Serial) { delay(10); } // Wait for serial console to open!

  Serial.println("SGP30 test");

  if (! sgp.begin()){
    Serial.println("Sensor not found :(");
    while (1);
  }
  Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);

  // If you have a baseline measurement from before you can assign it to start, to 'self-calibrate'
 //sgp.setIAQBaseline(0x8E68, 0x8F41);  // Will vary for each sensor!
    while(!Serial);    // time to get serial running
    Serial.println(F("BME280 test"));

    unsigned status;
    
    // default settings
    status = bme.begin();  
    // You can also pass in a Wire library object like &Wire2
    // status = bme.begin(0x76, &Wire2)
    if (!status) {
        Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
        Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16);
        Serial.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
        Serial.print("   ID of 0x56-0x58 represents a BMP 280,\n");
        Serial.print("        ID of 0x60 represents a BME 280.\n");
        Serial.print("        ID of 0x61 represents a BME 680.\n");
        while (1) delay(10);
    }
    
    Serial.println("-- Default Test --");
    delayTime = 1000;

    Serial.println();
}

int counter = 0;
void loop() {
  delay(30000);
   delay(30000);
  float temperature = bme.readTemperature(); // [°C]
  float humidity = bme.readHumidity(); // [%RH]
  sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
  if (! sgp.IAQmeasure()) {
    Serial.println("Measurement failed");
    return;
  }
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

  if (! sgp.IAQmeasureRaw()) {
    Serial.println("Raw Measurement failed");
    return;
  }
  Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
  Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");
 
  delay(1000);

  counter++;
  if (counter == 30) {
    counter = 0;

    uint16_t TVOC_base, eCO2_base;
    if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
      Serial.println("Failed to get baseline readings");
      return;
    }
    Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
    Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);
  }

    printValues();
    delay(delayTime);

     Serial.println("dodo");
  Serial.flush(); 
  esp_deep_sleep_start();


}

void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" °C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

c'est vraiment quand il y a "deep_sleep" car si je l'enlève, le capteur fonctionne très bien

essayez comme cela:

#include <Wire.h>
#include "Adafruit_SGP30.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

Adafruit_BME280 bme; // I2C
Adafruit_SGP30 sgp;

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

/* return absolute humidity [mg/m^3] with approximation formula
  @param temperature [°C]
  @param humidity [%RH]
*/
uint32_t getAbsoluteHumidity(float temperature, float humidity) {
  // approximation formula from Sensirion SGP30 Driver Integration chapter 3.15
  const float absoluteHumidity = 216.7f * ((humidity / 100.0f) * 6.112f * exp((17.62f * temperature) / (243.12f + temperature)) / (273.15f + temperature)); // [g/m^3]
  const uint32_t absoluteHumidityScaled = static_cast<uint32_t>(1000.0f * absoluteHumidity); // [mg/m^3]
  return absoluteHumidityScaled;
}

void printValues() {
  Serial.print("Temperature = ");
  Serial.print(bme.readTemperature());
  Serial.println(" °C");

  Serial.print("Pressure = ");
  Serial.print(bme.readPressure() / 100.0F);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.print("Humidity = ");
  Serial.print(bme.readHumidity());
  Serial.println(" %");

  Serial.println();
}

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);  // Wait for serial console to open!

  Serial.println("SGP30 test");

  if (! sgp.begin()) {
    Serial.println("Sensor not found; STOP");
    while (true) yield();
  }

  Serial.print("Found SGP30 serial #");
  Serial.print(sgp.serialnumber[0], HEX);
  Serial.print(sgp.serialnumber[1], HEX);
  Serial.println(sgp.serialnumber[2], HEX);


  Serial.println(F("BME280 test"));
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
    Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(), HEX);
    Serial.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
    Serial.print("   ID of 0x56-0x58 represents a BMP 280,\n");
    Serial.print("        ID of 0x60 represents a BME 280.\n");
    Serial.println("        ID of 0x61 represents a BME 680.\nSTOP");
    while (true) yield();
  }
  Serial.print("SensorID : 0x"); Serial.println(bme.sensorID(), HEX);


  Serial.println("-- Default Test --");

  float temperature = bme.readTemperature(); // [°C]
  float humidity = bme.readHumidity(); // [%RH]
  sgp.setHumidity(getAbsoluteHumidity(temperature, humidity));
  if (! sgp.IAQmeasure()) {
    Serial.println("Humidity Measurement failed; STOP");
    while (true) yield();
  }
  Serial.print("TVOC "); Serial.print(sgp.TVOC); Serial.print(" ppb\t");
  Serial.print("eCO2 "); Serial.print(sgp.eCO2); Serial.println(" ppm");

  if (! sgp.IAQmeasureRaw()) {
    Serial.println("Raw Measurement failed; STOP");
    while (true) yield();
  }
  Serial.print("Raw H2 "); Serial.print(sgp.rawH2); Serial.print(" \t");
  Serial.print("Raw Ethanol "); Serial.print(sgp.rawEthanol); Serial.println("");

  uint16_t TVOC_base, eCO2_base;
  if (! sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) {
    Serial.println("Failed to get baseline readings; STOP");
    while (true) yield();
  }
  Serial.print("****Baseline values: eCO2: 0x"); Serial.print(eCO2_base, HEX);
  Serial.print(" & TVOC: 0x"); Serial.println(TVOC_base, HEX);

  printValues();

  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("dodo");
  Serial.flush();
  delay(10);
  esp_deep_sleep_start();
}


void loop() {}

modifié ici sur la base de votre code, je ne sais pas si ça compile

l'idée est de voir ce qu'il se passe à chaque réveil. Sans loop

d'accord , j'obtient ceci
image

est-ce qu'il se réveille?

Non , j'ai toujours les valeurs par défauts, pour co2 et voc .
Pourtant mes valeurs de H2 et Ethanol varie

il ne se réveille pas ?

comment sont alimentés les capteurs ?

je n'ai pas mis de délai dans le code, donc la lecture se fait dès le réveil. Le point c'est de s'assurer déjà d'avoir un code qui fonctionne

Qu'entendez vous par réveiller ? Mon message (9) est une capture d'écran de ma console, j'ai ce message en boucle .
J'ai acheté un module sgp30 chez adafruit Overview | Adafruit SGP30 TVOC/eCO2 Gas Sensor | Adafruit Learning System
branché en i2c sur mon esp32 en 3.3v, le module dispose d'un convertisseur pour le 1.8v

OK donc il se réveille bien toutes les 5s.

Rajoutez un delay(60000UL); avant de faire les lectures juste au début du setup()

  Serial.begin(115200);
  while (!Serial) delay(10);  // Wait for serial console to open!
  Serial.println("Heating up delay");
  delay(60000UL);
  Serial.println("Heating up done");

J'ai toujours le même problème , je n'ai que les valeurs par défaut d'affiché.
Le problème viens peux être de la librairie ? #include "Adafruit_SGP30.h"
Adafruit SGP30 Arduino Library: Adafruit_SGP30 Class Reference

si vous faites tourner cet exemple, tout fonctionne ?

dans cet exemple ils font 30 tours de loop avant d'afficher quelque chose

j'ai des valeurs à partir de la 16 ème boucle
image
SI c'est par rapport au tour de loop , ça va être impossible avec un deep_sleep nn ?

on peut simplement mettre un while() et faire une boucle nous même, ce n'est pas un souci ou utiliser la loop et passer en sleep une fois qu'on est rentré dans le if (counter == 30)

Vous avez lu la doc ? notamment la partie sur la baseline

If no stored baseline is available after initializing the baseline algorithm, the sensor has to run for 12 hours until the baseline can be stored. This will ensure an optimal behavior for the next time it starts up. Reading out the baseline prior should be avoided unless a valid baseline is restored first. Once the baseline is properly initialized or restored, the current baseline value should be stored approximately once per hour. While the sensor is off, baseline values are valid for a maximum of seven days.

Restarting the sensor without reading back a previously stored baseline will result in the sensor trying to determine a new baseline. The adjustement algorithm will be accelerated for 12hrs which is the Maximum time required to find a new baseline.

The sensor adjusts to the best value it has been exposed to. So keeping it indoors the sensor thinks this is the best value and sets it to ~0ppb tVOC and 400ppm CO2eq. As soon as you expose the sensor to outside air it can adjust to the global H2 Background Signal. For normal Operation exposing the sensor to outside air for 10min cumulative time should be sufficient.

If you're experienced with sensors that don't have a baseline, you either won't be able to measure absolute values or you'll have to implement your own baseline algorithm.
The sensor to sensor variation of SGP30 in terms of sensitivity is very good as each of them is calibrated. But the baseline has to be determined for each sensor individually during the first Operation.

D'accord merci , mon programme essaie donc de recréer une ligne de base ?
Vous pensez que si je le laisse tourner 12h au rallumage j'aurais des valeurs dès le début ?
Car mon capteur à déjà fonctionné plus de 12h. Pouvez vous me faire un exemple de programme avec le while et le "counter==30" pour tester si ça fonctionne

Je vais vous laisser bosser :slight_smile:

lisez le tuto sur le mode opératoire

il disent bien :

The first 10-20 readings will always be TVOC 0 ppb eCO2 400 ppm. That's because the sensor is warming up, so it will have 'null' readings.

et à propos de la base line ils disent

To make that easy, SGP lets you query the 'baseline calibration readings' from the sensor with code like this:

uint16_t TVOC_base, eCO2_base; sgp.getIAQBaseline(&eCO2_base, &TVOC_base);

This will grab the two 16-bit sensor calibration words and place them in the variables so-named.

You should store these in EEPROM, FLASH or hard-coded. Then, next time you start up the sensor, you can pre-fill the calibration words with

sgp.setIAQBaseline(eCO2_baseline, TVOC_baseline);

donc il faudrait

  • laisser tourner le capteur un moment et lire la base line dans 12h environ
  • noter ces valeurs et les stocker en mémoire. utilisez la bibliothèque Preferences

ensuite vous écrivez votre code et au réveil vous allez lire la base line, vous la donnez au module en utilisant sgp.setIAQBaseline() et vous faites des lectures jusqu'à ce que vous obtenez autre chose que TVOC 0 ppb eCO2 400 ppm

une fois de temps en temps ils disent aussi de faire une mise à jour,

the baseline is properly initialized or restored, the current baseline value should be stored approximately once per hour

donc (toutes les heures) il faut aller lire la base line et mettre à jour les préférences