Infineon Team
Published © MIT

Eval PASCO2 Miniboard

Learn how you could measure CO2 concentration with this super advance yet tiny CO2 sensor!

BeginnerProtip2 hours307
Eval PASCO2 Miniboard

Things used in this project

Story

Read more

Schematics

PAS CO2 Miniboard PNG

PNG file of Infineons XENSIV PASCO2 Miniboard

PAS CO2 Miniboard Fritzing file

Fritzing file of Infineons XENSIV PASCO2 Miniboard

Code

Continuous mode Example

C/C++
This example code initializes the sensor, sets the measurement interval, and retrieves the CO2 concentration periodically, displaying it on the serial monitor.
#include <Arduino.h>
#include <pas-co2-ino.hpp>

/* 
 * The sensor supports 100KHz and 400KHz. 
 * You hardware setup and pull-ups value will
 * also influence the i2c operation. You can 
 * change this value to 100000 in case of 
 * communication issues.
 */
#define I2C_FREQ_HZ  400000                     
#define PERIODIC_MEAS_INTERVAL_IN_SECONDS  10 
#define PRESSURE_REFERENCE  900

/*
 * Create CO2 object. Unless otherwise specified,
 * using the Wire interface
 */
PASCO2Ino cotwo;

int16_t co2ppm;
Error_t err;

void setup()
{
    Serial.begin(9600);
    delay(800);
    Serial.println("serial initialized");

    /* Initialize the i2c interface used by the sensor */
    Wire.begin();
    Wire.setClock(I2C_FREQ_HZ);

    /* Initialize the sensor */
    err = cotwo.begin();
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("initialization error: ");
      Serial.println(err);
    }

    /* We can set the reference pressure before starting 
     * the measure 
     */
    err = cotwo.setPressRef(PRESSURE_REFERENCE);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("pressure reference error: ");
      Serial.println(err);
    }

    /*
     * Configure the sensor to measureme periodically 
     * every 10 seconds
     */
    err = cotwo.startMeasure(PERIODIC_MEAS_INTERVAL_IN_SECONDS);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("start measure error: ");
      Serial.println(err);
    }

    delay(1000);
}

void loop()
{
    /* Wait for the value to be ready. */
    delay(PERIODIC_MEAS_INTERVAL_IN_SECONDS*1000);

    err = cotwo.getCO2(co2ppm);
    if(XENSIV_PASCO2_OK != err)
    {
      /* Retry in case of timing synch mismatch */
      if(XENSIV_PASCO2_ERR_COMM == err)
      {
        delay(600);
        err = cotwo.getCO2(co2ppm);
        if(XENSIV_PASCO2_OK != err)          
        {
          Serial.print("get co2 error: ");
          Serial.println(err);
        }
      }
    }

    Serial.print("co2 ppm value : ");
    Serial.println(co2ppm);

    /*
     * Assuming we have some mechanism to obtain a
     * pressure reference (i.e. a pressure sensor),
     * we could compensate again by setting the new reference. 
     * Here we just keep the initial value.
     */
    err = cotwo.setPressRef(PRESSURE_REFERENCE);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("pressure reference error: ");
      Serial.println(err);
    }
}

Alarm mode

C/C++
Readout of the sensor CO2 concentration based on threshold crossing and synched via hardware interrupt
#include <Arduino.h>
#include <pas-co2-ino.hpp>

/* 
 * The sensor supports 100KHz and 400KHz. 
 * You hardware setup and pull-ups value will
 * also influence the i2c operation. You can 
 * change this value to 100000 in case of 
 * communication issues.
 */
#define I2C_FREQ_HZ     400000  
#define PERIODIC_MEAS_INTERVAL_IN_SECONDS  10 
#define ALARM_PPM_THRESHOLD  1200

uint8_t interrupt_pin = 9;      /* For XMC2Go. Change it for your hardware setup */

/*
 * The constructor takes the Wire instance as i2c interface,
 * and the controller interrupt pin
 */
PASCO2Ino cotwo(&Wire, interrupt_pin);

int16_t co2ppm;
Error_t err;

/* 
 * A simple interrupt service routine. This callback will be 
 * executed every time that the sensor alarm is triggered,
 * and set the flag to true. In the main loop we use that
 * flag to synchronize the co2 read out when a new value is
 * available.
 */
volatile bool intFlag = false;
void isr (void * )
{
  intFlag = true;
}

void setup()
{
    Serial.begin(9600);
    delay(500);
    Serial.println("serial initialized");

    /* Initialize the i2c serial interface used by the sensor */
    Wire.begin();
    Wire.setClock(I2C_FREQ_HZ);

    /*
    * No need to initialized the interrupt pin. This is done 
    * in the sensor begin() function 
    */
    err = cotwo.begin();
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("initialization error: ");
      Serial.println(err);
    }

    /*
    * Periodic measurement every 10 seconds.
    * Interrupt alarm when the CO2 value 
    * goes over 1200 ppm. The isr function is 
    * passed enabling the sensor interrupt mode.
    */
    err = cotwo.startMeasure(PERIODIC_MEAS_INTERVAL_IN_SECONDS, ALARM_PPM_THRESHOLD, isr);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("start measure error: ");
      Serial.println(err);
    }
}

void loop()
{
    /* Interrupt alarm requires a CO2 concentration above the threshold */
    Serial.println("USER ACTION REQUIRED --> increase co2 to 1200 PPM to trigger the alarm!!");
    while(false == intFlag) { };

    /* Clear the interrupt flag */
    Serial.println("int occurred");
    intFlag = false;

    err = cotwo.getCO2(co2ppm);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("get co2 error: ");
      Serial.println(err);
    }

    Serial.print("co2 ppm value : ");
    Serial.println(co2ppm);
}

single-shot-mode

C/C++
Readout of the sensor CO2 concentration value using single shot measurement mode
#include <Arduino.h>
#include <pas-co2-ino.hpp>

/* 
 * The sensor supports 100KHz and 400KHz. 
 * You hardware setup and pull-ups value will
 * also influence the i2c operation. You can 
 * change this value to 100000 in case of 
 * communication issues.
 */
#define I2C_FREQ_HZ 400000  

/**
 * Create CO2 object. Unless otherwise specified,
 * using the Wire interface
 */
PASCO2Ino cotwo;

int16_t co2ppm;
Error_t err;

void setup()
{
  Serial.begin(9600);
  delay(500);
  Serial.println("serial initialized");

  /* Initialize the i2c interface used by the sensor */
  Wire.begin();
  Wire.setClock(I2C_FREQ_HZ);

  /* Initialize the sensor */
  err = cotwo.begin();
  if(XENSIV_PASCO2_OK != err)
  {
    Serial.print("initialization error: ");
    Serial.println(err);
  }

}

void loop()
{

  /* 
   * Trigger a one shot measurement
   */
  err = cotwo.startMeasure();
  if(XENSIV_PASCO2_OK != err)
  {
    Serial.print("error: ");
    Serial.println(err);
  }

  /* Wait for the value to be ready. */
  delay(5000);

  /**
   *  getCO2() is called until the value is 
   *  available.  
   *  getCO2() returns 0 when no measurement 
   *  result is yet available or an error has
   *  occurred.
   */

  do
  {
    err = cotwo.getCO2(co2ppm);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("error: ");
      Serial.println(err);
      break;
    }
  } while (0 == co2ppm);

  Serial.print("co2 ppm value : ");
  Serial.println(co2ppm);
}

forced-compensation

C/C++
Set CO2 reference offset using forced compensation
#include <Arduino.h>
#include <pas-co2-ino.hpp>

/* 
 * The sensor supports 100KHz and 400KHz. 
 * You hardware setup and pull-ups value will
 * also influence the i2c operation. You can 
 * change this value to 100000 in case of 
 * communication issues.
 */
#define I2C_FREQ_HZ 400000
#define PERIODIC_MEAS_INTERVAL_IN_SECONDS  10 
#define FORCED_COMPENSATION_CO2_REFERENCE  400
#define PRESSURE_REFERENCE  900

/**
 * Create CO2 object. Unless otherwise specified,
 * using the Wire interface
 */
PASCO2Ino cotwo;

int16_t co2ppm;
Error_t err;

void setup()
{
    Serial.begin(9600);
    delay(500);
    Serial.println("serial initialized");

    /* Initialize the i2c interface used by the sensor */
    Wire.begin();
    Wire.setClock(I2C_FREQ_HZ);

    /* Initialize the sensor */
    err = cotwo.begin();
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("initialization error: ");
      Serial.println(err);
    }

    /* Clear previous forced compensation offset */
    err = cotwo.clearForcedCompensation();
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("clear forced compensation error: ");
      Serial.println(err);
    }

  err = cotwo.setPressRef(PRESSURE_REFERENCE);
  if (XENSIV_PASCO2_OK != err)
  {
    Serial.print("pressure reference error: ");
    Serial.println(err);
  }

    Serial.print("forced compensation started with ");
    Serial.print(FORCED_COMPENSATION_CO2_REFERENCE);
    Serial.println(" ppm baseline reference ...");

    err = cotwo.performForcedCompensation(FORCED_COMPENSATION_CO2_REFERENCE);
    if (XENSIV_PASCO2_OK != err)
    {
      Serial.print("forced compensation error: ");
      Serial.println(err);
    }

    Serial.println("forced compensation finished");

    /*
      * Configure the sensor to measureme periodically 
      * every 10 seconds
      */
    err = cotwo.startMeasure(PERIODIC_MEAS_INTERVAL_IN_SECONDS);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("start measure error: ");
      Serial.println(err);
    }
}

void loop()
{
    /* Wait for the value to be ready. */
    delay(PERIODIC_MEAS_INTERVAL_IN_SECONDS*1000);

    err = cotwo.getCO2(co2ppm);
    if(XENSIV_PASCO2_OK != err)
    {
      /* Retry in case of timing synch mismatch */
      if(XENSIV_PASCO2_ERR_COMM == err)
      {
        delay(600);
        err = cotwo.getCO2(co2ppm);
        if(XENSIV_PASCO2_OK != err)          
        {
          Serial.print("get co2 error: ");
          Serial.println(err);
        }
      }
    }

    Serial.print("co2 ppm value : ");
    Serial.println(co2ppm);

    /*
     * Assuming we have some mechanism to obtain a
     * pressure reference (i.e. a pressure sensor),
     * we could compensate again by setting the new reference. 
     * Here we just keep the initial value.
     */
    err = cotwo.setPressRef(PRESSURE_REFERENCE);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("pressure reference error: ");
      Serial.println(err);
    }
}

early-notification

C/C++
Readout of the sensor CO2 concentration based on early notification synched via hardware interrupt
#include <Arduino.h>
#include <pas-co2-ino.hpp>

/**
 * In this example, the interrupt is used to control the  12V emitter 
 * power supply, to just keep it enabled while the sensing is 
 * performed.
 * The interrupt signal will be enabled as long as the measure is 
 * being performed. 
 * At least, three options could be considered here:
 * 
 * 1. Direct hardware coupling of interrupt and 12V power supply.
 *    
 *    The interrupt signal is interfaced with a load control 
 *    circuitry which switches on/off the 12V signal. There is 
 *    no intervention of the controller. The interrupt signal
 *    is not be connected to the microcontroller. The controller
 *    can just synchronize the readout by delays and/or just poll 
 *    for the ready measurement.
 * 
 * 2. MCU coupling of interrupt and 12V power supply.
 * 
 *    The interrupt signal is interfaced with the microcontroller,
 *    which uses another digital output to enable or disable the 
 *    12V emitter power supply. 
 * 
 * 3. Both direct 12V coupling and MCU interfacing of interrupt signal.
 * 
 *    Alternatively, both options can be combined: the interrupt is 
 *    directly interfaced to the 12V power supply enablement
 *    signal, and it is additionally connected to the 
 *    microcontroller for only readout synchronization purposes.
 *
 *  In this example, we consider the third option. The micrcontroller
 *  waits for the falling edge on the interrupt signal to trigger the
 *  readout.
 */

uint8_t interruptPin = 9;      /* For XMC2Go. Change it for your hardware setup */

/* 
 * The sensor supports 100KHz and 400KHz. 
 * You hardware setup and pull-ups value will
 * also influence the i2c operation. You can 
 * change this value to 100000 in case of 
 * communication issues.
 */
#define I2C_FREQ_HZ     400000  
#define PERIODIC_MEAS_INTERVAL_IN_SECONDS  10 
#define EARLY_NOTIFICATION_ENABLED         true

/*
 * The constructor takes the Wire instance as i2c interface,
 * and the controller interrupt pin
 */
PASCO2Ino cotwo(&Wire, interruptPin);

int16_t co2ppm;
Error_t err;

/* 
 * A simple interrupt service routine. This callback will be 
 * executed every time that the sensor is about to start 
 * performing the measurement and when it is completed.
 * In the main loop we use that flag to synchronize the 
 * sensor CO2 concentration readout.
 */
volatile bool measurementReady = false;
void isr (void * )
{   
    uint8_t interruptPinLevel = digitalRead(interruptPin);
    /* A falling edge event*/
    if(interruptPinLevel == LOW)
    {
        measurementReady = true;
    }
    /* A rising edge event*/
    else if(interruptPinLevel == HIGH)
    {
        measurementReady = false;
    }
}

void setup()
{
    Serial.begin(9600);
    delay(500);
    Serial.println("serial initialized");

    /* Initialize the i2c serial interface used by the sensor */
    Wire.begin();
    Wire.setClock(I2C_FREQ_HZ);

    /*
    * No need to initialize the interrupt pin. This is done 
    * in the sensor begin() function 
    */
    err = cotwo.begin();
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("initialization error: ");
      Serial.println(err);
    }

    /*
    * Continuous measurement every 10 seconds.
    * Enable early notification enabled
    */
    err = cotwo.startMeasure(PERIODIC_MEAS_INTERVAL_IN_SECONDS, 0, isr, EARLY_NOTIFICATION_ENABLED);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("start measure error: ");
      Serial.println(err);
    }
}

void loop()
{
    /* Wait for measurement to be ready */
    while(false == measurementReady) { };

    /* Clear the measurement ready flag */
    Serial.println("measurement ready");
    measurementReady = false;

    err = cotwo.getCO2(co2ppm);
    if(XENSIV_PASCO2_OK != err)
    {
      Serial.print("get co2 error: ");
      Serial.println(err);
    }

    Serial.print("co2 ppm value : ");
    Serial.println(co2ppm);
}

PAS CO2 Sensor Library for Arduino

Infineon PAS CO2 sensor library for Arduino

Credits

Infineon Team

Infineon Team

79 projects • 120 followers

Comments