hypweb.net
XOOPSマニア  最新情報のRSS(サイト全体)
[ 自宅サーバーWebRing |ID=54 前後5表示乱移動サイト一覧 ]

TOP » UsersWiki » calendar nao-pon/blog/2020.12
Archives
2003
1 2 3 4 5 6 7 8 9 10 11 12
2004
1 2 3 4 5 6 7 8 9 10 11 12
2005
1 2 3 4 5 6 7 8 9 10 11 12
2006
1 2 3 4 5 6 7 8 9 10 11 12
2007
1 2 3 4 5 6 7 8 9 10 11 12
2008
1 2 3 4 5 6 7 8 9 10 11 12
2009
1 2 3 4 5 6 7 8 9 10 11 12
2010
1 2 3 4 5 6 7 8 9 10 11 12
2011
1 2 3 4 5 6 7 8 9 10 11 12
2012
1 2 3 4 5 6 7 8 9 10 11 12
2013
1 2 3 4 5 6 7 8 9 10 11 12
2014
1 2 3 4 5 6 7 8 9 10 11 12
2015
1 2 3 4 5 6 7 8 9 10 11 12
2016
1 2 3 4 5 6 7 8 9 10 11 12
2017
1 2 3 4 5 6 7 8 9 10 11 12
2020
1 2 3 4 5 6 7 8 9 10 11 12
2021
1 2 3 4 5 6 7 8 9 10 11 12
2022
1 2 3 4 5 6 7 8 9 10 11 12
2023
1 2 3 4 5 6 7 8 9 10 11 12
<< 2020.12 >>
[nao-pon/blog]
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 16 17 18 19
20 21 22 23 24 25 26
27 29 30 31    
 
RSS of nao-pon/blog

KS0457 keyestudio CCS811 Carbon Dioxide Air Quality Sensor anchor.png

Page Top

Description anchor.png

Keyestudio CCS811 carbon dioxide, air quality sensor mainly uses the CCS811 chip. It is an ultra-low-power miniature digital gas sensor that can detect a wide range of volatile organic compounds (TVOCs), including equivalent carbon dioxide (eCO2) and metal oxide (MOX) levels. Equivalent carbon dioxide (eCO2) is measured in the range of 400 to 29206 ppm (parts per million), and various volatile organic compounds (TVOC) ranges from 0 to 32768ppb(parts per billion). 3mm diameter position hole on sensor contributes to fix on the other device.

Keyestudio CCS811 二酸化炭素、大気質センサーは主にCCS811チップを使用します。 これは、二酸化炭素相当値(eCO2)および金属酸化物(MOX)レベルを含む、広範囲の揮発性有機化合物(TVOC)を検出できる超低電力の小型デジタルガスセンサーです。 二酸化炭素相当値(eCO2)は400〜29206 ppm(parts per million)の範囲で測定され、さまざまな揮発性有機化合物(TVOC)は0〜32768ppb(parts per Billion)の範囲です。 センサーの直径3mmの取り付け穴は、他のデバイスへの固定に利用できます。

Page Top

echnical Parameters anchor.png

  • Working voltage: DC 5V
  • Working current: 30mA
  • Maximum power: 60mW
  • eCO2 measurement range: 400-29206 ppm
  • TVOC measurement range: 0 to 32768ppb
  • Interface: 7pin (2.54mm pitch)
  • Positioning hole diameter: 3mm
  • Dimensions: 30*20mm
  • Environmental attributes: ROHS
  • 動作電圧:DC 5V
  • 動作電流:30mA
  • 最大電力:60mW
  • eCO2測定範囲:400-29206 ppm
  • TVOC測定範囲:0〜32768ppb
  • インターフェース:7ピン(2.54mmピッチ)
  • 位置決め穴径:3mm
  • 寸法:30 * 20mm
  • 環境属性:ROHS
Page Top

PINOUTS anchor.png

GNDground
VCCInput power
SDAI2C data pin
SCLI2C clock pin
RSTReset pin: connect to ground, sensor will automatically reset.
WAKEWAKE pin should connect to ground to communicate with sensor conveniently.
WAKEピンは、センサーと簡単に通信できるようにアースに接続する必要があります。
INTThis is the interrupt output pin that detects when a new reading is read or the reading becomes too high or too low.
これは、新しい読み取り値が読み取られたとき、または読み取り値が高すぎたり低すぎたりしたときに検出する割り込み出力ピンです。
Page Top

Connection anchor.png

800px-0457片3.png

Page Top

Test Code anchor.png

NOTE:

  1. Place the corresponding file in the libraries folder of Arduino IDE before uploading the code.
  2. We recommend to use arduino 1.8.7 version , other version may be not compatible.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <CCS811.h>
 
/*
 * IIC address default 0x5A, the address becomes 0x5B if the ADDR_SEL is soldered.
 */
//CCS811 sensor(&Wire, /*IIC_ADDRESS=*/0x5A);
CCS811 sensor;
 
void setup(void)
{
    Serial.begin(115200);
    /*Wait for the chip to be initialized completely, and then exit*/
    while(sensor.begin() != 0){
        Serial.println("failed to init chip, please check if the chip connection is fine");
        delay(1000);
    }
    /**
     * @brief Set measurement cycle
     * @param cycle:in typedef enum{
     *                  eClosed,      //Idle (Measurements are disabled in this mode)
     *                  eCycle_1s,    //Constant power mode, IAQ measurement every second
     *                  eCycle_10s,   //Pulse heating mode IAQ measurement every 10 seconds
     *                  eCycle_60s,   //Low power pulse heating mode IAQ measurement every 60 seconds
     *                  eCycle_250ms  //Constant power mode, sensor measurement every 250ms
     *                  }eCycle_t;
     */
    sensor.setMeasCycle(sensor.eCycle_250ms);
}
void loop() {
  delay(1000);
    if(sensor.checkDataReady() == true){
        Serial.print("CO2: ");
        Serial.print(sensor.getCO2PPM());
        Serial.print("ppm, TVOC: ");
        Serial.print(sensor.getTVOCPPB());
        Serial.println("ppb");
        
    } else {
        Serial.println("Data is not ready!");
    }
    /*!
     * @brief Set baseline
     * @param get from getBaseline.ino
     */
    sensor.writeBaseLine(0x847B);
    //delay cannot be less than measurement cycle
    //delay(1000);
}
Page Top

Resource anchor.png

Download all the relevant info from the link:


 
RSS of nao-pon/blog

ESPHome の CCS811 コンポーネントで Baseline 値センサーを追加 anchor.png

二酸化炭素濃度を簡易的に測れるセンサー CCS811 は、起動時出来るだけ早く適切な値が得られるようにするには Baseline 値が結構重要。なので、Baseline値をセンサーとして観察したい。

それには、ESPHome のソースコードを変更する必要があるけど、custom_components ディレクトリを使用することで、簡単にハックできる。

早速、いじってみた。

fileccs811.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#pragma once
 
#include "esphome/core/component.h"
#include "esphome/core/preferences.h"
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
 
namespace esphome {
namespace ccs811 {
 
class CCS811Component : public PollingComponent, public i2c::I2CDevice {
 public:
  void set_co2(sensor::Sensor *co2) { co2_ = co2; }
  void set_tvoc(sensor::Sensor *tvoc) { tvoc_ = tvoc; }
  void set_baseline(uint16_t baseline) { baseline_ = baseline; }
  void set_cur_baseline(sensor::Sensor *cur_baseline) { cur_baseline_ = cur_baseline; }
  void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
  void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
 
  /// Setup the sensor and test for a connection.
  void setup() override;
  /// Schedule temperature+pressure readings.
  void update() override;
 
  void dump_config() override;
 
  float get_setup_priority() const override { return setup_priority::DATA; }
 
 protected:
  optional<uint8_t> read_status_() { return this->read_byte(0x00); }
  bool status_has_error_() { return this->read_status_().value_or(1) & 1; }
  bool status_app_is_valid_() { return this->read_status_().value_or(0) & (1 << 4); }
  bool status_has_data_() { return this->read_status_().value_or(0) & (1 << 3); }
  void send_env_data_();
 
  enum ErrorCode {
    UNKNOWN,
    COMMUNICAITON_FAILED,
    INVALID_ID,
    SENSOR_REPORTED_ERROR,
    APP_INVALID,
    APP_START_FAILED,
  } error_code_{UNKNOWN};
 
  sensor::Sensor *co2_{nullptr};
  sensor::Sensor *tvoc_{nullptr};
  sensor::Sensor *cur_baseline_{nullptr};
  optional<uint16_t> baseline_{};
  /// Input sensor for humidity reading.
  sensor::Sensor *humidity_{nullptr};
  /// Input sensor for temperature reading.
  sensor::Sensor *temperature_{nullptr};
};
 
}  // namespace ccs811
}  // namespace esphome
fileccs811.cpp
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
 
 
 
-
-
|
|
|
-
|
!
|
-
|
|
|
!
|
|
|
-
-
!
|
|
|
-
!
|
|
-
!
|
|
-
!
|
-
!
|
|
|
|
|
|
|
|
|
|
-
-
!
!
!
-
|
|
|
-
!
-
|
|
|
!
|
|
|
|
-
!
|
-
|
!
|
|
|
|
|
|
|
|
|
|
|
|
|
!
-
|
|
|
|
|
|
|
|
|
|
|
|
|
-
!
|
-
!
|
|
!
-
|
|
|
|
|
|
-
|
-
|
!
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
!
!
|
!
!
#include "ccs811.h"
#include "esphome/core/log.h"
 
namespace esphome {
namespace ccs811 {
 
static const char *TAG = "ccs811";
 
// based on
//  - https://cdn.sparkfun.com/datasheets/BreakoutBoards/CCS811_Programming_Guide.pdf
 
#define CHECK_TRUE(f, error_code) \
  if (!(f)) { \
    this->mark_failed(); \
    this->error_code_ = (error_code); \
    return; \
  }
 
#define CHECKED_IO(f) CHECK_TRUE(f, COMMUNICAITON_FAILED)
 
void CCS811Component::setup() {
  // page 9 programming guide - hwid is always 0x81
  uint8_t hw_id;
  CHECKED_IO(this->read_byte(0x20, &hw_id))
  CHECK_TRUE(hw_id == 0x81, INVALID_ID)
 
  // software reset, page 3 - allowed to fail
  this->write_bytes(0xFF, {0x11, 0xE5, 0x72, 0x8A});
  delay(5);
 
  // page 10, APP_START
  CHECK_TRUE(!this->status_has_error_(), SENSOR_REPORTED_ERROR)
  CHECK_TRUE(this->status_app_is_valid_(), APP_INVALID)
  CHECK_TRUE(this->write_bytes(0xF4, {}), APP_START_FAILED)
  // App setup, wait for it to load
  delay(1);
 
  // set MEAS_MODE (page 5)
  uint8_t meas_mode = 0;
  uint32_t interval = this->get_update_interval();
  if (interval <= 1000)
    meas_mode = 1 << 4;
  else if (interval <= 10000)
    meas_mode = 2 << 4;
  else
    meas_mode = 3 << 4;
 
  CHECKED_IO(this->write_byte(0x01, meas_mode))
 
  if (this->baseline_.has_value()) {
    // baseline available, write to sensor
    this->write_bytes(0x11, decode_uint16(*this->baseline_));
  }
}
void CCS811Component::update() {
  if (!this->status_has_data_())
    this->status_set_warning();
 
  // page 12 - alg result data
  auto alg_data = this->read_bytes<4>(0x02);
  if (!alg_data.has_value()) {
    ESP_LOGW(TAG, "Reading CCS811 data failed!");
    this->status_set_warning();
    return;
  }
  auto res = *alg_data;
  uint16_t co2 = encode_uint16(res[0], res[1]);
  uint16_t tvoc = encode_uint16(res[2], res[3]);
 
  // also print baseline
  auto baseline_data = this->read_bytes<2>(0x11);
  uint16_t baseline = 0;
  if (baseline_data.has_value()) {
    baseline = encode_uint16((*baseline_data)[0], (*baseline_data)[1]);
  }
 
  ESP_LOGD(TAG, "Got co2=%u ppm, tvoc=%u ppb, baseline=0x%04X", co2, tvoc, baseline);
 
  if (this->co2_ != nullptr)
    this->co2_->publish_state(co2);
  if (this->tvoc_ != nullptr)
    this->tvoc_->publish_state(tvoc);
  if (this->cur_baseline_ != nullptr)
    this->cur_baseline_->publish_state(baseline);
 
  this->status_clear_warning();
 
  this->send_env_data_();
}
void CCS811Component::send_env_data_() {
  if (this->humidity_ == nullptr && this->temperature_ == nullptr)
    return;
 
  float humidity = NAN;
  if (this->humidity_ != nullptr)
    humidity = this->humidity_->state;
  if (isnan(humidity) || humidity < 0 || humidity > 100)
    humidity = 50;
  float temperature = NAN;
  if (this->temperature_ != nullptr)
    temperature = this->temperature_->state;
  if (isnan(temperature) || temperature < -25 || temperature > 50)
    temperature = 25;
  // temperature has a 25° offset to allow negative temperatures
  temperature += 25;
 
  // only 0.5 fractions are supported (application note)
  auto hum_value = static_cast<uint8_t>(roundf(humidity * 2));
  auto temp_value = static_cast<uint8_t>(roundf(temperature * 2));
  this->write_bytes(0x05, {hum_value, 0x00, temp_value, 0x00});
}
void CCS811Component::dump_config() {
  ESP_LOGCONFIG(TAG, "CCS811");
  LOG_I2C_DEVICE(this)
  LOG_UPDATE_INTERVAL(this)
  LOG_SENSOR("  ", "CO2 Sensor", this->co2_)
  LOG_SENSOR("  ", "TVOC Sensor", this->tvoc_)
  LOG_SENSOR("  ", "Current Baseline", this->cur_baseline_)
  if (this->baseline_) {
    ESP_LOGCONFIG(TAG, "  Baseline: %04X", *this->baseline_);
  } else {
    ESP_LOGCONFIG(TAG, "  Baseline: NOT SET");
  }
  if (this->is_failed()) {
    switch (this->error_code_) {
      case COMMUNICAITON_FAILED:
        ESP_LOGW(TAG, "Communication failed! Is the sensor connected?");
        break;
      case INVALID_ID:
        ESP_LOGW(TAG, "Sensor reported an invalid ID. Is this a CCS811?");
        break;
      case SENSOR_REPORTED_ERROR:
        ESP_LOGW(TAG, "Sensor reported internal error");
        break;
      case APP_INVALID:
        ESP_LOGW(TAG, "Sensor reported invalid APP installed.");
        break;
      case APP_START_FAILED:
        ESP_LOGW(TAG, "Sensor reported APP start failed.");
        break;
      case UNKNOWN:
      default:
        ESP_LOGW(TAG, "Unknown setup error!");
        break;
    }
  }
}
 
}  // namespace ccs811
}  // namespace esphome
filesensor.py
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
from esphome.const import CONF_ID, ICON_RADIATOR, UNIT_PARTS_PER_MILLION, \
    UNIT_PARTS_PER_BILLION, CONF_TEMPERATURE, CONF_HUMIDITY, ICON_MOLECULE_CO2, ICON_SCALE
 
DEPENDENCIES = ['i2c']
 
ccs811_ns = cg.esphome_ns.namespace('ccs811')
CCS811Component = ccs811_ns.class_('CCS811Component', cg.PollingComponent, i2c.I2CDevice)
 
CONF_ECO2 = 'eco2'
CONF_TVOC = 'tvoc'
CONF_BASELINE = 'baseline'
CONF_CUR_BASELINE = 'cur_baseline'
 
CONFIG_SCHEMA = cv.Schema({
    cv.GenerateID(): cv.declare_id(CCS811Component),
    cv.Required(CONF_ECO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2,
                                                 0),
    cv.Required(CONF_TVOC): sensor.sensor_schema(UNIT_PARTS_PER_BILLION, ICON_RADIATOR, 0),
    cv.Required(CONF_CUR_BASELINE): sensor.sensor_schema('', ICON_SCALE, 0),
 
    cv.Optional(CONF_BASELINE): cv.hex_uint16_t,
    cv.Optional(CONF_TEMPERATURE): cv.use_id(sensor.Sensor),
    cv.Optional(CONF_HUMIDITY): cv.use_id(sensor.Sensor),
}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5A))
 
 
def to_code(config):
    var = cg.new_Pvariable(config[CONF_ID])
    yield cg.register_component(var, config)
    yield i2c.register_i2c_device(var, config)
 
    sens = yield sensor.new_sensor(config[CONF_ECO2])
    cg.add(var.set_co2(sens))
    sens = yield sensor.new_sensor(config[CONF_TVOC])
    cg.add(var.set_tvoc(sens))
    sens = yield sensor.new_sensor(config[CONF_CUR_BASELINE])
    cg.add(var.set_cur_baseline(sens))
 
    if CONF_BASELINE in config:
        cg.add(var.set_baseline(config[CONF_BASELINE]))
 
    if CONF_TEMPERATURE in config:
        sens = yield cg.get_variable(config[CONF_TEMPERATURE])
        cg.add(var.set_temperature(sens))
    if CONF_HUMIDITY in config:
        sens = yield cg.get_variable(config[CONF_HUMIDITY])
        cg.add(var.set_humidity(sens))


トップ 印刷に適した表示   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom Powered by xpWiki
このページのTopへ
メインメニュー
ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録
最近の更新
オンライン状況
676 人のユーザが現在オンラインです。 (12 人のユーザが UsersWiki を参照しています。)

登録ユーザ: 0
ゲスト: 676

もっと...
サイト情報