arduino-i2c-sen5x icon indicating copy to clipboard operation
arduino-i2c-sen5x copied to clipboard

How to operate the VOC sensor and save power

Open oscgonfer opened this issue 4 months ago • 10 comments

We are using the SEN5X series and we would like to know how it should be operated if we want to have "interrupted" operation to save power. Ideally we want:

  1. Turn on measurement mode for 30s
  2. Get readings after 30s
  3. Stop measurement mode for 150s
  4. Go back to (1)

The question goes onto how we should interact with VOC state algorithm. The datasheet says:

Image

Does this mean that we could do:

  1. (If available, feed state of VOC state algorithm)
  2. Turn on measurement mode for 30s
  3. Get readings after 30s
  4. Get VOC state algorithm
  5. Stop measurement mode for 150s
  6. Go back to (1)

In this case, the VOC state is always [0, 0, 0, 0, 0, 0, 0, 0], so there is something wrong. Should it be done in a different way? For instance, not stopping measurement mode if we want to measure VOCs? In that case, how can we save battery?

oscgonfer avatar Aug 08 '25 09:08 oscgonfer

Hej @oscgonfer You are on the right track. The state you are reading is weird, how long is the algorithm running before reading ?

Cheers Q

quentin-cy avatar Aug 12 '25 10:08 quentin-cy

Hi @qfisch,

Thank you for the response. It's not running for much time (probably seconds?) before entering in that sequence from above forever. I left the device running in that mode for a while (hours) and the voc algorithm state is the same.

oscgonfer avatar Aug 12 '25 16:08 oscgonfer

Hej @oscgonfer

I will try to reproduce on my side this week and hopefully come back to you with a working code sample. Cheers Q

quentin-cy avatar Aug 13 '25 07:08 quentin-cy

Hej @oscgonfer

Can you try the following:

  1. Load the provided exampleUsage
  2. Replace the loop with the snipet below
  3. You should see the state changing once the algorithm starts initializing.
void loop() {
    uint16_t error;
    char errorMessage[256];

    delay(1000);

    // Read Measurement
    float massConcentrationPm1p0;
    float massConcentrationPm2p5;
    float massConcentrationPm4p0;
    float massConcentrationPm10p0;
    float ambientHumidity;
    float ambientTemperature;
    float vocIndex;
    float noxIndex;

    error = sen5x.readMeasuredValues(
        massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
        massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
        noxIndex);

    if (error) {
        Serial.print("Error trying to execute readMeasuredValues(): ");
        errorToString(error, errorMessage, 256);
        Serial.println(errorMessage);
    } else {
        Serial.print("VocIndex:");
        if (isnan(vocIndex)) {
            Serial.print("n/a");
        } else {
            Serial.print(vocIndex);
        }
    }

    uint8_t state[12];
    error = sen5x.getVocAlgorithmState(state, 12);
    if (error) {
        Serial.print("Error trying to execute getVocAlgorithmState(): ");
        errorToString(error, errorMessage, 256);
        Serial.println(errorMessage);
    }
    Serial.print("\t State: [");
    for( uint8_t i = 0; i < 12; i++ ){
        Serial.print(state[i]);
        Serial.print(" ");
    }
    Serial.println("]");
}

What I did is just remove some prints for quality, called getVocAlgorithmState, and printing the state on every iteration.

Can you confirm that with this code you do not get an empty array ?

quentin-cy avatar Aug 21 '25 09:08 quentin-cy

Hi @qfisch

Indeed, I tested the approach and I get the following (I added some decoration and only print the non-CRC parts of the buffer):

[0, 28, 177, 2, 21, 88, 0, 0]
... 
[0, 45, 98, 2, 112, 191, 0, 0]

This works when not stopping the sensor. But if I wanted to send 0x0104 (stop measurement, assuming that's the one the datasheet refers to) between reads to save battery, what should be the process?

oscgonfer avatar Aug 27 '25 09:08 oscgonfer

Good to hear that things seems in order @oscgonfer ,

What happened here is that you never gave time to the algorithm to correctly initialize, hence the 0 array you were reading. I would suggest the following procedure:

  1. On startup, the VOC algorithm is given time to stabilize in it's environment (I would suggest around an hour at least). Only after that point the low power routine could start.
  2. Read the state, and save it.
  3. Sleep
  4. Restore the algorithm state
  5. Make measurements
  6. Go back to step 2

Note that if the environment VOC is changing significantly, the algorithm would take a lot of time to adjust using this routine (the baseline would stick to the measurements taken during 1.)

I hope that helps you Cheers Q

quentin-cy avatar Aug 28 '25 08:08 quentin-cy

Hi @qfisch

Thanks for the comment. I have done as mentioned, run the algorithm for an hour without stopping and it works perfectly. However, as soon as I stop the measurement, even if I save the state and recover it before starting the new cycle, the VOC and NOx index values drop to flat 0.

Is there any particularity as to how to restore the algorithm state? For instance, delay after writing it, or something of the like?

Or, is the sleep command other than stopMeasurement()?

oscgonfer avatar Aug 29 '25 18:08 oscgonfer

Ok, I think I understand what's happening and it seems like the first responses are 0 after restoring thr voc state. After that, the values go back to similar values as the ones before stopping. Is it true? If so, how many readings are to be discarded?

UPDATE: @qfisch I am taking a different approach now, after reading low power application note. I am not really sure why, but stopping measurement completely doesn't make it, even if I leave an stabilization time. Approach is now to change to RHT/gas only mode after the first stabilization period as per below:

  1. On startup, the VOC algorithm is given time to stabilize in it's environment (I would suggest around an hour at least). Only after that point the low power routine could start.
  2. Read the state, and save it.
  3. Sleep (EDIT: RHT/Gas only mode)
  4. ~Restore the algorithm state~
  5. Make measurements
  6. Go back to step 2

Do you agree?

oscgonfer avatar Sep 12 '25 13:09 oscgonfer

Hej @oscgonfer

Sorry I had no time to get back to you. I think your last approach would work as well, it might just not bring the power consumption as low as with a complete MCU deep sleep though.

I would still like to look into a sleep example once I have a moment. In the meanwhile, feel free to reach out again if you encounter issues in implementing your approach.

Cheers Q

quentin-cy avatar Sep 16 '25 10:09 quentin-cy

Thanks @qfisch I am doing tests with this approach and will come back to you with results as well. The deep sleep mode is still returning 0s (so does the first reading)

oscgonfer avatar Sep 16 '25 11:09 oscgonfer