issues sending K33 CO2 sensor data to datalogging shield

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
mromero
 
Posts: 94
Joined: Fri Mar 18, 2016 12:10 pm

issues sending K33 CO2 sensor data to datalogging shield

Post by mromero »

I am running a metro AT328 (arduino board) with the adafruit datalogging shield with two K33ICB 10% CO2 sensors connected using I2C. I know the clock uses address 0x68 and the address for the sensors were changed to 0x69 and 0x56 respectively. The issue i am having is the co2 reading displays fine in the serial monitor but what i get on the SD card is 0,0 for the two sensors.

Code: Select all

//2CO2_to_I2Cv4_logger

// CO2 Meter K-series Example Interface
// Revised by Marv Kausch, 7/2016 at CO2 Meter <co2meter.com>
// Talks via I2C to K30/K22/K33/Logger sensors and displays CO2 values
// 12/31/09

//03/21/2023 will attempt 2 read 2 K33 CO2 sensors by modifying Arduino_to_I2C code
//provided by vendor in explicit manner 

#include <Wire.h>
#include <SD.h>//sd card
#include <SPI.h>
#include <RTClib.h>// clock

// We will be using the I2C hardware interface on the Arduino in
// combination with the built-in Wire library to interface.
// Arduino analog input 5 - I2C SCL
// Arduino analog input 4 - I2C SDA
/*
  In this example we will do a basic read of the CO2 value and checksum verification.
  For more advanced applications please see the I2C Comm guide.
*/
//int co2Addr =0;
int co2Addr1 = 0x69;// CO2 sensor 1
int co2Addr2 = 0x56;// CO2 sensor 2

int co2Value_1;
int co2Value_2;

// This is the default address:0x68 of the CO2 sensor, 7bits shifted left.  for sensor board 2 changed to 0X6A

RTC_PCF8523 rtc;// clock on datalogger

// create file
File myFile;
String Date,Time,CO2_1,CO2_2 ,Data;



void setup() {//=============================================================

  //start clock
    rtc.begin();
    
  //serial
  Serial.begin(9600);
  delay(2000);

   //clock 
 if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1) delay(10);
  }
    if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }  // close clock

  // SD card initialize

  Serial.print("Initializing SD card...");
  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("data.txt", FILE_WRITE); 
  if (myFile) {
    myFile.println( "Date, Time, CO2_1(ppm), CO2_2(ppm)) \r\n");
    myFile.close();
  } 
  else {
    Serial.println("error opening data.txt");
  }

  
  
  Wire.begin ();
  pinMode(13, OUTPUT); // address of the Arduino LED indicator
  Serial.println("Application Note AN-102: Interface Arduino to two  K-333");

  
}//==================================================== close setup Loop


///////////////////////////////////////////////////////////////////
// Function : int readCO2_1()
// Returns : CO2 Value upon success, 0 upon checksum failure
// Assumes : - Wire library has been imported successfully.
// - LED is connected to IO pin 13
// - CO2 sensor address is defined in co2_addr
///////////////////////////////////////////////////////////////////

int readCO2_1()
{//+++++++++++++++++++++++++++++++++++++++++++++++++  read CO2()function definition
  int co2_value_1 = 0;  // We will store the CO2 value inside this variable.

  digitalWrite(13, HIGH);  // turn on LED
  // On most Arduino platforms this pin is used as an indicator light.

  //////////////////////////
  /* Begin Write Sequence */
  //////////////////////////
  
  Wire.beginTransmission(0x69);
 // Wire.beginTransmission(co2Addr1);
  Wire.write(0x22);
  Wire.write(0x00);
  Wire.write(0x08);
  Wire.write(0x2A);

  Wire.endTransmission();

  /////////////////////////
  /* End Write Sequence. */
  /////////////////////////

  /*
    We wait 10ms for the sensor to process our command.
    The sensors's primary duties are to accurately
    measure CO2 values. Waiting 10ms will ensure the
    data is properly written to RAM

  */

  delay(10);

  /////////////////////////
  /* Begin Read Sequence */
  /////////////////////////

  /*
    Since we requested 2 bytes from the sensor we must
    read in 4 bytes. This includes the payload, checksum,
    and command status byte.

  */

  Wire.requestFrom(0x69, 4);

  byte i = 0;
  byte buffer[4] = {0, 0, 0, 0};

  /*
    Wire.available() is not nessessary. Implementation is obscure but we leave
    it in here for portability and to future proof our code
  */
  while (Wire.available())
  {
    buffer[i] = Wire.read();
    i++;
  }

  ///////////////////////
  /* End Read Sequence */
  ///////////////////////

  /*
    Using some bitwise manipulation we will shift our buffer
    into an integer for general consumption
  */

  co2_value_1 = 0;
  co2_value_1 |= buffer[1] & 0xFF;
  co2_value_1 = co2_value_1 << 8;
  co2_value_1 |= buffer[2] & 0xFF;


  byte sum = 0; //Checksum Byte
  sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow

  if (sum == buffer[3])
  {
    // Success!
    digitalWrite(13, LOW);
    return co2_value_1;
  }
  else
  {
    // Failure!
    /*
      Checksum failure can be due to a number of factors,
      fuzzy electrons, sensor busy, etc.
    */

    digitalWrite(13, LOW);
    return 0;
  }
}//++++++++++++++++++++++++++++++++++++++++++ close the read CO2 function definition

///////////////////////////////////////////////////////////////////
// Function : int readCO2_2()
// Returns : CO2 Value upon success, 0 upon checksum failure
// Assumes : - Wire library has been imported successfully.
// - LED is connected to IO pin 13
// - CO2 sensor address is defined in co2_addr
///////////////////////////////////////////////////////////////////

int readCO2_2()
{//+++++++++++++++++++++++++++++++++++++++++++++++++  read CO2()function definition
  int co2_value_2 = 0;  // We will store the CO2 value inside this variable.

  digitalWrite(13, HIGH);  // turn on LED
  // On most Arduino platforms this pin is used as an indicator light.

  //////////////////////////
  /* Begin Write Sequence */
  //////////////////////////

  Wire.beginTransmission(0x56);
  Wire.write(0x22);
  Wire.write(0x00);
  Wire.write(0x08);
  Wire.write(0x2A);

  Wire.endTransmission();

  /////////////////////////
  /* End Write Sequence. */
  /////////////////////////

  /*
    We wait 10ms for the sensor to process our command.
    The sensors's primary duties are to accurately
    measure CO2 values. Waiting 10ms will ensure the
    data is properly written to RAM

  */

  delay(10);

  /////////////////////////
  /* Begin Read Sequence */
  /////////////////////////

  /*
    Since we requested 2 bytes from the sensor we must
    read in 4 bytes. This includes the payload, checksum,
    and command status byte.

  */

  Wire.requestFrom(0x56, 4);

  byte i = 0;
  byte buffer[4] = {0, 0, 0, 0};

  /*
    Wire.available() is not nessessary. Implementation is obscure but we leave
    it in here for portability and to future proof our code
  */
  while (Wire.available())
  {
    buffer[i] = Wire.read();
    i++;
  }

  ///////////////////////
  /* End Read Sequence */
  ///////////////////////

  /*
    Using some bitwise manipulation we will shift our buffer
    into an integer for general consumption
  */

  co2_value_2 = 0;
  co2_value_2 |= buffer[1] & 0xFF;
  co2_value_2 = co2_value_2 << 8;
  co2_value_2 |= buffer[2] & 0xFF;


  byte sum = 0; //Checksum Byte
  sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow

  if (sum == buffer[3])
  {
    // Success!
    digitalWrite(13, LOW);
    return co2_value_2;
  }
  else
  {
    // Failure!
    /*
      Checksum failure can be due to a number of factors,
      fuzzy electrons, sensor busy, etc.
    */

    digitalWrite(13, LOW);
    return 0;
  }
}//++++++++++++++++++++++++++++++++++++++++++ close the read CO2 function definition




void loop() {//#####################################################void loop

   // make a string for assembling the data to log:
     data_logging();
     
     delay(10000);//time between writting to sd card: delay(ms) 1000=1sec ; 900,000=15 min use this for final use 20,000 for testing


 //once for sensor1 ADDRESS0x69//****************************************************************

 // int co2Value = readCO2();// orig
 int co2Value_1 = readCO2_1()*10;// what i was told to do. this gives half of what the dev kit prewired one reads.

  
  if (co2Value_1 > 0)
  {
    Serial.print("CO2 Value1: ");
    Serial.println(co2Value_1);
  }
  else
  {
    Serial.println("Checksum failed / Communication failure");
  }
  delay(2000);
  //********************************************************************done with CO2value1

  
//once for sensor2 ADDRESS0x56//****************************************************************

 // int co2Value = readCO2();// orig
 int co2Value_2 = readCO2_2()*10;// what i was told to do. this gives half of what the dev kit prewired one reads.

  
  if (co2Value_2 > 0)
  {
    Serial.print("CO2 Value2: ");
    Serial.println(co2Value_2);
  }
  else
  {
    Serial.println("Checksum failed / Communication failure");
  }
  delay(2000);
  
}//##############################################################################close loop

//--------------------subroutines------------------------------------

void data_logging() {
//  String CO2_1 = String(co2Value_1);
//  String CO2_2 = String(co2Value_2);
// 
//  Data = CO2_1 + "," + CO2_2  ;
//  

  Serial.print("Save data: ");
  Serial.println(Data);

  myFile = SD.open("data.txt", FILE_WRITE);
  if (myFile) {
    Serial.print("Writing to data.txt...");
    
    //time stamp
    DateTime now = rtc.now();
    myFile.print(now.year(), DEC);
    myFile.print('/');
    myFile.print(now.month(), DEC);
    myFile.print('/');
    myFile.print(now.day(), DEC);
    myFile.print(",");
    myFile.print(now.hour(), DEC);
    myFile.print(':');
    myFile.print(now.minute(), DEC);
    myFile.print(",");//delimeter between time and data
    //
   // myFile.println(Data);//ln adds carriage return
   myFile.print(co2Value_1);
   myFile.print(" , ");
   myFile.println(co2Value_2);
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("error opening data.txt");
  }  
  Serial.println();
}

//--------------------------

Attachments
output file.png
output file.png (8.89 KiB) Viewed 172 times
serial console.png
serial console.png (16.93 KiB) Viewed 172 times

User avatar
adafruit_support_bill
 
Posts: 88041
Joined: Sat Feb 07, 2009 10:11 am

Re: issues sending K33 CO2 sensor data to datalogging shield

Post by adafruit_support_bill »

In your loop, you are reading and printing the value of a local variable declared here:

Code: Select all

 int co2Value_1 = readCO2_1()*10;// what i was told to do.
In your data_logging function, you are logging the value of the global variable (with the same name) declared here:

Code: Select all

int co2Value_1;
Sine the global variable is never initialized or assigned to, it always logs zero.

User avatar
mromero
 
Posts: 94
Joined: Fri Mar 18, 2016 12:10 pm

Re: issues sending K33 CO2 sensor data to datalogging shield

Post by mromero »

I thought i had initiallized it when i wrote:

int co2Value_1;
int co2Value_2;
outside the void set up and void loop. was i supposed to initialize in a different way.

thanks for the help in advance

User avatar
adafruit_support_bill
 
Posts: 88041
Joined: Sat Feb 07, 2009 10:11 am

Re: issues sending K33 CO2 sensor data to datalogging shield

Post by adafruit_support_bill »

I thought i had initiallized it when i wrote:

int co2Value_1;
int co2Value_2;
outside the void set up and void loop. was i supposed to initialize in a different way.
That is just a declaration of two variables at global scope. It does not initialize anything.

In your loop you declare a new variable at local scope. And you assign it the value of the current co2 reading.

Code: Select all

int co2Value_1 = readCO2_1()*10;
This new variable just happens to have the same name as the one you declared at global scope. But it is not the same variable!

A few lines later, you print the value of the local variable:

Code: Select all

  if (co2Value_1 > 0)
  {
    Serial.print("CO2 Value1: ");
    Serial.println(co2Value_1);
  }
  
However, in your data_logging function you are printing the value of the global variable which has never had a value assigned to it.

Code: Select all

   myFile.print(co2Value_1);
   myFile.print(" , ");
   myFile.println(co2Value_2);
   
To fix this, you can just eliminate the declaration of the local variables in your loop and just assign the co2 readings to the global variables. In other words:

change this:

Code: Select all

int co2Value_1 = readCO2_1()*10;
to this:

Code: Select all

co2Value_1 = readCO2_1()*10;
https://www.tutorialspoint.com/cplusplu ... _scope.htm

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”