Temp, Humidity CO2 sensor and library.

HiBela
For calibrating Cozir and MinIr sensors, I would recommend using a terminal program (e.g. Hyperterminal or CO2meter.com's GasLab software, which will recognize many sensors bought through CO2meter.com !). This way, you can connect your sensor through a UART to USB-interface (such as your FTDI arduino-mini programmer or even a chinese CP1202). But instead of you having to write the instructions, you simply enter the basic communication codes as stated in GSS' datasheets for your sensor (send line ends with line feeds !).
This will keep your arduino code limited to the minimum required for use.
Since revision AL19 (2013), the communication protocol for Cozir, SprintIR, Misir and MinIR sensors is the same for the three types of sensors. To calibrate the lower span point, you can either choose to use a known gas concentration or to use a fresh air calibration.
The problem is that, due to global warming, fresh air tends to contain more and more CO2 every year, and that actually, on the northern hemisphere, fresh air contains over 400 ppm, depending on the area. In 2016, the CO2-concentration in the southern hemisphere has also exceeded 400 ppm.
But lets's assume that fresh air contains 400 ppm, then you can simply send the command G\r\n to your sensor, which sets the zero point assuming the sensor is in 400 ppm.
If you want it more precise and you know the real value of fresh air, e.g. you want to set the lower span point of, let's say, 450 ppm, then you have to send the command F 410 450\r\n where the first value is your actual reading and the second one the known gas concentration in ppm.

Hi,

I have just got my Cozir wide range 5-100% co2 sensor and i have uploaded the code on this forum for it to start co2 measurements. Could some one please help me understand a couple of things. Thanks alot.

  1. i believe there are multiple models of cozir for example 20%, 65% , 100% range etc .. How does this library handle these models. Because for example if i am using 100% range co2 sensor than do i have to multiply my output with 100 ? if i am using 20% range sensor than do i have to multiply co2 measurement with 10 ? .. So on .. where and how does this library takes this in to account ?
    Right now i have followed the instructions in this forum of commenting and uncommenting
//czr.SetOperatingMode(CZR_POLLING);
//czr.SetOperatingMode(CZR_STREAMING);

//czr.CalibrateFreshAir();

to calibrate the sensor for first use. And after that i get the following measurement from my sensor on the serial monitor:

Celcius: 29.20
Farrenheit : 84.56
Co2: 1
Digital Filter: 16

Celcius: 29.20
Farrenheit : 84.56
Co2: 0
Digital Filter: 16

Celcius: 29.20
Farrenheit : 84.56
Co2: 0
Digital Filter: 16

NOTE: CO2 values.

When i blow on it the values go up to 20.

My question: Shouldn't these values be in the range of something like 400-600 ppm . (My environment is normal office with window open for fresh air with one person in the room)...

Thank you people for the love forum.

I have been using the cozir sensor for a few years now, and your code/libraries have been great. I would like to add it to a TFT touch screen and for the life of me cannot find a way to print the readings to the screen. What is the easiest way to go about tackling such a task? Seems like reading the Serial.print since we are already establishing that would be the easiest, but does that still work when you're not connected to a computer? I am not asking for someone to write the code, because I want to learn how to do this myself, but to point me where I can learn the easiest and most efficient way to perform the task.

@timothypaul26

First learn to work with the TFT of your choice without any sensor or so, just have simple messages like "Hello" and move from there to e.g. the time in millis() since start. What you need to learn is to erase part of the screen before writing a new value to it.
Then connect the Cozir and capture the data from it and send it to the TFT, updating in a similar way.

thanks Rob, I have my tft working, and using a 1307 rtc and I can send all of that data. Maybe I do need to work more, but I cannot figure out what in the cozir.h can be sent. I'm assuming that I need to write varriables and such? Is there an example that you could reccomend? For practice?

(I do not have a COZIR sensor but helped writing the library for it)

Besides the CO2 level you could print the other values the sensor can provide (lux and temp). Besides the actual level you could print the average upto that moment or so. Or peak info of the last 7 days?

Or did I misinterpret your question?

I think that my sensor only has temp, humidity and co2. Is it possible to read the pins for those or do I have to read off of the serial, or is this an IIC setup? I'm not sure where to look into how to create the varriables and statements to get the information from the sensor to print to the TFT.

I guess I should know that it's serial only as it states that in the data sheet... And that is where my trouble is, i'm not sure how to use the serial communication. I'll continue reading and see if that helps me get a bit closer to my goal.

The code in post #166 above might help you to get all info out of the sensor...

I had that code from the example. Every time I would try to myGLCD.print(c(), CENTER, 0); I would get an error. After reading through the UTFT manual a few times I realized that it told you how to print a float... myGLCD.printNumF(c(), CENTER, 0); did the trick. Once I got that figured out things went well from there. I was having a funny issue where my rtc and my co2/temp/humidity would only update for 5 seconds and freeze. Only thing I could think of is that there was some sort of serial conflict? I changed the rtc speed to 4k, and it seems to have fixed the issue, but I'm not sure that it's the best fix, might be more of a band-aid? Time will tell I guess. I really do appreciate your patients with me and the work that you and DirtGambit have done on this library, also thanks to Henning for his work. My hat is off to all of you.

Hello everyone, i have read the entire thread now, can i still can't get my COZIR av-2000 sensor to work.

First off i have the sensor without temperature and humidity so only the CO2 sensor.

have today 27/11-2017 downloaded the newest versions of the cozir.h
i am trying to get this to work on an ATMega2560 and using the following code

#include <SoftwareSerial.h>
#include "cozir.h"

SoftwareSerial nss(11,12);
COZIR czr(nss);

void setup()
{
Serial.begin(9600);
delay(5000);
czr.SetOperatingMode(CZR_POLLING);
//czr.SetOperatingMode(CZR_STREAMING);
//czr.CalibrateFreshAir();
// czr.SetDigiFilter(64);
}

void loop()
{
delay(1000);
float t = czr.Celsius();
float f = czr.Fahrenheit();
float h = czr.Humidity();
int c = czr.CO2();
int digi = czr.GetDigiFilter();

Serial.print("Celcius : ");Serial.println(t);
Serial.print("Fahrenheit : ");Serial.println(f);
Serial.print("Humidity : ");Serial.println(h);
Serial.print("CO2 : ");Serial.println(c);
Serial.print("Digital Filter : ");Serial.println(digi);
Serial.println("");
}

and i am getting the following output:

Celcius : 0.20
Fahrenheit : 32.36
CO2 : 2
Digital Filter : 2

Hope somone can help

Ps nothing happens when i blow on it..

I just bought one of these COZIR co2 sensors the "COZIR-AH-5000" and after trying the library they offer i could not get it to read the data, However i was able to use the post he provides in this thread to calibrate it, by uncommenting and commenting out the given lines in his example.

But again not reading the data, the library example was just printing 0.00 or nothing at all.

So i looked through the library and wrote a shorter but just as accurate code that you can just paste into your C code, you can also use any serial method, as the library only allowed software serial.

:slight_smile: :slight_smile: :slight_smile: :slight_smile:

Here is my code to read the data when set to Streaming mode "Default mode"

char buffer[32];
char buff[6];
byte bufferCount = 0;
float celsius;
float fahrenheit;
float humidity;
int co2;
int digiRead;


void setup()
{
  Serial1.begin(9600);
  Serial.begin(115200);
  Serial.println(F("Starting system."));
}

void loop()
{
  getSerialData();
}

place this code in a new tab to keep your project organized.

void getSerialData() {
  char input = Serial1.read();
  if (input > 0 && input != 32 && bufferCount < 32) {  // 0 is null, 32 is a space
    buffer[bufferCount] = input;
    // Serial.print(input);  // expected format: H00588T01263Z00456z00456
    bufferCount++;
  }
  else if (input == '\n') { // input == 10, but '\n' is easier to read.
    bufferCount = 0;
    formatData();
  }
}

void formatData() {
  //Serial.print("\nbuffer: "); Serial.println(buffer);
  // ============================ Humidity ============================
  sortBuffer(1);
  humidity = atof(buff);
  humidity = humidity * 0.1;
  clearBuff();
  // ============================ Temperature =========================
  sortBuffer(7);
  celsius = atof(buff);
  if (celsius < 1000)
  {
    celsius = 0.1 * celsius;
  }
  else
  {
    celsius = 0.1 * (celsius - 1000);
  }
  fahrenheit = celsius * 1.8 + 32;
  clearBuff();
  // ============================ Digital Read ========================
  sortBuffer(13);
  digiRead = atoi(buff);
  clearBuff();
  // ============================ Raw Co2 =============================
  sortBuffer(19);
  co2 = atoi(buff);
  clearBuff();
  // =========================== Clear the main buffer ===============
  for (byte n = 0; n < 32; n++) {
    buffer[n] = 0;
  }
  // ============================ Print Data =========================
  Serial.print(F("\nHumidity: ")); Serial.println(humidity);
  Serial.print(F("Celsius: ")); Serial.println(celsius);
  Serial.print(F("Fahrenheit: ")); Serial.println(fahrenheit);
  Serial.print(F("Digital Co2 ppm: ")); Serial.println(digiRead);
  Serial.print(F("Raw Co2 pmm: ")); Serial.println(co2);
}

void sortBuffer(byte start) {
  for (byte i = start; i < start + 5; i++) {
    buff[i - start] = buffer[i];
  }
}

void clearBuff() {
  for (byte n = 0; n < 6; n++) {
    buff[n] = 0;
  }
}

Output:

Humidity: 46.80
Celsius: 25.90
Fahrenheit: 78.62
Digital Co2 ppm: 459
Raw Co2 pmm: 529

And here is my code for Polling mode, COZIR set to mode 2 Polling !
Which i recommend using, it more efficient and quicker than Streaming mode and compared
to the library recommended in this thread, my code is far quicker and uses less resources, being
22 Bytes in total, and only two 50ms delays compared to the 250 ms delay that said library sends after each request being 4 in total.

// https://www.airtest.com/support/datasheet/COZIRSerialInterface.pdf

//    Command             Description               Example         Notes

//    G\r\n               fresh air calibration     G\r\n           Assumes 450ppm in fresh air !
//    F ##### #####\r\n   exact calibration         F 410 400\r\n   Note the space after F and the first value
//    K #\r\n             set mode                  K 1\r\n         Mode 0 = Command Mode,  Mode 1 = Streaming Mode,  Mode 2 = Polling Mode. --- Note the space after K
//    Z\r\n               get Co2                   Z\r\n
//    T\r\n               get temperature           T\r\n
//    H\r\n               get humidity              H\r\n

char buffer[8];
byte bufferCount = 0;
byte receiveCount = 0;
float celsius;
float humidity;
int digitalCo2;
// timer vars
unsigned long currentMillis;
unsigned long oneSecond_PreviousMillis;
const long oneSecondInterval = 1000;


void setup() {
  Serial1.begin(9600); // here i am using an Arduino Mega2560 on Serial 1, if your using a Uno you can use software serial instead.
  // Or just use the Main Serial below which i am using for data output, but if you do just use the main serial alone be care what you print when debugging else you may
  // Send a cmd to the COZIR and calibrate it in the wrong situation i.e gas mode or whatever so please be careful.
  Serial.begin(115200);
  Serial.println(F("Starting system."));
}

void loop() {
  currentMillis = millis();
  if (currentMillis - oneSecond_PreviousMillis >= oneSecondInterval) { // one second timer
    cozSerialData();
    oneSecond_PreviousMillis = currentMillis;
  }
}

void cozSerialData(void) {
  Serial1.println(F("Z")); // request co2
  delay(50);
  Serial1.println(F("T")); // request celsius
  delay(50);
  Serial1.println(F("H")); // request R/H
  bool foundValues = false;
  while (!foundValues) {
    char input = Serial1.read();
    if (input > 0) {
      if (input != '\n' && input != 32 && bufferCount < 8) { // get response from COZIR
        buffer[bufferCount] = input;
        bufferCount++;
      }
      else if (input == '\n') { // sort Serial data once we have received the \n
        bufferCount = 0;
        //Serial.println(buffer);
        for (byte i = 0; i < 7; i++) { // shuffle array back one position to get rid of the capital letter
          buffer[i] = buffer[i + 1];
        }
        receiveCount++;
        if (receiveCount == 1) {
          digitalCo2 = atoi(buffer);
          Serial.print(F("\nDigital Co2 ppm: ")); Serial.println(digitalCo2);
        }
        else if (receiveCount == 2) {
          celsius = atof(buffer);
          if (celsius < 1000) {
            celsius = 0.1 * celsius;
          }
          else {
            celsius = 0.1 * (celsius - 1000);
          }
          Serial.print(F("Celsius: ")); Serial.println(celsius);
        }
        else if (receiveCount == 3) {
          humidity = atof(buffer);
          humidity = humidity * 0.1;
          Serial.print(F("Humidity: ")); Serial.println(humidity);
          receiveCount = 0;
          foundValues = true;
        }
        for (byte i = 0; i < 8; i++) { // clear the entire buffer array
          buffer[i] = 0;
        }
      }
    }
  }
}

Output:

Digital Co2 ppm: 518
Celsius: 25.10
Humidity: 51.70

Co2_PollingMode.ino (3.16 KB)

This library is great! I am looking through the data sheet and the library and I see there are options to show Light and/or LED intensity. Which is called using "O". How can I get that to print to serial?

second question for KawasakiZx10r. I downloaded your .ino file and it doesn't print any data just the commands for H Z and T. Is there more I need to do to make use of your script?

Thanks for all the hard work you have put into this.

Depends which codes are you running if you are running the second one, you must make sure that you have sent the command to set the CO2 sensor for polling mode.

In case you are unsure how to change the mode you must just send a capital k using serial print line, just send it the setup, mode 1 is streaming and mode 2 is polling.

I have been operating in polling mode. Would Serial.Println ("K 2"); need to be re declared during the setup?

I have been using the script by Dirtgambit I have gone back to see if Humidity and Temp read but now only the CO2 seems to be reading.

Hi everyone,

Is anyone having problems using this cozir(versions 1 to 1.03 tested so far) library with the arduino create web editor?

I have been able to use my CO2 sensor using a sketch made by Jason Berger(does not use the cozir lib)

http://forum.arduino.cc/index.php?action=dlattach;topic=91467.0;attach=78152

code below
( I placed the sensor inside a 5% co2 incubator and changed the multiplier until it showed the correct ppm(50,000) for 5% CO2) (final value set to 70)

/*
Cozir Sample code
 Written by: Jason Berger ( for Co2meter.com)


// From PDF guide http://forum.arduino.cc/index.php?action=dlattach;topic=91467.0;attach=78152


 This sketch connects will connect to a Cozir gss or SprintIR sensor
 and report readings back to the host computer over usb. The value is
 stored in a global variable 'co2' and can be used for any number of applications.

 pin connections:

 Arduino________Cozir Sensor
 GND ------------------ 1 (gnd)
 3.3v------------------- 3 (Vcc)
 10 -------------------- 5 (Rx)
 11 -------------------- 7 (Tx)
 */
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
String val= ""; //holds the string of the value
double co2 =0; // holds the actual value
double multiplier = 70; //each range of sensor has a different value. ````
 // up to 2% =1
 // up to 65% = 10
 //up to 100% = 100;
uint8_t buffer[25];
uint8_t ind =0;
void setup()
{
 Serial.begin(9600); //Start Serial connection with host
 Serial.println("Co2Meter.com Cozir Sample"); 


 mySerial.begin(9600); //Start Serial connection with Sensor

}
void loop()
{
 //Cozir sensors ship from the factory in streaming mode
 //So we read incoming bytes into a buffer until we get '0x0A' which is the ASCII value for new-line
 while(buffer[ind-1] != 0x0A)
 {
 if(mySerial.available())
 {
 buffer[ind] = mySerial.read();
 ind++;
 }
 }

 report(); //Once we get the '0x0A' we will report what is in the buffer
}
void report()
{
 //Cycle through the buffer and send out each byte including the final linefeed

 /*
 each packet in the stream looks like "Z 00400 z 00360"
 'Z' lets us know its a co2 reading. the first number is the filtered value
 and the number after the 'z' is the raw value.
 We are really only interested in the filtered value

 */

 for(int i=0; i < ind+1; i++)
 {
 if(buffer[i] == 'z') //once we hit the 'z' we can stop
 break;

 if((buffer[i] != 0x5A)&&(buffer[i] != 0x20)) //ignore 'Z' and white space
 {
 val += buffer[i]-48; //because we break at 'z' the only bytes getting added are the numbers
 // we subtract 48 to get to the actual numerical value
 // example the character '9' has an ASCII value of 57. [57-48=9] 


 }
 }

 co2 = (multiplier * val.toInt()); //now we multiply the value by a factor specific ot the sensor. see the cozir software guide

 Serial.print( "Co2 = ");
 Serial.print(co2);
 Serial.println(" ppm");
 ind=0; //Reset the buffer index to overwrite the previous packet
 val=""; //Reset the value string
}

I have read this entire thread and there is a lot of great info but I have not seen any talk of using the arduino create web editor with the cozir library.

Does the cozir library work on the arduino create web editor by automatically pulling the #included libraries from github? This is my understanding from reading about the way the web editor uses libraries.

I got the library and example sketch from

Using just the example sketch provided below without adding any libraries to the custom section of the web editor...

#include <cozir.h>

#if defined(ARDUINO) && ARDUINO >= 100
  #include <SoftwareSerial.h>
  SoftwareSerial nss(3,2);
#else
  #include <NewSoftSerial.h>
  NewSoftSerial nss(3,2);
#endif


COZIR czr(nss);

void setup()
{
  Serial.begin(9600);
  Serial.println("Setup");
  delay(1000);
}

void loop()
{
  Serial.println("Loop");
  float t = czr.Celsius();
  float f = czr.Fahrenheit();
  float h = czr.Humidity();
  uint16_t c = czr.CO2();
  
  Serial.print("Celcius = ");
  Serial.println(t);
  Serial.print("Fahrenheit = ");
  Serial.println(f);
  Serial.print("Humidity = ");
  Serial.println(h);
  Serial.print("CO2 = ");
  Serial.println(c);
  
  delay(3000);
}

I get the error:

Detecting libraries used...

/tmp/217961788/Cozir_test/Cozir_test.ino:5:19: fatal error: cozir.h: No such file or directory

compilation terminated.

exit status 1

If I uploaded the Cozir library (I tried versions cozir 1.0 to cozir 0.1.03 so far) to the custom libraries section of the arduino create web editor and then try to compile the same code as above I get a slightly different error


Multiple libraries were found for "SoftwareSerial.h"

Used: /home/ubuntu/opt/cores/arduino/avr/libraries/SoftwareSerial

Not used: /home/ubuntu/opt/libraries/latest/printoo_library_1_0_2

Not used: /home/ubuntu/opt/libraries/latest/dabble_1_0_0

Using library cozir in folder: /tmp/930274234/custom/cozir (legacy)

Using library SoftwareSerial at version 1.0 in folder: /home/ubuntu/opt/cores/arduino/avr/libraries/SoftwareSerial

/tmp/930274234/custom/cozir/cozir.cpp:14:19: fatal error: Cozir.h: No such file or directory

#include "Cozir.h"

^

compilation terminated.

exit status 1


In this scenario It seems to be recognizing one library(cozir.h) and then not being able to find the one with a Capital C (Cozir.h or maybe cozir.cpp?)

So it seems that uploading the cozir library to the custom section of the web editor does SOMETHING but still does not get it to compile completely. I have not been able to get past this problem and be able to use the functionality of this great library

I hope that it is something simple I am missing as a beginner

I am not sure where to go from here and any advice would be much appreciated!

Cozir libraries used to upload to the custom section of arduino create web editor are attached

cozir0.1.03.zip (93.6 KB)

cozir.zip (2.99 KB)

I'm also noob but I've gotten a lot better thanks to the help I've received through this forum.

A few things I would try:

  1. Remove the files that contain the "SoftwareSerial" library from your libraries folder and see if that helps.

Used: /home/ubuntu/opt/cores/arduino/avr/libraries/SoftwareSerial

Not used: /home/ubuntu/opt/libraries/latest/printoo_library_1_0_2

Not used: /home/ubuntu/opt/libraries/latest/dabble_1_0_0

  1. find a PC and Download the desktop IDE, I feel like I've read a lot of posts where people are having difficulties with the web version.

  2. If it's looking for Cozir.h and you have cozir.h it won't find the header file.

Hope this helps.

Suugest you just try an Amphenol Sensors T6713, half the cost, 5V, I2C, just as accurate, and can change address if you need.

Code is:
#define ADDR_6713 0x15 // default I2C slave address

byte data[6];
int CO2ppmValue;

void GetCO2PPM()
{
// start I2C
Wire.beginTransmission(ADDR_6713);
Wire.write(0x04);
Wire.write(0x13);
Wire.write(0x8B);
Wire.write(0x00);
Wire.write(0x01);

// end transmission
Wire.endTransmission();

// read report of current gas measurement in ppm after delay!
delay(5);

Wire.requestFrom(ADDR_6713, 4); // request 4 bytes from slave device
data[0] = Wire.read();
data[1] = Wire.read();
data[2] = Wire.read();
data[3] = Wire.read();

CO2ppmValue = ((data[2] & 0x3F ) << 8) | data[3];
}

Other code examples available at: GitHub - AmphenolAdvancedSensors/Telaire: Arduino Code to communicate and measure AAS Telaire Sensors

Is there any way that the COZIR-AH-1 can work with the Arduino MKRWAN 1300 board?

If you want temp and hum, as well as a shield, screen, UNO clone, CO2 sensor, and a dust sensor, then google part number "aas-aqs-uno-rh-co2", code is preloaded, but also available on github (search AmphenolAdvncedSensors). Its also less cost than the solution suggested here.