//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.close();
Serial.println("done.");
} else {
Serial.println("error opening data.txt");
}
Serial.println();
}
//--------------------------
output file read: