completely new from arends/development
This commit is contained in:
gemu2015 2018-07-23 16:27:15 +02:00
parent adc781b8fc
commit d21a04e872
13 changed files with 873 additions and 1 deletions

View File

@ -0,0 +1,27 @@
language: c
sudo: false
# Blacklist
branches:
except:
- gh-pages
env:
global:
- PRETTYNAME="Adafruit CCS811 Arduino Library"
# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile"
# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
install:
- arduino --install-library "Adafruit SSD1306","Adafruit GFX Library"
script:
- build_main_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View File

@ -0,0 +1,280 @@
#include "Adafruit_CCS811.h"
/**************************************************************************/
/*!
@brief Setups the I2C interface and hardware and checks for communication.
@param addr Optional I2C address the sensor can be found on. Default is 0x5A
@returns True if device is set up, false on any failure
*/
/**************************************************************************/
sint8_t Adafruit_CCS811::begin(uint8_t addr)
{
_i2caddr = addr;
_i2c_init();
SWReset();
delay(100);
//check that the HW id is correct
if(this->read8(CCS811_HW_ID) != CCS811_HW_ID_CODE) {
return -1;
}
//try to start the app
this->write(CCS811_BOOTLOADER_APP_START, NULL, 0);
delay(100);
//make sure there are no errors and we have entered application mode
if(checkError()) {
return -2;
}
if(!_status.FW_MODE) {
return -3;
}
disableInterrupt();
//default to read every second
setDriveMode(CCS811_DRIVE_MODE_1SEC);
return 0;
}
/**************************************************************************/
/*!
@brief sample rate of the sensor.
@param mode one of CCS811_DRIVE_MODE_IDLE, CCS811_DRIVE_MODE_1SEC, CCS811_DRIVE_MODE_10SEC, CCS811_DRIVE_MODE_60SEC, CCS811_DRIVE_MODE_250MS.
*/
void Adafruit_CCS811::setDriveMode(uint8_t mode)
{
_meas_mode.DRIVE_MODE = mode;
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
}
/**************************************************************************/
/*!
@brief enable the data ready interrupt pin on the device.
*/
/**************************************************************************/
void Adafruit_CCS811::enableInterrupt()
{
_meas_mode.INT_DATARDY = 1;
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
}
/**************************************************************************/
/*!
@brief disable the data ready interrupt pin on the device
*/
/**************************************************************************/
void Adafruit_CCS811::disableInterrupt()
{
_meas_mode.INT_DATARDY = 0;
this->write8(CCS811_MEAS_MODE, _meas_mode.get());
}
/**************************************************************************/
/*!
@brief checks if data is available to be read.
@returns True if data is ready, false otherwise.
*/
/**************************************************************************/
bool Adafruit_CCS811::available()
{
_status.set(read8(CCS811_STATUS));
if(!_status.DATA_READY)
return false;
else return true;
}
/**************************************************************************/
/*!
@brief read and store the sensor data. This data can be accessed with getTVOC() and geteCO2()
@returns 0 if no error, error code otherwise.
*/
/**************************************************************************/
uint8_t Adafruit_CCS811::readData()
{
if(!available())
return false;
else{
uint8_t buf[8];
this->read(CCS811_ALG_RESULT_DATA, buf, 8);
_eCO2 = ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]);
_TVOC = ((uint16_t)buf[2] << 8) | ((uint16_t)buf[3]);
if(_status.ERROR)
return buf[5];
else return 0;
}
}
/**************************************************************************/
/*!
@brief set the humidity and temperature compensation for the sensor.
@param humidity the humidity data as a percentage. For 55% humidity, pass in integer 55.
@param temperature the temperature in degrees C as a decimal number. For 25.5 degrees C, pass in 25.5
*/
/**************************************************************************/
void Adafruit_CCS811::setEnvironmentalData(uint8_t humidity, double temperature)
{
/* Humidity is stored as an unsigned 16 bits in 1/512%RH. The
default value is 50% = 0x64, 0x00. As an example 48.5%
humidity would be 0x61, 0x00.*/
/* Temperature is stored as an unsigned 16 bits integer in 1/512
degrees; there is an offset: 0 maps to -25°C. The default value is
25°C = 0x64, 0x00. As an example 23.5% temperature would be
0x61, 0x00.
The internal algorithm uses these values (or default values if
not set by the application) to compensate for changes in
relative humidity and ambient temperature.*/
uint8_t hum_perc = humidity << 1;
float fractional = modf(temperature, &temperature);
uint16_t temp_high = (((uint16_t)temperature + 25) << 9);
uint16_t temp_low = ((uint16_t)(fractional / 0.001953125) & 0x1FF);
uint16_t temp_conv = (temp_high | temp_low);
uint8_t buf[] = {hum_perc, 0x00,
(uint8_t)((temp_conv >> 8) & 0xFF), (uint8_t)(temp_conv & 0xFF)};
this->write(CCS811_ENV_DATA, buf, 4);
}
/**************************************************************************/
/*!
@brief calculate the temperature using the onboard NTC resistor.
@returns temperature as a double.
*/
/**************************************************************************/
double Adafruit_CCS811::calculateTemperature()
{
uint8_t buf[4];
this->read(CCS811_NTC, buf, 4);
uint32_t vref = ((uint32_t)buf[0] << 8) | buf[1];
uint32_t vntc = ((uint32_t)buf[2] << 8) | buf[3];
//from ams ccs811 app note
uint32_t rntc = vntc * CCS811_REF_RESISTOR / vref;
double ntc_temp;
ntc_temp = log((double)rntc / CCS811_REF_RESISTOR); // 1
ntc_temp /= 3380; // 2
ntc_temp += 1.0 / (25 + 273.15); // 3
ntc_temp = 1.0 / ntc_temp; // 4
ntc_temp -= 273.15; // 5
return ntc_temp - _tempOffset;
}
/**************************************************************************/
/*!
@brief set interrupt thresholds
@param low_med the level below which an interrupt will be triggered.
@param med_high the level above which the interrupt will ge triggered.
@param hysteresis optional histeresis level. Defaults to 50
*/
/**************************************************************************/
void Adafruit_CCS811::setThresholds(uint16_t low_med, uint16_t med_high, uint8_t hysteresis)
{
uint8_t buf[] = {(uint8_t)((low_med >> 8) & 0xF), (uint8_t)(low_med & 0xF),
(uint8_t)((med_high >> 8) & 0xF), (uint8_t)(med_high & 0xF), hysteresis};
this->write(CCS811_THRESHOLDS, buf, 5);
}
/**************************************************************************/
/*!
@brief trigger a software reset of the device
*/
/**************************************************************************/
void Adafruit_CCS811::SWReset()
{
//reset sequence from the datasheet
uint8_t seq[] = {0x11, 0xE5, 0x72, 0x8A};
this->write(CCS811_SW_RESET, seq, 4);
}
/**************************************************************************/
/*!
@brief read the status register and store any errors.
@returns the error bits from the status register of the device.
*/
/**************************************************************************/
bool Adafruit_CCS811::checkError()
{
_status.set(read8(CCS811_STATUS));
return _status.ERROR;
}
/**************************************************************************/
/*!
@brief write one byte of data to the specified register
@param reg the register to write to
@param value the value to write
*/
/**************************************************************************/
void Adafruit_CCS811::write8(byte reg, byte value)
{
this->write(reg, &value, 1);
}
/**************************************************************************/
/*!
@brief read one byte of data from the specified register
@param reg the register to read
@returns one byte of register data
*/
/**************************************************************************/
uint8_t Adafruit_CCS811::read8(byte reg)
{
uint8_t ret;
this->read(reg, &ret, 1);
return ret;
}
void Adafruit_CCS811::_i2c_init()
{
Wire.begin();
#ifdef ESP8266
Wire.setClockStretchLimit(1000);
#endif
}
void Adafruit_CCS811::read(uint8_t reg, uint8_t *buf, uint8_t num)
{
uint8_t value;
uint8_t pos = 0;
//on arduino we need to read in 32 byte chunks
while(pos < num){
uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos));
Wire.beginTransmission((uint8_t)_i2caddr);
Wire.write((uint8_t)reg + pos);
Wire.endTransmission();
Wire.requestFrom((uint8_t)_i2caddr, read_now);
for(int i=0; i<read_now; i++){
buf[pos] = Wire.read();
pos++;
}
}
}
void Adafruit_CCS811::write(uint8_t reg, uint8_t *buf, uint8_t num)
{
Wire.beginTransmission((uint8_t)_i2caddr);
Wire.write((uint8_t)reg);
Wire.write((uint8_t *)buf, num);
Wire.endTransmission();
}

View File

@ -0,0 +1,231 @@
#ifndef LIB_ADAFRUIT_CCS811_H
#define LIB_ADAFRUIT_CCS811_H
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define CCS811_ADDRESS (0x5A)
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
enum
{
CCS811_STATUS = 0x00,
CCS811_MEAS_MODE = 0x01,
CCS811_ALG_RESULT_DATA = 0x02,
CCS811_RAW_DATA = 0x03,
CCS811_ENV_DATA = 0x05,
CCS811_NTC = 0x06,
CCS811_THRESHOLDS = 0x10,
CCS811_BASELINE = 0x11,
CCS811_HW_ID = 0x20,
CCS811_HW_VERSION = 0x21,
CCS811_FW_BOOT_VERSION = 0x23,
CCS811_FW_APP_VERSION = 0x24,
CCS811_ERROR_ID = 0xE0,
CCS811_SW_RESET = 0xFF,
};
//bootloader registers
enum
{
CCS811_BOOTLOADER_APP_ERASE = 0xF1,
CCS811_BOOTLOADER_APP_DATA = 0xF2,
CCS811_BOOTLOADER_APP_VERIFY = 0xF3,
CCS811_BOOTLOADER_APP_START = 0xF4
};
enum
{
CCS811_DRIVE_MODE_IDLE = 0x00,
CCS811_DRIVE_MODE_1SEC = 0x01,
CCS811_DRIVE_MODE_10SEC = 0x02,
CCS811_DRIVE_MODE_60SEC = 0x03,
CCS811_DRIVE_MODE_250MS = 0x04,
};
/*=========================================================================*/
#define CCS811_HW_ID_CODE 0x81
#define CCS811_REF_RESISTOR 100000
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with CCS811 gas sensor chips
*/
/**************************************************************************/
class Adafruit_CCS811 {
public:
//constructors
Adafruit_CCS811(void) {};
~Adafruit_CCS811(void) {};
sint8_t begin(uint8_t addr = CCS811_ADDRESS);
void setEnvironmentalData(uint8_t humidity, double temperature);
//calculate temperature based on the NTC register
double calculateTemperature();
void setThresholds(uint16_t low_med, uint16_t med_high, uint8_t hysteresis = 50);
void SWReset();
void setDriveMode(uint8_t mode);
void enableInterrupt();
void disableInterrupt();
/**************************************************************************/
/*!
@brief returns the stored total volatile organic compounds measurement. This does does not read the sensor. To do so, call readData()
@returns TVOC measurement as 16 bit integer
*/
/**************************************************************************/
uint16_t getTVOC() { return _TVOC; }
/**************************************************************************/
/*!
@brief returns the stored estimated carbon dioxide measurement. This does does not read the sensor. To do so, call readData()
@returns eCO2 measurement as 16 bit integer
*/
/**************************************************************************/
uint16_t geteCO2() { return _eCO2; }
/**************************************************************************/
/*!
@brief set the temperature compensation offset for the device. This is needed to offset errors in NTC measurements.
@param offset the offset to be added to temperature measurements.
*/
/**************************************************************************/
void setTempOffset(float offset) { _tempOffset = offset; }
//check if data is available to be read
bool available();
uint8_t readData();
bool checkError();
private:
uint8_t _i2caddr;
float _tempOffset;
uint16_t _TVOC;
uint16_t _eCO2;
void write8(byte reg, byte value);
void write16(byte reg, uint16_t value);
uint8_t read8(byte reg);
void read(uint8_t reg, uint8_t *buf, uint8_t num);
void write(uint8_t reg, uint8_t *buf, uint8_t num);
void _i2c_init();
/*=========================================================================
REGISTER BITFIELDS
-----------------------------------------------------------------------*/
// The status register
struct status {
/* 0: no error
* 1: error has occurred
*/
uint8_t ERROR: 1;
// reserved : 2
/* 0: no samples are ready
* 1: samples are ready
*/
uint8_t DATA_READY: 1;
uint8_t APP_VALID: 1;
// reserved : 2
/* 0: boot mode, new firmware can be loaded
* 1: application mode, can take measurements
*/
uint8_t FW_MODE: 1;
void set(uint8_t data){
ERROR = data & 0x01;
DATA_READY = (data >> 3) & 0x01;
APP_VALID = (data >> 4) & 0x01;
FW_MODE = (data >> 7) & 0x01;
}
};
status _status;
//measurement and conditions register
struct meas_mode {
// reserved : 2
/* 0: interrupt mode operates normally
* 1: Interrupt mode (if enabled) only asserts the nINT signal (driven low) if the new
ALG_RESULT_DATA crosses one of the thresholds set in the THRESHOLDS register
by more than the hysteresis value (also in the THRESHOLDS register)
*/
uint8_t INT_THRESH: 1;
/* 0: int disabled
* 1: The nINT signal is asserted (driven low) when a new sample is ready in
ALG_RESULT_DATA. The nINT signal will stop being driven low when
ALG_RESULT_DATA is read on the I²C interface.
*/
uint8_t INT_DATARDY: 1;
uint8_t DRIVE_MODE: 3;
uint8_t get(){
return (INT_THRESH << 2) | (INT_DATARDY << 3) | (DRIVE_MODE << 4);
}
};
meas_mode _meas_mode;
struct error_id {
/* The CCS811 received an I²C write request addressed to this station but with
invalid register address ID */
uint8_t WRITE_REG_INVALID: 1;
/* The CCS811 received an I²C read request to a mailbox ID that is invalid */
uint8_t READ_REG_INVALID: 1;
/* The CCS811 received an I²C request to write an unsupported mode to
MEAS_MODE */
uint8_t MEASMODE_INVALID: 1;
/* The sensor resistance measurement has reached or exceeded the maximum
range */
uint8_t MAX_RESISTANCE: 1;
/* The Heater current in the CCS811 is not in range */
uint8_t HEATER_FAULT: 1;
/* The Heater voltage is not being applied correctly */
uint8_t HEATER_SUPPLY: 1;
void set(uint8_t data){
WRITE_REG_INVALID = data & 0x01;
READ_REG_INVALID = (data & 0x02) >> 1;
MEASMODE_INVALID = (data & 0x04) >> 2;
MAX_RESISTANCE = (data & 0x08) >> 3;
HEATER_FAULT = (data & 0x10) >> 4;
HEATER_SUPPLY = (data & 0x20) >> 5;
}
};
error_id _error_id;
/*=========================================================================*/
};
#endif

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,13 @@
# Adafruit CCS811 Library [![Build Status](https://travis-ci.org/adafruit/Adafruit_CCS811.svg?branch=master)](https://travis-ci.org/adafruit/Adafruit_CCS811)
<img src="https://cdn-shop.adafruit.com/970x728/3566-00.jpg" height="300"/>
This is a library for the Adafruit CCS811 gas sensor breakout board:
* https://www.adafruit.com/product/3566
Check out the links above for our tutorials and wiring diagrams. This chip uses I2C to communicate
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Dean Miller for Adafruit Industries.
MIT license, all text above must be included in any redistribution

View File

@ -0,0 +1,80 @@
/* This demo shows how to display the CCS811 readings on an Adafruit I2C OLED.
* (We used a Feather + OLED FeatherWing)
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
Adafruit_SSD1306 display = Adafruit_SSD1306();
void setup() {
Serial.begin(115200);
if(!ccs.begin()){
Serial.println("Failed to start sensor! Please check your wiring.");
while(1);
}
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32)
// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.display();
delay(500);
// Clear the buffer.
display.clearDisplay();
display.display();
//calibrate temperature sensor
while(!ccs.available());
float temp = ccs.calculateTemperature();
ccs.setTempOffset(temp - 25.0);
Serial.println("IO test");
// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
}
void loop() {
display.setCursor(0,0);
if(ccs.available()){
display.clearDisplay();
float temp = ccs.calculateTemperature();
if(!ccs.readData()){
display.print("eCO2: ");
Serial.print("eCO2: ");
float eCO2 = ccs.geteCO2();
display.print(eCO2);
Serial.print(eCO2);
display.print(" ppm\nTVOC: ");
Serial.print(" ppm, TVOC: ");
float TVOC = ccs.getTVOC();
display.print(TVOC);
Serial.print(TVOC);
Serial.print(" ppb Temp:");
display.print(" ppb\nTemp: ");
Serial.println(temp);
display.println(temp);
display.display();
}
else{
Serial.println("ERROR!");
while(1);
}
}
delay(500);
}

View File

@ -0,0 +1,56 @@
/***************************************************************************
This is a library for the CCS811 air
This sketch reads the sensor
Designed specifically to work with the Adafruit CCS811 breakout
----> http://www.adafruit.com/products/3566
These sensors use I2C to communicate. The device's I2C address is 0x5A
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Dean Miller for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
void setup() {
Serial.begin(9600);
Serial.println("CCS811 test");
if(!ccs.begin()){
Serial.println("Failed to start sensor! Please check your wiring.");
while(1);
}
//calibrate temperature sensor
while(!ccs.available());
float temp = ccs.calculateTemperature();
ccs.setTempOffset(temp - 25.0);
}
void loop() {
if(ccs.available()){
float temp = ccs.calculateTemperature();
if(!ccs.readData()){
Serial.print("CO2: ");
Serial.print(ccs.geteCO2());
Serial.print("ppm, TVOC: ");
Serial.print(ccs.getTVOC());
Serial.print("ppb Temp:");
Serial.println(temp);
}
else{
Serial.println("ERROR!");
while(1);
}
}
delay(500);
}

View File

@ -0,0 +1,9 @@
name=Adafruit CCS811 Library
version=1.0.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for the Adafruit CCS811 I2C gas sensor breakout.
paragraph=This is a library for the Adafruit CCS811 I2C gas sensor breakou.
category=Sensors
url=https://github.com/adafruit/Adafruit_CCS811
architectures=*

5
sonoff/sonoff.ino Normal file → Executable file
View File

@ -198,6 +198,11 @@ char log_data[LOGSZ]; // Logging
char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer
String backlog[MAX_BACKLOG]; // Command backlog
#ifdef USE_CCS811
uint8_t glob_humidity=0;
sint16_t glob_temperature=-9999;
#endif
/********************************************************************************************/
char* Format(char* output, const char* input, int size)

4
sonoff/sonoff_post.h Normal file → Executable file
View File

@ -58,6 +58,9 @@ void KNX_CB_Action(message_t const &msg, void *arg);
* Provide an image with all supported sensors enabled
\*********************************************************************************************/
#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code)
#ifdef USE_ALL_SENSORS
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
@ -71,6 +74,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#define USE_BMP // Add I2C code for BMP085/BMP180/BMP280/BME280 sensor (+4k code)
#define USE_BME680 // Add additional support for BME680 sensor using Bosch BME680 library (+4k code)
#define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code)
#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code)
#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code)
#define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code)
#define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code)

6
sonoff/xsns_09_bmp.ino Normal file → Executable file
View File

@ -495,6 +495,12 @@ void BmpShow(boolean json)
dtostrfd(bmp_gas_resistance, 2, gas_resistance);
#endif // USE_BME680
#ifdef USE_CCS811
glob_humidity=bmp_humidity;
glob_temperature=(bmp_temperature*4);
#endif
if (json) {
char json_humidity[40];
snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity);

11
sonoff/xsns_14_sht3x.ino Normal file → Executable file
View File

@ -101,9 +101,18 @@ void Sht3xShow(boolean json)
char types[11];
for (byte i = 0; i < sht3x_count; i++) {
if (Sht3xRead(t, h, sht3x_sensors[i].address)) {
#ifdef USE_CCS811
if (i==0) {
glob_humidity=h;
glob_temperature=(t*4);
}
#endif
dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX"
if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, types, temperature, humidity);
#ifdef USE_DOMOTICZ
@ -159,4 +168,4 @@ boolean Xsns14(byte function)
}
#endif // USE_SHT3X
#endif // USE_I2C
#endif // USE_I2C

131
sonoff/xsns_31_ccs811.ino Normal file
View File

@ -0,0 +1,131 @@
/*
xsns_31_cc811.ino - CCS811 gas and air quality sensor support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_CCS811
/*********************************************************************************************\
* SGP30 - Gas (TVOC - Total Volatile Organic Compounds) and Air Quality (CO2)
*
* Source: Gerhard Mutz and Adafruit
*
* I2C Address: 0x5A assumes ADDR connected to Gnd, Wake also must be grounded
\*********************************************************************************************/
#include "Adafruit_CCS811.h"
Adafruit_CCS811 ccs;
uint8_t CCS811_ready;
uint8_t CCS811_type;
uint16_t eCO2;
uint16_t TVOC;
uint8_t tcnt,ecnt;
/********************************************************************************************/
#define EVERYNSECONDS 5
void CCS811Update() // Perform every n second
{
tcnt+=1;
if (tcnt>=EVERYNSECONDS) {
tcnt=0;
CCS811_ready = 0;
if (!CCS811_type) {
sint8_t res=ccs.begin(CCS811_ADDRESS);
if (!res) {
CCS811_type = 1;
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "CCS811", 0x5A);
AddLog(LOG_LEVEL_DEBUG);
} else {
//snprintf_P(log_data, sizeof(log_data), "CCS811 init failed: %d",res);
//AddLog(LOG_LEVEL_DEBUG);
}
} else {
if (ccs.available()) {
if (!ccs.readData()){
TVOC=ccs.getTVOC();
eCO2=ccs.geteCO2();
CCS811_ready = 1;
if (glob_humidity!=0 && glob_temperature!=-9999) {
double gtmp=glob_temperature;
ccs.setEnvironmentalData(glob_humidity,gtmp/4);
}
ecnt=0;
}
} else {
// failed, count up
ecnt+=1;
if (ecnt>6) {
// after 30 seconds, restart
ccs.begin(CCS811_ADDRESS);
}
}
}
}
}
const char HTTP_SNS_CCS811[] PROGMEM = "%s"
"{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
"{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
void CCS811Show(boolean json)
{
if (CCS811_ready) {
if (json) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data,eCO2,TVOC);
#ifdef USE_DOMOTICZ
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2);
#endif // USE_DOMOTICZ
} else {
#ifdef USE_WEBSERVER
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_CCS811, mqtt_data, eCO2, TVOC);
#endif
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
#define XSNS_29
boolean Xsns29(byte function)
{
boolean result = false;
if (i2c_flg) {
switch (function) {
case FUNC_EVERY_SECOND:
CCS811Update();
break;
case FUNC_JSON_APPEND:
CCS811Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_APPEND:
CCS811Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_CCS811
#endif // USE_I2C