Wake from low Power (Sleep/Standby) using external interrupts from the CCS 881 Sensor

Hello, Arduino Forum.

I attempt for 3 days now to set an Nano 33 IoT aswell as an Seeeduino XIAO to Sleep/Standby until the external interrupt from the CCS 881 CO2-Gas Sensor is waking him up, and having lots of trouble with it.

As far as I know both the Seeeduino XIAO and the Nano 33 IoT have the same CPU, the SAMD21G18.
So most libraries should work on both chips (exept ArduinoBLE and NinaWifi, well because the Seeeduino XIAO has no Wifi or BLE).

But already getting the Microcontroller to periodically wake up deemed very challenging. The ArduinoLowPower (sorry that I can provide the link, I'm restricted to two links) library didn't work the chip stayed sleep indefinitely using the examples provided. For the Seeeduino XIAO not even the by Seeedstudio provided pre-compiled "EnergySaving.h" library did work, which is kinda surprising, because its a library specifically designed for just this Microcontroller.
In the End Low-Power did work using the example with the small change in line 28 by making the pin INPUT_PULLUP for the interrupt, made the chip waking up

pinMode(pin, INPUT_PULLUP);
attachInterrupt(pin, blink, LOW);

Than by shorting the pin to GND, the chip woke up.

For the CCS 881 I use adafruit Adafruit_CCS811 library and did work to read samples when ever the inerrupt was triggered.

For the CCS 881 CO2 Sensor I got it working, that the CO2 Sensor send an interrupt to the Micro-controller as soon as there as a new reading ready, but the Micro-controller did not went to sleep, it just looped over and over again.

It was kinda buggy, it took over 3 minutes for the first interrupt to be triggered, despite configuring the Sensor to create a new reading every minute. So it never worked properly.

Now I attempted to merge both programs.

(I hope Markdown Code works)

// **** INCLUDES *****
#include "LowPower.h"
#include <Adafruit_CCS811.h>

// External interrupt on pin 0 (use pin 0 to 24, except pin 4 on Arduino Zero)
const int pin = 13;
unsigned char count = 10;
volatile unsigned short eco2 = 0;
volatile unsigned short tvoc = 0;
volatile boolean interruptTriggered = false;

Adafruit_CCS811 ccs;

void setup()
{
	// Wait for serial USB port to open
	while(!SerialUSB);
  
  if(!ccs.begin()){
    SerialUSB.println("Failed to start CCS sensor! Please check your wiring.");
  }
  else {
    SerialUSB.println("CCS-Sucessful");
  }

  ccs.setDriveMode(CCS811_DRIVE_MODE_10SEC);
  delay(100);
  ccs.enableInterrupt();
	SerialUSB.println("***** ATSAMD21 Standby Mode Example *****");
	
	// ***** IMPORTANT *****
	// Delay is required to allow the USB interface to be active during
	// sketch upload process
	SerialUSB.println("Entering standby mode in:");
	for (count; count > 0; count--)
	{
	  SerialUSB.print(count);	
	  SerialUSB.println(" s");
	  delay(1000);
  }
  // *********************
 // in case data is already available clear it. (Race Condition)
  if(ccs.available()){
    // Clear already stored data so the interrupt pin is high again
    if(ccs.readData()){
      eco2 = ccs.geteCO2();
      tvoc = ccs.getTVOC();
    }
    
  SerialUSB.println("attachedInterrupt & check Status");
  // External interrupt on pin (example: press of an active low button)
  pinMode(pin, INPUT_PULLUP);
  SerialUSB.println(ccs.checkError());
  attachInterrupt(digitalPinToInterrupt(pin), isr, LOW);

  }
}

void loop() 
{
    SerialUSB.println(ccs.checkError() ? "Error" : "No Error");
    SerialUSB.println("Entering standby mode.");
    SerialUSB.println("Apply low signal to wake the processor.");
    SerialUSB.println("Zzzz...");
    // Detach USB interface
    //USBDevice.detach();
    // Enter standby mode
    LowPower.standby();  
    // Attach USB interface
    //USBDevice.attach();
    // Wait for serial USB port to open
    while(!SerialUSB);
    // Serial USB is blazing fast, you might miss the messages
    delay(1000);
    SerialUSB.println("Awake!");
  
    if (interruptTriggered){
        interruptTriggered = false;
        SerialUSB.print(" ,eCO2: ");
        SerialUSB.print(eco2);
        SerialUSB.print(" ,TVOC: ");
        SerialUSB.println(tvoc); 
    }
}

void isr(void)
{
  interruptTriggered = true;
  SerialUSB.print("Flipped interrupt bit"); 
  //Yes you shouldn't call Serial.print() in an ISR but SerialUSB is so fast, that it doesn't really matter
  SerialUSB.println(interruptTriggered ? "High" : "Low");
  if(ccs.available()){
      // Technically the css.available() shouldn't be neccesary, because when the interrupt is 
      // triggered we know that new sample is available, but it doesn't hurt to still check it.
      if(!ccs.readData()){
        //Getting CCS Data
        eco2 = ccs.geteCO2();
        tvoc = ccs.getTVOC();
    }
  }
}

The Status register of the Chip is fine, I get no error, so I did configure it correctly.
The CCS 881 Sensor is according to the datasheet in Page 17 "The nINT signal is asserted (driven low) when a new sample is ready".

So It should be correct that I trigger the ISR, when the signal is low.

Now I'm stuck I can't find the problem, that the chip doesn't register the interrupt.
Because I use Pin 13 I can see it on the LED_BUILDIN if the nINT signal is HIGH or LOW.
I played around a lot with the code. Even when I short Pin 13 to GND no interrupt is triggered.

I no long know what I can change in the code.

If it isnt't clear What I want to archive.
I want the CPU to go into Sleep/Standby automatically after the setup and only wake it up when a new sample is ready, read the sample from the chip print it to the terminal (later send it via BLE to an MQTT server) and go back to sleep until the next interrupt is triggered.

Kind regards for any help in advance.
Pascal.

PS: Responses can be in English or German I speak both.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.