0.3.0 Cozir

This commit is contained in:
rob tillaart 2021-08-15 19:38:45 +02:00
parent e67bc3a86a
commit 50c8a2e0f7
10 changed files with 739 additions and 351 deletions

View File

@ -12,58 +12,72 @@ Arduino library for COZIR range of temperature, humidity and CO2 sensors.
## Description
The Cozir library is **experimental** as I do not have a sensor to test the library.
The polling mode as used in the examples seems to work quite well.
The polling mode as used in the examples seems to work quite well as this is tested by DirtGambit.
This library supports only the Serial interface. An I2C based library will be written
when I have access to a Cozir sensor that supports I2C.
Idea is to make the interface identical if possible.
#### Notes
- the **CozirDemoHWSerial.ino** example needs to run on a MEGA or a Teensy,
at least a board with more than one Serial port.
- Read the datasheet before using this library. It helps to understand the working of the Cozir sensor.
- Read the datasheet before using this library.
It helps to understand the working of the Cozir sensor.
## Interface
Read the datasheet (again)
Read the datasheet (again).
### Constructor and initialisation
- **COZIR(Stream \*)** constructor
- **void init()** sets operatingMode to CZR_POLLING
- **void SetOperatingMode(uint8_t mode)** set the operating mode either to **CZR_COMMAND**, **CZR_POLLING** or **CZR_STREAMING**
- **COZIR(Stream \* str)** constructor.
- **void init()** sets operatingMode to CZR_POLLING.
- **bool isInitialized()** returns true if enough time has passed after the call to **init()** for the sensor.
### Operating mode
- **void setOperatingMode(uint8_t mode)** set the operating mode either to **CZR_COMMAND**, **CZR_POLLING** or **CZR_STREAMING**
- **uint8_t getOperatingMode()** returns the mode set, **CZR_STREAMING** is the default.
Please note that **init()** sets the operating mode to **CZR_POLLING**.
### Core
- **float Celsius()** idem
- **float Fahrenheit()** idem, wrapper around **Celsius()**
- **float Humidity()** idem
- **float Light()** idem
- **float celsius()** idem.
- **float fahrenheit()** idem, 'wrapper' around **celsius()**
- **float humidity()** idem.
- **float light()** idem.
- **uint32_t CO2()** idem.
- **uint16_t getPPMFactor()** returns 1, 10, 100 See Page 14.
### Calibration
Read datasheet before use
Read datasheet before using these functions:
- **uint16_t FineTuneZeroPoint(uint16_t v1, uint16_t v2)**
- **uint16_t CalibrateFreshAir()**
- **uint16_t CalibrateNitrogen()**
- **uint16_t CalibrateKnownGas(uint16_t value)**
- **uint16_t fineTuneZeroPoint(uint16_t v1, uint16_t v2)**
- **uint16_t calibrateFreshAir()**
- **uint16_t calibrateNitrogen()**
- **uint16_t calibrateKnownGas(uint16_t value)**
#### Calibration NOT Recommended
Following 3 functions are **NOT RECOMMENDED** by the datasheet.
Feel free to uncomment but use at your own risk. Read datasheet before use.
Feel free to uncomment and use at your own risk.
Read datasheet before using these functions:
- **uint16_t CalibrateManual(uint16_t value)**
- **uint16_t SetSpanCalibrate(uint16_t value)**
- **uint16_t GetSpanCalibrate()**
- **uint16_t calibrateManual(uint16_t value)**
- **uint16_t setSpanCalibrate(uint16_t value)**
- **uint16_t getSpanCalibrate()**
### Digifilter
use with care, read datasheet before use
use with care, read datasheet before use.
| value | meaning |
|:-----:|:--------|
@ -72,22 +86,26 @@ use with care, read datasheet before use
| 32 | default, good average |
| 255 | slow, max smoothed |
- **void SetDigiFilter(uint8_t value)**
- **uint8_t GetDigiFilter()**
- **void setDigiFilter(uint8_t value)**
- **uint8_t getDigiFilter()**
### Streaming MODE
Warning: Not tested ,
- **void SetOutputFields(uint16_t fields)** Sets the fields in the output stream.
- **void ClrOutputFields()** clears all the fields.
- **void GetRecentFields()** After a call to GetRecentFields() you must read the serial port yourself as the internal buffer of this Class cannot handle the possible large output. It can be over 100 bytes long lines!
- **void setOutputFields(uint16_t fields)** Sets the fields in the output stream as a 16 bit mask. See table below.
- **void clearOutputFields()** clears all the fields.
- **uint16_t getOutputFields()** returns the 16 bit mask of set output fields.
- **bool inOutputFields(uint16_t field)** returns true if the field is set.
- **void getRecentFields()** After a call to getRecentFields() you must read the serial stream yourself.
The internal buffer of this Class cannot handle the possible large output. Lines can be over 100 bytes long!
The fields must be set as a bit mask, the order of the fields in the output is undetermined. So parse carefully.
The fields must be set as a bit mask, the order of the fields in the output is undetermined.
So one need to parse the output of the sensor carefully.
| Field | Value | Notes |
|:------------------|:-------|:------|
|:------------------|:-------|:---------|
| CZR_LIGHT | 0x2000 | |
| CZR_HUMIDITY | 0x1000 | |
| CZR_FILTLED | 0x0800 | |
@ -111,15 +129,33 @@ The fields must be set as a bit mask, the order of the fields in the output is u
Read datasheet Page 11-12 about the addresses and their meaning.
Use with care.
- **void SetEEPROM(uint8_t address, uint8_t value)**
- **uint8_t GetEEPROM(uint8_t address)**
In 0.3.0 the EEPROM function have been replaced by specific accessor
functions. Read datasheet for the details.
- **void setAutoCalibrationPreload(uint16_t value)**
- **uint16_t getAutoCalibrationPreload()**
- **void setAutoCalibrationInterval(uint16_t value)**
- **uint16_t getAutoCalibrationInterval()**
- **void setAutoCalibrationOn()**
- **void setAutoCalibrationOff()**
- **bool getAutoCalibration()**
- **void setAutoCalibrationBackgroundConcentration(uint16_t value)**
- **uint16_t getAutoCalibrationBackgroundConcentration()**
- **void setAmbientConcentration(uint16_t value)**
- **uint16_t getAmbientConcentration()**
- **void setBufferClearTime(uint16_t value)**
- **uint16_t getBufferClearTime()**
#### EEPROM addresses used by above functions.
Read datasheet for the details.
| Name | Address | Default | Notes |
|:---------|:-------:|:-------:|:------|
| AHHI | 0x00 | | reserved |
| ANLO | 0x01 | | reserved |
| ANSOURCE | 0x02 | | reserved |
|:---------|:-------:|:-------:|:---------|
| AHHI | 0x00 | ? | reserved |
| ANLO | 0x01 | ? | reserved |
| ANSOURCE | 0x02 | ? | reserved |
| ACINITHI | 0x03 | 87 | |
| ACINITLO | 0x04 | 192 | |
| ACHI | 0x05 | 94 | |
@ -133,10 +169,24 @@ Use with care.
| BCLO | 0x0D | 8 | |
### Misc
### Miscellaneous
- **void GetVersionSerial()** requests version over serial. The user should read (and parse) the serial output as it can become large. Also the user must reset the operating mode either to **CZR_POLLING** or **CZR_STREAMING**
- **void GetConfiguration()** requests configuration over serial. The user should read (and parse) the serial output as it can become large. Also the user must reset the operating mode either to **CZR_POLLING** or **CZR_STREAMING**
- **void getVersionSerial()** requests version over serial.
The user should read (and parse) the serial output as it can become large.
Also the user must reset the operating mode either to **CZR_POLLING** or **CZR_STREAMING**
- **void getConfiguration()** requests configuration over serial.
The user should read (and parse) the serial output as it can become large.
Also the user must reset the operating mode either to **CZR_POLLING** or **CZR_STREAMING**
## Future
- test test test test and ...
- add a **setEEPROMFactoryDefault()**?
- example two Cozir sensors
- example Cozir with I2C display?
- build a Arduino COZIR simulator for testing.
- Cozir I2C class for newer generation ~ same interface
## Operation

View File

@ -1,16 +1,22 @@
//
// FILE: Cozir.cpp
// AUTHOR: DirtGambit & Rob Tillaart
// VERSION: 0.2.6
// VERSION: 0.3.0
// PURPOSE: library for COZIR range of sensors for Arduino
// Polling Mode
// URL: https://github.com/RobTillaart/Cozir
// http://forum.arduino.cc/index.php?topic=91467.0
//
// HISTORY:
// 0.3.0 2021-08-08 Major update - breaks interface (names mainly)
// add isInitialized(), add getOperatingMode(),
// add getOutputFields(), add inOutputFields(),
// add kelvin(), add EEPROM functions
// class methods camelCase
// extend unit tests
// 0.2.6 2021-01-31 fix #4 use Mode0 for versions and configuration
// 0.2.5 2020-12-26 fix software Serial + version number (oops)
// 0.2.2 2020-12-17 add arduino-ci + unit tests
// 0.2.2 2020-12-17 add Arduino-CI + unit tests
// 0.2.1 2020-06-05 fix library.json
// 0.2.0 2020-03-30 some refactor and own repo
// 0.1.06 added support for HardwareSerial for MEGA (Rob T)
@ -28,20 +34,52 @@
#include "cozir.h"
#define CZR_INIT_DELAY 1200
#define CZR_REQUEST_TIMEOUT 200
// EEPROM ADRESSES
// P 11-12 manual
// Name Address Default value/ notes
#define CZR_AHHI 0x00 // reserved
#define CZR_ANLO 0x01 // reserved
#define CZR_ANSOURCE 0x02 // reserved
#define CZR_ACINITHI 0x03 // 87
#define CZR_ACINITLO 0x04 // 192
#define CZR_ACHI 0x05 // 94
#define CZR_ACLO 0x06 // 128
#define CZR_ACONOFF 0x07 // 0
#define CZR_ACPPMHI 0x08 // 1
#define CZR_ACPPMLO 0x09 // 194
#define CZR_AMBHI 0x0A // 1
#define CZR_AMBLO 0x0B // 194
#define CZR_BCHI 0x0C // 0
#define CZR_BCLO 0x0D // 8
COZIR::COZIR(Stream * str)
{
ser = str;
buffer[0] = '\0';
_ser = str;
_buffer[0] = '\0';
}
void COZIR::init()
{
// overide default streaming (takes too much performance)
SetOperatingMode(CZR_POLLING);
// delay for initialization TODO should be timestamp based
// with an isInitialized function. Non blocking.
delay(1200);
// override default streaming (takes too much performance)
setOperatingMode(CZR_POLLING);
_initTimeStamp = millis();
// delay for initialization is kept until next major release.
// timestamp + isInitialized() is prepared.
// users can comment next line.
delay(CZR_INIT_DELAY);
}
bool COZIR::isInitialized()
{
return (millis() - _initTimeStamp) > CZR_INIT_DELAY;
}
@ -53,10 +91,11 @@ void COZIR::init()
// CZR_POLLING and CZR_STREAMING use an equally amount
// of power as both sample continuously...
//
void COZIR::SetOperatingMode(uint8_t mode)
void COZIR::setOperatingMode(uint8_t mode)
{
sprintf(buffer, "K %u", mode);
Command(buffer);
_operatingMode = mode;
sprintf(_buffer, "K %u", mode);
_command(_buffer);
}
@ -64,39 +103,40 @@ void COZIR::SetOperatingMode(uint8_t mode)
//
// POLLING MODE
//
// you need to set the polling mode explicitely before
// you need to set the polling mode explicitly before
// using these functions. SetOperatingMode(CZR_POLLING);
// this is the default behaviour of this Class but
// not of the sensor!!
//
float COZIR::Celsius()
float COZIR::celsius()
{
uint16_t rv = Request("T");
uint16_t rv = _request("T");
return 0.1 * (rv - 1000.0); // P17 negative values
}
float COZIR::Humidity()
float COZIR::humidity()
{
return 0.1 * Request("H");
return 0.1 * _request("H");
}
// TODO UNITS UNKNOWN lux??
float COZIR::Light()
// UNITS UNKNOWN lux??
float COZIR::light()
{
return 1.0 * Request("L");
return 1.0 * _request("L");
}
uint32_t COZIR::CO2()
{
return Request("Z");
return _request("Z");
}
uint16_t COZIR::getPPMFactor()
{
_ppmFactor = Request(".");
_ppmFactor = _request(".");
return _ppmFactor;
}
@ -107,61 +147,61 @@ uint16_t COZIR::getPPMFactor()
// a reading of v1 will be reported as v2
// sort of mapping
// check datasheet for detailed description
uint16_t COZIR::FineTuneZeroPoint(uint16_t v1, uint16_t v2)
uint16_t COZIR::fineTuneZeroPoint(uint16_t v1, uint16_t v2)
{
sprintf(buffer, "F %u %u", v1, v2);
return Request(buffer);
sprintf(_buffer, "F %u %u", v1, v2);
return _request(_buffer);
}
// mostly the default calibrator
uint16_t COZIR::CalibrateFreshAir()
uint16_t COZIR::calibrateFreshAir()
{
return Request("G");
return _request("G");
}
uint16_t COZIR::CalibrateNitrogen()
uint16_t COZIR::calibrateNitrogen()
{
return Request("U");
return _request("U");
}
uint16_t COZIR::CalibrateKnownGas(uint16_t value)
uint16_t COZIR::calibrateKnownGas(uint16_t value)
{
sprintf(buffer, "X %u", value);
return Request(buffer);
sprintf(_buffer, "X %u", value);
return _request(_buffer);
}
//uint16_t COZIR::CalibrateManual(uint16_t value)
//uint16_t COZIR::calibrateManual(uint16_t value)
//{
//sprintf(buffer, "u %u", value);
//return Request(buffer);
//sprintf(_buffer, "u %u", value);
//return _request(_buffer);
//}
//uint16_t COZIR::SetSpanCalibrate(uint16_t value)
//uint16_t COZIR::setSpanCalibrate(uint16_t value)
//{
//sprintf(buffer, "S %u", value);
//return Request(buffer);
//sprintf(_buffer, "S %u", value);
//return _request(_buffer);
//}
//uint16_t COZIR::GetSpanCalibrate()
//uint16_t COZIR::getSpanCalibrate()
//{
// return Request("s");
// return _request("s");
//}
void COZIR::SetDigiFilter(uint8_t value)
void COZIR::setDigiFilter(uint8_t value)
{
sprintf(buffer, "A %u", value);
Command(buffer);
sprintf(_buffer, "A %u", value);
_command(_buffer);
}
uint8_t COZIR::GetDigiFilter()
uint8_t COZIR::getDigiFilter()
{
return Request("a");
return _request("a");
}
@ -172,15 +212,22 @@ uint8_t COZIR::GetDigiFilter()
// output fields should be OR-ed
// e.g. SetOutputFields(CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2);
//
// you need to set the STREAMING mode explicitely
// you need to set the STREAMING mode explicitly
// SetOperatingMode(CZR_STREAMING);
//
// in STREAMING mode you must parse the output of serial yourself
//
void COZIR::SetOutputFields(uint16_t fields)
void COZIR::setOutputFields(uint16_t fields)
{
sprintf(buffer, "M %u", fields);
Command(buffer);
_outputFields = fields;
sprintf(_buffer, "M %u", fields);
_command(_buffer);
}
bool COZIR::inOutputFields(uint16_t field)
{
return (_outputFields & field) == field;
}
@ -188,30 +235,96 @@ void COZIR::SetOutputFields(uint16_t fields)
// After a call to GetRecentFields() you must read the serial port yourself as
// the internal buffer of this Class cannot handle the possible large output.
// It can be over 100 bytes long lines!
void COZIR::GetRecentFields()
void COZIR::getRecentFields()
{
Command("Q");
_command("Q");
}
////////////////////////////////////////////////////////////
//
// EEPROM - USE WITH CARE
// EEPROM CALLS - USE WITH CARE
//
// SEE DATASHEET 7.2 EEPROM FOR DETAILS
//
void COZIR::SetEEPROM(uint8_t address, uint8_t value)
void COZIR::setAutoCalibrationPreload(uint16_t value)
{
if (address > BCLO) return;
sprintf(buffer, "P %u %u", address, value);
Command(buffer);
_setEEPROM2(CZR_ACINITHI, value);
}
uint16_t COZIR::getAutoCalibrationPreload()
{
return _getEEPROM2(CZR_ACINITHI);
}
void COZIR::setAutoCalibrationInterval(uint16_t value)
{
_setEEPROM2(CZR_ACHI, value);
}
uint16_t COZIR::getAutoCalibrationInterval()
{
return _getEEPROM2(CZR_ACHI);
}
void COZIR::setAutoCalibrationOn()
{
_setEEPROM(CZR_ACONOFF, 1);
}
void COZIR::setAutoCalibrationOff()
{
_setEEPROM(CZR_ACONOFF, 0);
}
bool COZIR::getAutoCalibration()
{
return _getEEPROM(CZR_ACONOFF);
}
void COZIR::setAutoCalibrationBackgroundConcentration(uint16_t value)
{
_setEEPROM2(CZR_ACPPMHI, value);
}
uint16_t COZIR::getAutoCalibrationBackgroundConcentration()
{
return _getEEPROM2(CZR_ACPPMHI);
}
void COZIR::setAmbientConcentration(uint16_t value)
{
_setEEPROM2(CZR_AMBHI, value);
}
uint16_t COZIR::getAmbientConcentration()
{
return _getEEPROM2(CZR_AMBHI);
}
void COZIR::setBufferClearTime(uint16_t value)
{
_setEEPROM2(CZR_BCHI, value);
}
uint16_t COZIR::getBufferClearTime()
{
return _getEEPROM2(CZR_BCHI);
}
uint8_t COZIR::GetEEPROM(uint8_t address)
/*
// TODO first verify if single functions work.
void COZIR::setEEPROMFactoryReset()
{
sprintf(buffer, "p %u", address);
return Request(buffer);
setAutoCalibrationPreload(0x57C0);
setAutoCalibrationInterval(0x8E80);
setAutoCalibrationOff();
setAutoCalibrationBackgroundConcentration(0x01C2);
setAmbientConcentration(0x01C2);
setBufferClearTime(0x0008);
}
*/
////////////////////////////////////////////////////////////
//
@ -224,19 +337,19 @@ uint8_t COZIR::GetEEPROM(uint8_t address)
// of information from the sensor (for example using the Y and * commands).
// In this mode, the sensor is stopped waiting for commands.
//
void COZIR::GetVersionSerial()
void COZIR::getVersionSerial()
{
// overide modes to prevent interference in output
SetOperatingMode(CZR_COMMAND);
Command("Y");
// override modes to prevent interference in output
setOperatingMode(CZR_COMMAND);
_command("Y");
}
void COZIR::GetConfiguration()
void COZIR::getConfiguration()
{
// overide modes to prevent interference in output
SetOperatingMode(CZR_COMMAND);
Command("*");
// override modes to prevent interference in output
setOperatingMode(CZR_COMMAND);
_command("*");
}
@ -244,35 +357,75 @@ void COZIR::GetConfiguration()
//
// PRIVATE
//
void COZIR::Command(const char* str)
void COZIR::_command(const char* str)
{
ser->print(str);
ser->print("\r\n");
_ser->print(str);
_ser->print("\r\n");
}
uint32_t COZIR::Request(const char* str)
uint32_t COZIR::_request(const char* str)
{
Command(str);
_command(str);
// read answer; there may be a 100ms delay!
// TODO: PROPER TIMEOUT CODE. - what is longest answer possible?
// yield()?
// output always stops with /r/n.
delay(200);
// start with empty buffer
// read the answer from serial.
// TODO: PROPER TIMEOUT CODE.
// - might be a big delay
// - what is longest answer possible?
uint8_t idx = 0;
while(ser->available())
uint32_t start = millis();
// while (millis() - start < CZR_REQUEST_TIMEOUT)
delay(CZR_REQUEST_TIMEOUT);
while (true)
{
buffer[idx++] = ser->read();
// delay(1);
if (_ser->available())
{
char c = _ser->read();
_buffer[idx++] = c;
_buffer[idx] = '\0';
if (c == '\n') break;
}
}
uint32_t rv = atol(&_buffer[2]);
if (idx > 2) return rv;
return 0;
}
buffer[idx] = '\0';
uint32_t rv = atol(&buffer[2]);
return rv;
void COZIR::_setEEPROM(uint8_t address, uint8_t value)
{
if (address > CZR_BCLO) return;
sprintf(_buffer, "P %u %u", address, value);
_command(_buffer);
}
uint8_t COZIR::_getEEPROM(uint8_t address)
{
sprintf(_buffer, "p %u", address);
return _request(_buffer);
}
void COZIR::_setEEPROM2(uint8_t address, uint16_t value)
{
if (address > CZR_BCLO) return;
sprintf(_buffer, "P %u %u", address, value >> 8);
_command(_buffer);
sprintf(_buffer, "P %u %u", address + 1, value & 0xFF);
_command(_buffer);
}
uint16_t COZIR::_getEEPROM2(uint8_t address)
{
sprintf(_buffer, "p %u", address);
uint16_t val = _request(_buffer) << 8;
sprintf(_buffer, "p %u", address + 1);
return val + _request(_buffer);
}
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: Cozir.h
// AUTHOR: DirtGambit & Rob Tillaart
// VERSION: 0.2.6
// VERSION: 0.3.0
// PURPOSE: library for COZIR range of sensors for Arduino
// Polling Mode
// URL: https://github.com/RobTillaart/Cozir
@ -11,9 +11,12 @@
// READ DATASHEET BEFORE USE OF THIS LIB !
//
#include "Arduino.h"
#define COZIR_LIB_VERSION (F("0.2.6"))
#define COZIR_LIB_VERSION (F("0.3.0"))
// OUTPUTFIELDS
// See datasheet for details.
@ -34,95 +37,126 @@
#define CZR_NONE 0x0001
// easy default setting for streaming
#define CZR_HTC (CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2)
// not in datasheet for debug only
#define CZR_ALL 0x3FFE
// OPERATING MODES
#define CZR_COMMAND 0x00
#define CZR_STREAMING 0x01
#define CZR_POLLING 0x02
// EEPROM ADRESSES
// P 11-12 manual - maybe some deserve a function?
// Name Address Default value/ notes
#define AHHI 0x00 // reserved
#define ANLO 0x01 // reserved
#define ANSOURCE 0x02 // reserved
#define ACINITHI 0x03 // 87
#define ACINITLO 0x04 // 192
#define ACHI 0x05 // 94
#define ACLO 0x06 // 128
#define ACONOFF 0x07 // 0
#define ACPPMHI 0x08 // 1
#define ACPPMLO 0x09 // 194
#define AMBHI 0x0A // 1
#define AMBLO 0x0B // 194
#define BCHI 0x0C // 0
#define BCLO 0x0D // 8
class COZIR
{
public:
COZIR(Stream *);
COZIR(Stream * str);
void init(); // sets operatingMode to CZR_POLLING
bool isInitialized();
// warning: CZR_STREAMING is experimental, minimal tested.
void SetOperatingMode(uint8_t mode);
void setOperatingMode(uint8_t mode);
uint8_t getOperatingMode() { return _operatingMode; };
float Celsius();
float Fahrenheit() { return (Celsius() * 1.8) + 32; };
float Humidity();
float Light();
float celsius();
float fahrenheit() { return (celsius() * 1.8) + 32; };
float kelvin() { return celsius() + 273.15; };
float humidity();
float light();
uint32_t CO2();
uint16_t getPPMFactor(); // P14 . command return 1, 10 or 100
// Callibration function, read datasheet before use
uint16_t FineTuneZeroPoint(uint16_t v1, uint16_t v2);
uint16_t CalibrateFreshAir();
uint16_t CalibrateNitrogen();
uint16_t CalibrateKnownGas(uint16_t value);
// Calibration function, read datasheet before use
uint16_t fineTuneZeroPoint(uint16_t v1, uint16_t v2);
uint16_t calibrateFreshAir();
uint16_t calibrateNitrogen();
uint16_t calibrateKnownGas(uint16_t value);
// WARNING: following 3 functions are NOT RECOMMENDED,
// read datasheet before use
// uint16_t CalibrateManual(uint16_t value);
// uint16_t SetSpanCalibrate(uint16_t value);
// uint16_t GetSpanCalibrate();
// uint16_t calibrateManual(uint16_t value);
// uint16_t setSpanCalibrate(uint16_t value);
// uint16_t getSpanCalibrate();
// DIGIFILTER, use with care, read datasheet before use
// 32 = default value = 32,
// 1 = fast (noisy)
// 255 = slow (smoothed)
// 0 = special. details see datasheet
void SetDigiFilter(uint8_t value);
uint8_t GetDigiFilter();
void setDigiFilter(uint8_t value);
uint8_t getDigiFilter();
// STREAMING MODE - needs testing...
void SetOutputFields(uint16_t fields);
void ClrOutputFields() { SetOutputFields(CZR_NONE); };
void setOutputFields(uint16_t fields);
uint16_t getOutputFields() { return _outputFields; };
bool inOutputFields(uint16_t field);
void clearOutputFields() { setOutputFields(CZR_NONE); };
// WARNING:
// After a call to GetRecentFields() you must read the serial port yourself as
// the internal buffer of this Class cannot handle the possible large output.
// It can be over 100 bytes long lines!
void GetRecentFields();
// Answers can be over 100 bytes long!
void getRecentFields();
// EEPROM
// TODO some specific wrappers? in the end it are only 6 different calls?
void SetEEPROM(uint8_t address, uint8_t value);
uint8_t GetEEPROM(uint8_t address);
void setAutoCalibrationPreload(uint16_t value);
uint16_t getAutoCalibrationPreload();
void setAutoCalibrationInterval(uint16_t value);
uint16_t getAutoCalibrationInterval();
void setAutoCalibrationOn();
void setAutoCalibrationOff();
bool getAutoCalibration();
void setAutoCalibrationBackgroundConcentration(uint16_t value);
uint16_t getAutoCalibrationBackgroundConcentration();
void setAmbientConcentration(uint16_t value);
uint16_t getAmbientConcentration();
void setBufferClearTime(uint16_t value);
uint16_t getBufferClearTime();
// TODO test EEPROM function first.
// void setEEPROMFactoryReset();
// META INFORMATION
void getVersionSerial();
void getConfiguration();
///////////////////////////////////////////////
//
// SEMI PRIVATE FOR UNIT TESTING THEM
//
void _setEEPROM(uint8_t address, uint8_t value);
uint8_t _getEEPROM(uint8_t address);
void _setEEPROM2(uint8_t address, uint16_t value);
uint16_t _getEEPROM2(uint8_t address);
void GetVersionSerial();
void GetConfiguration();
private:
Stream *ser;
char buffer[20];
Stream * _ser;
char _buffer[20];
uint32_t _initTimeStamp = 0;
uint16_t _ppmFactor = 1;
void Command(const char* str);
uint32_t Request(const char* str);
uint8_t _operatingMode = CZR_STREAMING;
uint16_t _outputFields = CZR_NONE;
void _command(const char* str);
uint32_t _request(const char* str);
};
// -- END OF FILE --

View File

@ -29,9 +29,9 @@ void setup()
void loop()
{
float t = czr.Celsius();
float f = czr.Fahrenheit();
float h = czr.Humidity();
float t = czr.celsius();
float f = czr.fahrenheit();
float h = czr.humidity();
uint32_t c = czr.CO2();
Serial.print("Celcius =\t"); Serial.println(t);

View File

@ -29,9 +29,9 @@ void setup()
void loop()
{
float t = czr.Celsius();
float f = czr.Fahrenheit();
float h = czr.Humidity();
float t = czr.celsius();
float f = czr.fahrenheit();
float h = czr.humidity();
uint32_t c = czr.CO2();
Serial.print("Celcius =\t"); Serial.println(t);

View File

@ -25,7 +25,7 @@ void setup()
Serial.println();
delay(100);
czr.GetVersionSerial();
czr.getVersionSerial();
delay(5);
while (Serial1.available())
{
@ -33,7 +33,7 @@ void setup()
}
delay(100);
czr.GetConfiguration();
czr.getConfiguration();
delay(5);
while (Serial1.available())
{
@ -42,14 +42,14 @@ void setup()
delay(1000);
// reset to polling again.
czr.SetOperatingMode(CZR_POLLING);
czr.setOperatingMode(CZR_POLLING);
}
void loop()
{
float t = czr.Celsius();
float f = czr.Fahrenheit();
float h = czr.Humidity();
float t = czr.celsius();
float f = czr.fahrenheit();
float h = czr.humidity();
uint32_t c = czr.CO2();
Serial.print("Celcius =\t"); Serial.println(t);

View File

@ -1,4 +1,4 @@
# Syntax Coloring Map For COZIR
# Syntax Colouring Map For COZIR
# Data types (KEYWORD1)
COZIR KEYWORD1
@ -6,26 +6,52 @@ COZIR KEYWORD1
# Methods and Functions (KEYWORD2)
init KEYWORD2
SetOperatingMode KEYWORD2
Celsius KEYWORD2
Fahrenheit KEYWORD2
Humidity KEYWORD2
Light KEYWORD2
setOperatingMode KEYWORD2
getOperatingMode KEYWORD2
celsius KEYWORD2
fahrenheit KEYWORD2
humidity KEYWORD2
light KEYWORD2
CO2 KEYWORD2
getPPMFactor KEYWORD2
FineTuneZeroPoint KEYWORD2
CalibrateFreshAir KEYWORD2
CalibrateNitrogen KEYWORD2
CalibrateKnownGas KEYWORD2
SetDigiFilter KEYWORD2
GetDigiFilter KEYWORD2
SetOutputFields KEYWORD2
ClrOutputFields KEYWORD2
GetRecentFields KEYWORD2
SetEEPROM KEYWORD2
GetEEPROM KEYWORD2
GetVersionSerial KEYWORD2
GetConfiguration KEYWORD2
fineTuneZeroPoint KEYWORD2
calibrateFreshAir KEYWORD2
calibrateNitrogen KEYWORD2
calibrateKnownGas KEYWORD2
setDigiFilter KEYWORD2
getDigiFilter KEYWORD2
setOutputFields KEYWORD2
getOutputFields KEYWORD2
inOutputFields KEYWORD2
clrOutputFields KEYWORD2
getRecentFields KEYWORD2
setAutoCalibrationPreload KEYWORD2
getAutoCalibrationPreload KEYWORD2
setAutoCalibrationInterval KEYWORD2
getAutoCalibrationInterval KEYWORD2
setAutoCalibrationOn KEYWORD2
setAutoCalibrationOff KEYWORD2
getAutoCalibration KEYWORD2
setAutoCalibrationBackgroundConcentration KEYWORD2
getAutoCalibrationBackgroundConcentration KEYWORD2
setAmbientConcentration KEYWORD2
getAmbientConcentration KEYWORD2
setBufferClearTime KEYWORD2
getBufferClearTime KEYWORD2
getVersionSerial KEYWORD2
getConfiguration KEYWORD2
# Constants (LITERAL1)

View File

@ -18,7 +18,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Cozir.git"
},
"version": "0.2.6",
"version": "0.3.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*"

View File

@ -1,5 +1,5 @@
name=Cozir
version=0.2.6
version=0.3.0
author=Rob Tillaart <rob.tillaart@gmail.com>, DirtGambit
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for COZIR range of CO2 sensors. Polling mode only.

View File

@ -68,6 +68,8 @@ unittest(test_software_serial)
fprintf(stderr, "COZIR.init()\n");
co.init();
assertEqual("K 2\r\n", state->digitalPin[transmitPin].toAscii(1, bigEndian));
delay(1300);
assertTrue(co.isInitialized());
}
@ -91,16 +93,16 @@ unittest(test_constructor)
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.GetVersionSerial()\n");
fprintf(stderr, "COZIR.getVersionSerial()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.GetVersionSerial();
co.getVersionSerial();
assertEqual("K 0\r\nY\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.GetConfiguration()\n");
fprintf(stderr, "COZIR.getConfiguration()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.GetConfiguration();
co.getConfiguration();
assertEqual("K 0\r\n*\r\n", state->serialPort[0].dataOut);
}
@ -115,25 +117,30 @@ unittest(test_setOperatingMode)
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.init();
// init() sets CZR_POLLING
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOperatingMode(), CZR_POLLING);
fprintf(stderr, "COZIR.SetOperatingMode(CZR_COMMAND)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetOperatingMode(CZR_COMMAND);
co.setOperatingMode(CZR_COMMAND);
assertEqual("K 0\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOperatingMode(), CZR_COMMAND);
fprintf(stderr, "COZIR.SetOperatingMode(CZR_STREAMING)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetOperatingMode(CZR_STREAMING);
co.setOperatingMode(CZR_STREAMING);
assertEqual("K 1\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOperatingMode(), CZR_STREAMING);
fprintf(stderr, "COZIR.SetOperatingMode(CZR_POLLING)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetOperatingMode(CZR_POLLING);
co.setOperatingMode(CZR_POLLING);
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOperatingMode(), CZR_POLLING);
}
@ -152,29 +159,29 @@ unittest(test_read_sensor)
fprintf(stderr, "COZIR.Celsius()\n");
state->serialPort[0].dataIn = "T 750\r\n"; // 1000 = 0°C
state->serialPort[0].dataOut = "";
float Celsius = co.Celsius();
float celsius = co.celsius();
assertEqual("T\r\n", state->serialPort[0].dataOut);
assertEqualFloat(-25.0, Celsius, 0.0001);
assertEqualFloat(-25.0, celsius, 0.0001);
state->serialPort[0].dataIn = "T 1257\r\n";
state->serialPort[0].dataOut = "";
Celsius = co.Celsius();
celsius = co.celsius();
assertEqual("T\r\n", state->serialPort[0].dataOut);
assertEqualFloat(25.7, Celsius, 0.0001);
assertEqualFloat(25.7, celsius, 0.0001);
fprintf(stderr, "COZIR.Humidity()\n");
fprintf(stderr, "COZIR.humidity()\n");
state->serialPort[0].dataIn = "H 627\r\n";
state->serialPort[0].dataOut = "";
float Humidity = co.Humidity();
float humidity = co.humidity();
assertEqual("H\r\n", state->serialPort[0].dataOut);
assertEqualFloat(62.7, Humidity, 0.0001);
assertEqualFloat(62.7, humidity, 0.0001);
fprintf(stderr, "COZIR.Light()\n");
fprintf(stderr, "COZIR.light()\n");
state->serialPort[0].dataIn = "L 189\r\n";
state->serialPort[0].dataOut = "";
float Light = co.Light();
float light = co.light();
assertEqual("L\r\n", state->serialPort[0].dataOut);
assertEqual(189, Light);
assertEqual(189, light);
fprintf(stderr, "COZIR.CO2()\n");
state->serialPort[0].dataIn = "Z 432\r\n";
@ -197,34 +204,34 @@ unittest(test_calibrate)
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.FineTuneZeroPoint(400, 382)\n");
fprintf(stderr, "COZIR.fineTuneZeroPoint(400, 382)\n");
state->serialPort[0].dataIn = "F 32950\r\n";
state->serialPort[0].dataOut = "";
uint16_t FineTuneZeroPoint = co.FineTuneZeroPoint(400, 382);
uint16_t fineTuneZeroPoint = co.fineTuneZeroPoint(400, 382);
assertEqual("F 400 382\r\n", state->serialPort[0].dataOut);
assertEqual(32950, FineTuneZeroPoint);
assertEqual(32950, fineTuneZeroPoint);
fprintf(stderr, "COZIR.CalibrateFreshAir()\n");
fprintf(stderr, "COZIR.calibrateFreshAir()\n");
state->serialPort[0].dataIn = "G 32950\r\n";
state->serialPort[0].dataOut = "";
uint16_t CalibrateFreshAir = co.CalibrateFreshAir();
uint16_t calibrateFreshAir = co.calibrateFreshAir();
assertEqual("G\r\n", state->serialPort[0].dataOut);
assertEqual(32950, CalibrateFreshAir);
assertEqual(32950, calibrateFreshAir);
fprintf(stderr, "COZIR.CalibrateNitrogen()\n");
fprintf(stderr, "COZIR.calibrateNitrogen()\n");
state->serialPort[0].dataIn = "U 32590\r\n";
state->serialPort[0].dataOut = "";
uint16_t CalibrateNitrogen = co.CalibrateNitrogen();
uint16_t calibrateNitrogen = co.calibrateNitrogen();
assertEqual("U\r\n", state->serialPort[0].dataOut);
assertEqual(32590, CalibrateNitrogen);
assertEqual(32590, calibrateNitrogen);
fprintf(stderr, "COZIR.CalibrateKnownGas(100)\n");
fprintf(stderr, "COZIR.calibrateKnownGas(100)\n");
state->serialPort[0].dataIn = "X 33012\r\n";
state->serialPort[0].dataOut = "";
uint16_t CalibrateKnownGas = co.CalibrateKnownGas(100);
uint16_t calibrateKnownGas = co.calibrateKnownGas(100);
assertEqual("X 100\r\n", state->serialPort[0].dataOut);
assertEqual(33012, CalibrateKnownGas);
assertEqual(33012, calibrateKnownGas);
}
@ -241,16 +248,16 @@ unittest(test_digi_filter)
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.SetDigiFilter(42)\n");
fprintf(stderr, "COZIR.setDigiFilter(42)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetDigiFilter(42);
co.setDigiFilter(42);
assertEqual("A 42\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.GetDigiFilter()\n");
fprintf(stderr, "COZIR.getDigiFilter()\n");
state->serialPort[0].dataIn = "a 42\r\n";
state->serialPort[0].dataOut = "";
uint8_t digifilter = co.GetDigiFilter();
uint8_t digifilter = co.getDigiFilter();
assertEqual("a\r\n", state->serialPort[0].dataOut);
assertEqual(42, digifilter);
}
@ -267,41 +274,53 @@ unittest(test_streaming_mode)
state->serialPort[0].dataOut = "";
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOutputFields(), CZR_NONE);
fprintf(stderr, "COZIR.SetOperatingMode(CZR_STREAMING)\n");
fprintf(stderr, "COZIR.setOperatingMode(CZR_STREAMING)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetOperatingMode(CZR_STREAMING);
co.setOperatingMode(CZR_STREAMING);
assertEqual("K 1\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.SetOutputFields(CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2)\n");
fprintf(stderr, "COZIR.setOutputFields(CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetOutputFields(CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2);
co.setOutputFields(CZR_HUMIDITY | CZR_RAWTEMP | CZR_RAWCO2);
assertEqual("M 4226\r\n", state->serialPort[0].dataOut);
assertEqual(co.getOutputFields(), CZR_HTC);
fprintf(stderr, "COZIR.GetRecentFields()\n");
fprintf(stderr, "COZIR.inOutputFields()\n");
assertTrue(co.inOutputFields(CZR_HUMIDITY));
assertTrue(co.inOutputFields(CZR_RAWTEMP));
assertTrue(co.inOutputFields(CZR_RAWCO2));
assertFalse(co.inOutputFields(CZR_LIGHT));
assertFalse(co.inOutputFields(~CZR_HTC));
fprintf(stderr, "COZIR.getRecentFields()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.GetRecentFields();
co.getRecentFields();
assertEqual("Q\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.ClrOutputFields()\n");
fprintf(stderr, "COZIR.clearOutputFields()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.ClrOutputFields();
co.clearOutputFields();
assertEqual("M 1\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.inOutputFields()\n");
assertTrue(co.inOutputFields(CZR_NONE));
assertFalse(co.inOutputFields(~CZR_NONE));
fprintf(stderr, "COZIR.GetRecentFields()\n");
fprintf(stderr, "COZIR.getRecentFields()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.GetRecentFields();
co.getRecentFields();
assertEqual("Q\r\n", state->serialPort[0].dataOut);
// USER MUST READ RETURNED DATA AS IT CAN BE QUITE A LOT.
}
unittest(test_eeprom)
unittest(test_eeprom_I)
{
GodmodeState* state = GODMODE();
@ -313,21 +332,125 @@ unittest(test_eeprom)
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.SetEEPROM(10, 42)\n");
// needs redo
fprintf(stderr, "COZIR._setEEPROM(10, 42)\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.SetEEPROM(10, 42);
co._setEEPROM(10, 42);
assertEqual("P 10 42\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.GetEEPROM(100)\n");
fprintf(stderr, "COZIR._getEEPROM(100)\n");
state->serialPort[0].dataIn = "p 42\r\n";
state->serialPort[0].dataOut = "";
uint8_t GetEEPROM = co.GetEEPROM(100);
uint8_t getEEPROM = co._getEEPROM(100);
assertEqual("p 100\r\n", state->serialPort[0].dataOut);
assertEqual(42, GetEEPROM);
assertEqual(42, getEEPROM);
}
unittest(test_eeprom_II)
{
GodmodeState* state = GODMODE();
COZIR co(&Serial);
fprintf(stderr, "COZIR.init()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.init();
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.setAutoCalibrationPreload()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAutoCalibrationPreload(123);
assertEqual("P 3 0\r\nP 4 123\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getAutoCalibrationPreload()\n");
state->serialPort[0].dataIn = "p 01\r\np 42\r\n";
state->serialPort[0].dataOut = "";
uint16_t ACP = co.getAutoCalibrationPreload();
assertEqual("p 3\r\np 4\r\n", state->serialPort[0].dataOut);
assertEqual(298, ACP);
fprintf(stderr, "COZIR.setAutoCalibrationInterval()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAutoCalibrationInterval(123);
assertEqual("P 5 0\r\nP 6 123\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getAutoCalibrationInterval()\n");
state->serialPort[0].dataIn = "p 04\r\np 01\r\n";
state->serialPort[0].dataOut = "";
uint16_t interval = co.getAutoCalibrationInterval();
assertEqual("p 5\r\np 6\r\n", state->serialPort[0].dataOut);
assertEqual(1025, interval);
fprintf(stderr, "COZIR.setAutoCalibrationOn()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAutoCalibrationOn();
assertEqual("P 7 1\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.setAutoCalibrationOff()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAutoCalibrationOff();
assertEqual("P 7 0\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getAutoCalibration()\n");
state->serialPort[0].dataIn = "p 01\r\n";
state->serialPort[0].dataOut = "";
uint8_t AC = co.getAutoCalibration();
assertEqual("p 7\r\n", state->serialPort[0].dataOut);
assertEqual(1, AC);
fprintf(stderr, "COZIR.setAutoCalibrationBackgroundConcentration()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAutoCalibrationBackgroundConcentration(524);
assertEqual("P 8 2\r\nP 9 12\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getAutoCalibrationBackgroundConcentration()\n");
state->serialPort[0].dataIn = "p 03\r\np 10\r\n";
state->serialPort[0].dataOut = "";
uint16_t ACBC = co.getAutoCalibrationBackgroundConcentration();
assertEqual("p 8\r\np 9\r\n", state->serialPort[0].dataOut);
assertEqual(778, ACBC);
fprintf(stderr, "COZIR.setAmbientConcentration()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setAmbientConcentration(1083);
assertEqual("P 10 4\r\nP 11 59\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getAmbientConcentration()\n");
state->serialPort[0].dataIn = "p 05\r\np 00\r\n";
state->serialPort[0].dataOut = "";
uint16_t AMC = co.getAmbientConcentration();
assertEqual("p 10\r\np 11\r\n", state->serialPort[0].dataOut);
assertEqual(1280, AMC);
fprintf(stderr, "COZIR.setBufferClearTime()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataOut = "";
co.setBufferClearTime(83);
assertEqual("P 12 0\r\nP 13 83\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getBufferClearTime()\n");
state->serialPort[0].dataIn = "p 06\r\np 01\r\n";
state->serialPort[0].dataOut = "";
uint16_t BCT = co.getBufferClearTime();
assertEqual("p 12\r\np 13\r\n", state->serialPort[0].dataOut);
assertEqual(1537, BCT);
}
unittest(test_PPM)
{
@ -342,12 +465,14 @@ unittest(test_PPM)
assertEqual("K 2\r\n", state->serialPort[0].dataOut);
fprintf(stderr, "COZIR.getPPMFactor()\n");
state->serialPort[0].dataIn = "";
state->serialPort[0].dataIn = "p 01\r\n";
state->serialPort[0].dataOut = "";
co.getPPMFactor();
uint16_t ppm = co.getPPMFactor();
assertEqual(".\r\n", state->serialPort[0].dataOut);
}
assertEqual(1, ppm);
fprintf(stderr, "\n===========================================\n\n");
}
unittest_main()