Go Down

Topic: Temp, Humidity CO2 sensor and library. (Read 136516 times) previous topic - next topic

KawasakiZx10r

#180
Aug 07, 2018, 11:27 pm Last Edit: Aug 15, 2018, 03:27 am by KawasakiZx10r
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.

:)  :)  :)  :)

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

Code: [Select]
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.
Code: [Select]
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.
Code: [Select]
// 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

Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.

Albert Einstein

morr8362

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.

KawasakiZx10r

#182
Jan 21, 2019, 02:54 pm Last Edit: Jan 21, 2019, 03:07 pm by KawasakiZx10r
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.
Only two things are infinite, the universe and human stupidity, and I'm not sure about the former.

Albert Einstein

morr8362

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.

nagol10h

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)

Code: [Select]

/*
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

https://github.com/RobTillaart/Arduino/tree/master/libraries/Cozir

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

Code: [Select]


#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

morr8362



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.

Quote
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
2. 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. 

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


Hope this helps.

AmphenolSensors

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: https://github.com/AmphenolAdvancedSensors/Telaire

Go Up