initial
This commit is contained in:
parent
7f066f338f
commit
5009ec0563
@ -3,30 +3,52 @@
|
||||
|
||||
#include "globals.h"
|
||||
#include <Wire.h>
|
||||
#include "bsec_integration.h"
|
||||
#include "irqhandler.h"
|
||||
|
||||
extern const uint8_t bsec_config_iaq[454];
|
||||
#include "bsec.h"
|
||||
|
||||
extern bmeStatus_t
|
||||
bme_status; // Make struct for storing gps data globally available
|
||||
extern TaskHandle_t BmeTask;
|
||||
|
||||
// --- Bosch BSEC library configuration ---
|
||||
// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days
|
||||
// calibration. Change this const if not applicable for your application (see
|
||||
// BME680 datasheet)
|
||||
const uint8_t bsec_config_iaq[454] = {
|
||||
1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0,
|
||||
0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0,
|
||||
64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64,
|
||||
49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0,
|
||||
0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0,
|
||||
0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10,
|
||||
215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9,
|
||||
0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27,
|
||||
156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97,
|
||||
64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121,
|
||||
71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48,
|
||||
117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4,
|
||||
144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48,
|
||||
117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0,
|
||||
100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48,
|
||||
117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117,
|
||||
100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44,
|
||||
1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1,
|
||||
44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
|
||||
7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
|
||||
112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112,
|
||||
23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255,
|
||||
255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0,
|
||||
239, 79, 0, 0};
|
||||
|
||||
int bme_init();
|
||||
void bme_loop(void *pvParameters);
|
||||
int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data,
|
||||
uint16_t len);
|
||||
int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data,
|
||||
uint16_t len);
|
||||
void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy,
|
||||
float temperature, float humidity, float pressure,
|
||||
float raw_temperature, float raw_humidity, float gas,
|
||||
bsec_library_return_t bsec_status, float static_iaq,
|
||||
float co2_equivalent, float breath_voc_equivalent);
|
||||
uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer);
|
||||
void state_save(const uint8_t *state_buffer, uint32_t length);
|
||||
uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer);
|
||||
void user_delay_ms(uint32_t period);
|
||||
int64_t get_timestamp_us();
|
||||
int checkIaqSensorStatus(void);
|
||||
|
||||
#endif
|
493
lib/Bosch-BSEC/bsec.cpp
Normal file
493
lib/Bosch-BSEC/bsec.cpp
Normal file
@ -0,0 +1,493 @@
|
||||
/**
|
||||
* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||
*
|
||||
* The information provided is believed to be accurate and reliable.
|
||||
* The copyright holder assumes no responsibility
|
||||
* for the consequences of use
|
||||
* of such information nor for any infringement of patents or
|
||||
* other rights of third parties which may result from its use.
|
||||
* No license is granted by implication or otherwise under any patent or
|
||||
* patent rights of the copyright holder.
|
||||
*
|
||||
* @file bsec.cpp
|
||||
* @date 31 Jan 2018
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bsec.h"
|
||||
|
||||
TwoWire* Bsec::wireObj = NULL;
|
||||
SPIClass* Bsec::spiObj = NULL;
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Bsec::Bsec()
|
||||
{
|
||||
nextCall = 0;
|
||||
version.major = 0;
|
||||
version.minor = 0;
|
||||
version.major_bugfix = 0;
|
||||
version.minor_bugfix = 0;
|
||||
millisOverflowCounter = 0;
|
||||
lastTime = 0;
|
||||
bme680Status = BME680_OK;
|
||||
outputTimestamp = 0;
|
||||
_tempOffset = 0.0f;
|
||||
status = BSEC_OK;
|
||||
zeroOutputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
*/
|
||||
void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask)
|
||||
{
|
||||
_bme680.dev_id = devId;
|
||||
_bme680.intf = intf;
|
||||
_bme680.read = read;
|
||||
_bme680.write = write;
|
||||
_bme680.delay_ms = idleTask;
|
||||
_bme680.amb_temp = 25;
|
||||
_bme680.power_mode = BME680_FORCED_MODE;
|
||||
|
||||
beginCommon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
*/
|
||||
void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c)
|
||||
{
|
||||
_bme680.dev_id = i2cAddr;
|
||||
_bme680.intf = BME680_I2C_INTF;
|
||||
_bme680.read = Bsec::i2cRead;
|
||||
_bme680.write = Bsec::i2cWrite;
|
||||
_bme680.delay_ms = Bsec::delay_ms;
|
||||
_bme680.amb_temp = 25;
|
||||
_bme680.power_mode = BME680_FORCED_MODE;
|
||||
|
||||
Bsec::wireObj = &i2c;
|
||||
Bsec::wireObj->begin();
|
||||
|
||||
beginCommon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
*/
|
||||
void Bsec::begin(uint8_t chipSelect, SPIClass &spi)
|
||||
{
|
||||
_bme680.dev_id = chipSelect;
|
||||
_bme680.intf = BME680_SPI_INTF;
|
||||
_bme680.read = Bsec::spiTransfer;
|
||||
_bme680.write = Bsec::spiTransfer;
|
||||
_bme680.delay_ms = Bsec::delay_ms;
|
||||
_bme680.amb_temp = 25;
|
||||
_bme680.power_mode = BME680_FORCED_MODE;
|
||||
|
||||
pinMode(chipSelect, OUTPUT);
|
||||
digitalWrite(chipSelect, HIGH);
|
||||
Bsec::spiObj = &spi;
|
||||
Bsec::spiObj->begin();
|
||||
|
||||
beginCommon();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common code for the begin function
|
||||
*/
|
||||
void Bsec::beginCommon(void)
|
||||
{
|
||||
status = bsec_init();
|
||||
|
||||
getVersion();
|
||||
|
||||
bme680Status = bme680_init(&_bme680);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function that sets the desired sensors and the sample rates
|
||||
*/
|
||||
void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate)
|
||||
{
|
||||
bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS],
|
||||
sensorSettings[BSEC_MAX_PHYSICAL_SENSOR];
|
||||
uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR;
|
||||
|
||||
for (uint8_t i = 0; i < nSensors; i++) {
|
||||
virtualSensors[nVirtualSensors].sensor_id = sensorList[i];
|
||||
virtualSensors[nVirtualSensors].sample_rate = sampleRate;
|
||||
nVirtualSensors++;
|
||||
}
|
||||
|
||||
status = bsec_update_subscription(virtualSensors, nVirtualSensors, sensorSettings, &nSensorSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback from the user to trigger reading of data from the BME680, process and store outputs
|
||||
*/
|
||||
bool Bsec::run(void)
|
||||
{
|
||||
bool newData = false;
|
||||
/* Check if the time has arrived to call do_steps() */
|
||||
int64_t callTimeMs = getTimeMs();
|
||||
|
||||
if (callTimeMs >= nextCall) {
|
||||
|
||||
bsec_bme_settings_t bme680Settings;
|
||||
|
||||
int64_t callTimeNs = callTimeMs * INT64_C(1000000);
|
||||
|
||||
status = bsec_sensor_control(callTimeNs, &bme680Settings);
|
||||
if (status < BSEC_OK)
|
||||
return false;
|
||||
|
||||
nextCall = bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms
|
||||
|
||||
bme680Status = setBme680Config(bme680Settings);
|
||||
if (bme680Status != BME680_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bme680Status = bme680_set_sensor_mode(&_bme680);
|
||||
if (bme680Status != BME680_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Wait for measurement to complete */
|
||||
uint16_t meas_dur = 0;
|
||||
|
||||
bme680_get_profile_dur(&meas_dur, &_bme680);
|
||||
delay_ms(meas_dur);
|
||||
|
||||
newData = readProcessData(callTimeNs, bme680Settings);
|
||||
}
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to get the state of the algorithm to save to non-volatile memory
|
||||
*/
|
||||
void Bsec::getState(uint8_t *state)
|
||||
{
|
||||
uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
|
||||
uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
|
||||
status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to set the state of the algorithm from non-volatile memory
|
||||
*/
|
||||
void Bsec::setState(uint8_t *state)
|
||||
{
|
||||
uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
|
||||
|
||||
status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to set the configuration of the algorithm from memory
|
||||
*/
|
||||
void Bsec::setConfig(const uint8_t *state)
|
||||
{
|
||||
uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE];
|
||||
|
||||
status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, workBuffer, sizeof(workBuffer));
|
||||
}
|
||||
|
||||
/* Private functions */
|
||||
|
||||
/**
|
||||
* @brief Get the version of the BSEC library
|
||||
*/
|
||||
void Bsec::getVersion(void)
|
||||
{
|
||||
bsec_get_version(&version);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from the BME680 and process it
|
||||
*/
|
||||
bool Bsec::readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings)
|
||||
{
|
||||
bme680Status = bme680_get_sensor_data(&_data, &_bme680);
|
||||
if (bme680Status != BME680_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas
|
||||
uint8_t nInputs = 0, nOutputs = 0;
|
||||
|
||||
if (_data.status & BME680_NEW_DATA_MSK) {
|
||||
if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) {
|
||||
inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE;
|
||||
inputs[nInputs].signal = _data.temperature;
|
||||
inputs[nInputs].time_stamp = currTimeNs;
|
||||
nInputs++;
|
||||
/* Temperature offset from the real temperature due to external heat sources */
|
||||
inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE;
|
||||
inputs[nInputs].signal = _tempOffset;
|
||||
inputs[nInputs].time_stamp = currTimeNs;
|
||||
nInputs++;
|
||||
}
|
||||
if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) {
|
||||
inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY;
|
||||
inputs[nInputs].signal = _data.humidity;
|
||||
inputs[nInputs].time_stamp = currTimeNs;
|
||||
nInputs++;
|
||||
}
|
||||
if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) {
|
||||
inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE;
|
||||
inputs[nInputs].signal = _data.pressure;
|
||||
inputs[nInputs].time_stamp = currTimeNs;
|
||||
nInputs++;
|
||||
}
|
||||
if (bme680Settings.process_data & BSEC_PROCESS_GAS) {
|
||||
inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR;
|
||||
inputs[nInputs].signal = _data.gas_resistance;
|
||||
inputs[nInputs].time_stamp = currTimeNs;
|
||||
nInputs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nInputs > 0) {
|
||||
nOutputs = BSEC_NUMBER_OUTPUTS;
|
||||
bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS];
|
||||
|
||||
status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs);
|
||||
if (status != BSEC_OK)
|
||||
return false;
|
||||
|
||||
zeroOutputs();
|
||||
|
||||
if (nOutputs > 0) {
|
||||
outputTimestamp = _outputs[0].time_stamp / 1000000; // Convert from ns to ms
|
||||
|
||||
for (uint8_t i = 0; i < nOutputs; i++) {
|
||||
switch (_outputs[i].sensor_id) {
|
||||
case BSEC_OUTPUT_IAQ:
|
||||
iaqEstimate = _outputs[i].signal;
|
||||
iaqAccuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
case BSEC_OUTPUT_STATIC_IAQ:
|
||||
staticIaq = _outputs[i].signal;
|
||||
staticIaqAccuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
case BSEC_OUTPUT_CO2_EQUIVALENT:
|
||||
co2Equivalent = _outputs[i].signal;
|
||||
co2Accuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
|
||||
breathVocEquivalent = _outputs[i].signal;
|
||||
breathVocAccuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_TEMPERATURE:
|
||||
rawTemperature = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_PRESSURE:
|
||||
pressure = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_HUMIDITY:
|
||||
rawHumidity = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_GAS:
|
||||
gasResistance = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_STABILIZATION_STATUS:
|
||||
stabStatus = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_RUN_IN_STATUS:
|
||||
runInStatus = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
|
||||
temperature = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
|
||||
humidity = _outputs[i].signal;
|
||||
break;
|
||||
case BSEC_OUTPUT_COMPENSATED_GAS:
|
||||
compGasValue = _outputs[i].signal;
|
||||
compGasAccuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
case BSEC_OUTPUT_GAS_PERCENTAGE:
|
||||
gasPercentage = _outputs[i].signal;
|
||||
gasPercentageAcccuracy = _outputs[i].accuracy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the BME680 sensor's configuration
|
||||
*/
|
||||
int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings)
|
||||
{
|
||||
_bme680.gas_sett.run_gas = bme680Settings.run_gas;
|
||||
_bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling;
|
||||
_bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling;
|
||||
_bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling;
|
||||
_bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature;
|
||||
_bme680.gas_sett.heatr_dur = bme680Settings.heating_duration;
|
||||
uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL
|
||||
| BME680_GAS_SENSOR_SEL;
|
||||
return bme680_set_sensor_settings(desired_settings, &_bme680);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to zero the outputs
|
||||
*/
|
||||
void Bsec::zeroOutputs(void)
|
||||
{
|
||||
temperature = 0.0f;
|
||||
pressure = 0.0f;
|
||||
humidity = 0.0f;
|
||||
gasResistance = 0.0f;
|
||||
rawTemperature = 0.0f;
|
||||
rawHumidity = 0.0f;
|
||||
stabStatus = 0.0f;
|
||||
runInStatus = 0.0f;
|
||||
iaqEstimate = 0.0f;
|
||||
iaqAccuracy = 0;
|
||||
staticIaq = 0.0f;
|
||||
staticIaqAccuracy = 0;
|
||||
co2Equivalent = 0.0f;
|
||||
co2Accuracy = 0;
|
||||
breathVocEquivalent = 0.0f;
|
||||
breathVocAccuracy = 0;
|
||||
compGasValue = 0.0f;
|
||||
compGasAccuracy = 0;
|
||||
gasPercentage = 0.0f;
|
||||
gasPercentageAcccuracy = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to calculate an int64_t timestamp in milliseconds
|
||||
*/
|
||||
int64_t Bsec::getTimeMs(void)
|
||||
{
|
||||
int64_t timeMs = millis();
|
||||
|
||||
if (lastTime > timeMs) { // An overflow occured
|
||||
lastTime = timeMs;
|
||||
millisOverflowCounter++;
|
||||
}
|
||||
|
||||
return timeMs + (millisOverflowCounter * 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Task that delays for a ms period of time
|
||||
*/
|
||||
void Bsec::delay_ms(uint32_t period)
|
||||
{
|
||||
// Wait for a period amount of ms
|
||||
// The system may simply idle, sleep or even perform background tasks
|
||||
delay(period);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Callback function for reading registers over I2C
|
||||
*/
|
||||
int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length)
|
||||
{
|
||||
uint16_t i;
|
||||
int8_t rslt = 0;
|
||||
if(Bsec::wireObj) {
|
||||
Bsec::wireObj->beginTransmission(devId);
|
||||
Bsec::wireObj->write(regAddr);
|
||||
rslt = Bsec::wireObj->endTransmission();
|
||||
Bsec::wireObj->requestFrom((int) devId, (int) length);
|
||||
for (i = 0; (i < length) && Bsec::wireObj->available(); i++) {
|
||||
regData[i] = Bsec::wireObj->read();
|
||||
}
|
||||
} else {
|
||||
rslt = -1;
|
||||
}
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function for writing registers over I2C
|
||||
*/
|
||||
int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length)
|
||||
{
|
||||
uint16_t i;
|
||||
int8_t rslt = 0;
|
||||
if(Bsec::wireObj) {
|
||||
Bsec::wireObj->beginTransmission(devId);
|
||||
Bsec::wireObj->write(regAddr);
|
||||
for (i = 0; i < length; i++) {
|
||||
Bsec::wireObj->write(regData[i]);
|
||||
}
|
||||
rslt = Bsec::wireObj->endTransmission();
|
||||
} else {
|
||||
rslt = -1;
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function for reading and writing registers over SPI
|
||||
*/
|
||||
int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length)
|
||||
{
|
||||
int8_t rslt = 0;
|
||||
if(Bsec::spiObj) {
|
||||
Bsec::spiObj->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz
|
||||
|
||||
digitalWrite(devId, LOW);
|
||||
|
||||
Bsec::spiObj->transfer(regAddr); // Write the register address, ignore the return
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
regData[i] = Bsec::spiObj->transfer(regData[i]);
|
||||
|
||||
digitalWrite(devId, HIGH);
|
||||
Bsec::spiObj->endTransaction();
|
||||
} else {
|
||||
rslt = -1;
|
||||
}
|
||||
|
||||
return rslt;;
|
||||
}
|
230
lib/Bosch-BSEC/bsec.h
Normal file
230
lib/Bosch-BSEC/bsec.h
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the copyright holder nor the names of the
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||
*
|
||||
* The information provided is believed to be accurate and reliable.
|
||||
* The copyright holder assumes no responsibility
|
||||
* for the consequences of use
|
||||
* of such information nor for any infringement of patents or
|
||||
* other rights of third parties which may result from its use.
|
||||
* No license is granted by implication or otherwise under any patent or
|
||||
* patent rights of the copyright holder.
|
||||
*
|
||||
* @file bsec.h
|
||||
* @date 31 Jan 2018
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BSEC_CLASS_H
|
||||
#define BSEC_CLASS_H
|
||||
|
||||
/* Includes */
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "SPI.h"
|
||||
#include "bsec_datatypes.h"
|
||||
#include "bsec_interface.h"
|
||||
#include "bme680.h"
|
||||
|
||||
/* BSEC class definition */
|
||||
class Bsec
|
||||
{
|
||||
public:
|
||||
/* Public variables */
|
||||
bsec_version_t version; // Stores the version of the BSEC algorithm
|
||||
int64_t nextCall; // Stores the time when the algorithm has to be called next in ms
|
||||
int8_t bme680Status; // Placeholder for the BME680 driver's error codes
|
||||
bsec_library_return_t status;
|
||||
float iaqEstimate, rawTemperature, pressure, rawHumidity, gasResistance, stabStatus, runInStatus, temperature, humidity,
|
||||
staticIaq, co2Equivalent, breathVocEquivalent, compGasValue, gasPercentage;
|
||||
uint8_t iaqAccuracy, staticIaqAccuracy, co2Accuracy, breathVocAccuracy, compGasAccuracy, gasPercentageAcccuracy;
|
||||
int64_t outputTimestamp; // Timestamp in ms of the output
|
||||
static TwoWire *wireObj;
|
||||
static SPIClass *spiObj;
|
||||
|
||||
/* Public APIs */
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Bsec();
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
* @param devId : Device identifier parameter for the read/write interface functions
|
||||
* @param intf : Physical communication interface
|
||||
* @param read : Pointer to the read function
|
||||
* @param write : Pointer to the write function
|
||||
* @param idleTask : Pointer to the idling task
|
||||
*/
|
||||
void begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask);
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
* @param i2cAddr : I2C address
|
||||
* @param i2c : Pointer to the TwoWire object
|
||||
*/
|
||||
void begin(uint8_t i2cAddr, TwoWire &i2c);
|
||||
|
||||
/**
|
||||
* @brief Function to initialize the BSEC library and the BME680 sensor
|
||||
* @param chipSelect : SPI chip select
|
||||
* @param spi : Pointer to the SPIClass object
|
||||
*/
|
||||
void begin(uint8_t chipSelect, SPIClass &spi);
|
||||
|
||||
/**
|
||||
* @brief Function that sets the desired sensors and the sample rates
|
||||
* @param sensorList : The list of output sensors
|
||||
* @param nSensors : Number of outputs requested
|
||||
* @param sampleRate : The sample rate of requested sensors
|
||||
*/
|
||||
void updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate = BSEC_SAMPLE_RATE_ULP);
|
||||
|
||||
/**
|
||||
* @brief Callback from the user to trigger reading of data from the BME680, process and store outputs
|
||||
* @return true if there are new outputs. false otherwise
|
||||
*/
|
||||
bool run(void);
|
||||
|
||||
/**
|
||||
* @brief Function to get the state of the algorithm to save to non-volatile memory
|
||||
* @param state : Pointer to a memory location that contains the state
|
||||
*/
|
||||
void getState(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief Function to set the state of the algorithm from non-volatile memory
|
||||
* @param state : Pointer to a memory location that contains the state
|
||||
*/
|
||||
void setState(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief Function to set the configuration of the algorithm from memory
|
||||
* @param state : Pointer to a memory location that contains the configuration
|
||||
*/
|
||||
void setConfig(const uint8_t *config);
|
||||
|
||||
/**
|
||||
* @brief Function to set the temperature offset
|
||||
* @param tempOffset : Temperature offset in degree Celsius
|
||||
*/
|
||||
void setTemperatureOffset(float tempOffset)
|
||||
{
|
||||
_tempOffset = tempOffset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function to calculate an int64_t timestamp in milliseconds
|
||||
*/
|
||||
int64_t getTimeMs(void);
|
||||
|
||||
/**
|
||||
* @brief Task that delays for a ms period of time
|
||||
* @param period : Period of time in ms
|
||||
*/
|
||||
static void delay_ms(uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief Callback function for reading registers over I2C
|
||||
* @param devId : Library agnostic parameter to identify the device to communicate with
|
||||
* @param regAddr : Register address
|
||||
* @param regData : Pointer to the array containing the data to be read
|
||||
* @param length : Length of the array of data
|
||||
* @return Zero for success, non-zero otherwise
|
||||
*/
|
||||
static int8_t i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Callback function for writing registers over I2C
|
||||
* @param devId : Library agnostic parameter to identify the device to communicate with
|
||||
* @param regAddr : Register address
|
||||
* @param regData : Pointer to the array containing the data to be written
|
||||
* @param length : Length of the array of data
|
||||
* @return Zero for success, non-zero otherwise
|
||||
*/
|
||||
static int8_t i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Callback function for reading and writing registers over SPI
|
||||
* @param devId : Library agnostic parameter to identify the device to communicate with
|
||||
* @param regAddr : Register address
|
||||
* @param regData : Pointer to the array containing the data to be read or written
|
||||
* @param length : Length of the array of data
|
||||
* @return Zero for success, non-zero otherwise
|
||||
*/
|
||||
static int8_t spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
|
||||
|
||||
private:
|
||||
/* Private variables */
|
||||
struct bme680_dev _bme680;
|
||||
struct bme680_field_data _data;
|
||||
float _tempOffset;
|
||||
// Global variables to help create a millisecond timestamp that doesn't overflow every 51 days.
|
||||
// If it overflows, it will have a negative value. Something that should never happen.
|
||||
uint32_t millisOverflowCounter;
|
||||
uint32_t lastTime;
|
||||
|
||||
/* Private APIs */
|
||||
/**
|
||||
* @brief Get the version of the BSEC library
|
||||
*/
|
||||
void getVersion(void);
|
||||
|
||||
/**
|
||||
* @brief Read data from the BME680 and process it
|
||||
* @param currTimeNs: Current time in ns
|
||||
* @param bme680Settings: BME680 sensor's settings
|
||||
* @return true if there are new outputs. false otherwise
|
||||
*/
|
||||
bool readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings);
|
||||
|
||||
/**
|
||||
* @brief Set the BME680 sensor's configuration
|
||||
* @param bme680Settings: Settings to configure the BME680
|
||||
* @return BME680 return code. BME680_OK for success, failure otherwise
|
||||
*/
|
||||
int8_t setBme680Config(bsec_bme_settings_t bme680Settings);
|
||||
|
||||
/**
|
||||
* @brief Common code for the begin function
|
||||
*/
|
||||
void beginCommon(void);
|
||||
|
||||
/**
|
||||
* @brief Function to zero the outputs
|
||||
*/
|
||||
void zeroOutputs(void);
|
||||
};
|
||||
|
||||
#endif
|
@ -6,7 +6,7 @@
|
||||
|
||||
; ---> SELECT TARGET PLATFORM HERE! <---
|
||||
[platformio]
|
||||
env_default = generic
|
||||
;env_default = generic
|
||||
;env_default = ebox
|
||||
;env_default = eboxtube
|
||||
;env_default = heltec
|
||||
@ -16,7 +16,7 @@ env_default = generic
|
||||
;env_default = ttgov21old
|
||||
;env_default = ttgov21new
|
||||
;env_default = ttgobeam_old
|
||||
;env_default = ttgobeam_new
|
||||
env_default = ttgobeam_new
|
||||
;env_default = lopy
|
||||
;env_default = lopy4
|
||||
;env_default = fipy
|
||||
@ -30,10 +30,10 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
|
||||
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 1.7.01
|
||||
release_version = 1.7.03
|
||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||
debug_level = 0
|
||||
debug_level = 4
|
||||
; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA
|
||||
upload_protocol = esptool
|
||||
;upload_protocol = custom
|
||||
|
@ -1,88 +1,89 @@
|
||||
#ifdef HAS_BME
|
||||
|
||||
#include "bme680mems.h"
|
||||
#include "bsec.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
|
||||
bmeStatus_t bme_status;
|
||||
TaskHandle_t BmeTask;
|
||||
|
||||
float bme_offset = (float)BME_TEMP_OFFSET;
|
||||
|
||||
// --- Bosch BSEC library configuration ---
|
||||
// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days
|
||||
// calibration. Change this const if not applicable for your application (see
|
||||
// BME680 datasheet)
|
||||
const uint8_t bsec_config_iaq[454] = {
|
||||
1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0,
|
||||
0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0,
|
||||
64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64,
|
||||
49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0,
|
||||
0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0,
|
||||
0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10,
|
||||
215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9,
|
||||
0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27,
|
||||
156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97,
|
||||
64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121,
|
||||
71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48,
|
||||
117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4,
|
||||
144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48,
|
||||
117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0,
|
||||
100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48,
|
||||
117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117,
|
||||
100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44,
|
||||
1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1,
|
||||
44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
|
||||
7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
|
||||
112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112,
|
||||
23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255,
|
||||
255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0,
|
||||
239, 79, 0, 0};
|
||||
Bsec iaqSensor;
|
||||
|
||||
// initialize BME680 sensor
|
||||
int bme_init(void) {
|
||||
|
||||
// struct bme680_dev gas_sensor;
|
||||
Wire.begin(HAS_BME, 400000); // I2C connect to BME680 sensor with 400 KHz
|
||||
Wire.begin(HAS_BME);
|
||||
iaqSensor.begin(BME_ADDR, Wire);
|
||||
|
||||
// Call to the function which initializes the BSEC library
|
||||
// Switch on low-power mode and provide no temperature offset
|
||||
ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
|
||||
iaqSensor.version.minor, iaqSensor.version.major_bugfix,
|
||||
iaqSensor.version.minor_bugfix);
|
||||
|
||||
return_values_init ret =
|
||||
bsec_iot_init(BSEC_SAMPLE_RATE_LP, bme_offset, i2c_write, i2c_read,
|
||||
user_delay_ms, state_load, config_load);
|
||||
iaqSensor.setConfig(bsec_config_iaq);
|
||||
|
||||
if ((int)ret.bme680_status) {
|
||||
ESP_LOGE(TAG, "Could not initialize BME680, error %d",
|
||||
(int)ret.bme680_status);
|
||||
} else if ((int)ret.bsec_status) {
|
||||
ESP_LOGE(TAG, "Could not initialize BSEC library, error %d",
|
||||
(int)ret.bsec_status);
|
||||
} else {
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BME680 sensor found and initialized");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BME680 sensor not found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bsec_virtual_sensor_t sensorList[10] = {
|
||||
BSEC_OUTPUT_RAW_TEMPERATURE,
|
||||
BSEC_OUTPUT_RAW_PRESSURE,
|
||||
BSEC_OUTPUT_RAW_HUMIDITY,
|
||||
BSEC_OUTPUT_RAW_GAS,
|
||||
BSEC_OUTPUT_IAQ,
|
||||
BSEC_OUTPUT_STATIC_IAQ,
|
||||
BSEC_OUTPUT_CO2_EQUIVALENT,
|
||||
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
|
||||
};
|
||||
|
||||
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BSEC subscription succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BSEC subscription error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iaqSensor.setTemperatureOffset(bme_offset);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "Ttemperature offset initialized succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "Temperature offset initialization error");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy,
|
||||
float temperature, float humidity, float pressure,
|
||||
float raw_temperature, float raw_humidity, float gas,
|
||||
bsec_library_return_t bsec_status, float static_iaq,
|
||||
float co2_equivalent, float breath_voc_equivalent) {
|
||||
// Helper function definitions
|
||||
int checkIaqSensorStatus(void) {
|
||||
int rslt = 1; // true = 1 = no error, false = 0 = error
|
||||
|
||||
bme_status.temperature = temperature;
|
||||
bme_status.humidity = humidity;
|
||||
bme_status.pressure = (pressure / 100.0); // conversion Pa -> hPa
|
||||
bme_status.iaq = iaq;
|
||||
if (iaqSensor.status != BSEC_OK) {
|
||||
rslt = 0;
|
||||
if (iaqSensor.status < BSEC_OK)
|
||||
ESP_LOGE(TAG, "BSEC error %d", iaqSensor.status);
|
||||
else
|
||||
ESP_LOGW(TAG, "BSEC warning %d", iaqSensor.status);
|
||||
}
|
||||
|
||||
if (iaqSensor.bme680Status != BME680_OK) {
|
||||
rslt = 0;
|
||||
if (iaqSensor.bme680Status < BME680_OK)
|
||||
ESP_LOGE(TAG, "BME680 error %d", iaqSensor.bme680Status);
|
||||
else
|
||||
ESP_LOGW(TAG, "BME680 warning %d", iaqSensor.bme680Status);
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
// loop function which reads and processes data based on sensor settings
|
||||
@ -91,84 +92,23 @@ void bme_loop(void *pvParameters) {
|
||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||
|
||||
#ifdef HAS_BME
|
||||
// State is saved every 10.000 samples, which means every 10.000 * 3 secs =
|
||||
// 500 minutes
|
||||
bsec_iot_loop(user_delay_ms, get_timestamp_us, output_ready, state_save,
|
||||
10000);
|
||||
while (checkIaqSensorStatus()) {
|
||||
if (iaqSensor.run()) { // If new data is available
|
||||
bme_status.raw_temperature = iaqSensor.rawTemperature;
|
||||
bme_status.raw_humidity = iaqSensor.rawHumidity;
|
||||
bme_status.temperature = iaqSensor.temperature;
|
||||
bme_status.humidity = iaqSensor.humidity;
|
||||
bme_status.pressure =
|
||||
(iaqSensor.pressure / 100.0); // conversion Pa -> hPa
|
||||
bme_status.iaq = iaqSensor.iaqEstimate;
|
||||
bme_status.iaq_accuracy = iaqSensor.iaqAccuracy;
|
||||
bme_status.gas = iaqSensor.gasResistance;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ESP_LOGE(TAG, "BME task ended");
|
||||
vTaskDelete(BmeTask); // should never be reached
|
||||
|
||||
} // bme_loop()
|
||||
|
||||
int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data,
|
||||
uint16_t len) {
|
||||
int8_t rslt = 0;
|
||||
Wire.beginTransmission(dev_id);
|
||||
Wire.write(reg_addr);
|
||||
rslt = Wire.endTransmission(false);
|
||||
|
||||
Wire.requestFrom((int)dev_id, (int)len);
|
||||
for (uint16_t i = 0; (i < len) && Wire.available(); i++) {
|
||||
reg_data[i] = Wire.read();
|
||||
}
|
||||
// return 0 for success, non-zero for failure
|
||||
return rslt;
|
||||
}
|
||||
|
||||
int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data,
|
||||
uint16_t len) {
|
||||
Wire.beginTransmission(dev_id);
|
||||
Wire.write(reg_addr);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
Wire.write(reg_data[i]);
|
||||
}
|
||||
// return 0 for success, non-zero for failure
|
||||
return Wire.endTransmission(true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Load previous library state from non-volatile memory
|
||||
*
|
||||
* @param[in,out] state_buffer buffer to hold the loaded state string
|
||||
* @param[in] n_buffer size of the allocated state buffer
|
||||
*
|
||||
* @return number of bytes copied to state_buffer
|
||||
*/
|
||||
uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer) {
|
||||
// ...
|
||||
// Load a previous library state from non-volatile memory, if available.
|
||||
//
|
||||
// Return zero if loading was unsuccessful or no state was available,
|
||||
// otherwise return length of loaded state string.
|
||||
// ...
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Save library state to non-volatile memory
|
||||
*
|
||||
* @param[in] state_buffer buffer holding the state to be stored
|
||||
* @param[in] length length of the state string to be stored
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void state_save(const uint8_t *state_buffer, uint32_t length) {
|
||||
// ...
|
||||
// Save the string some form of non-volatile memory, if possible.
|
||||
// ...
|
||||
}
|
||||
|
||||
uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer) {
|
||||
|
||||
// Load a library config from non-volatile memory, if available.
|
||||
// Return zero if loading was unsuccessful or no config was available,
|
||||
// otherwise return length of loaded config string.
|
||||
|
||||
memcpy(config_buffer, bsec_config_iaq, sizeof(bsec_config_iaq));
|
||||
return sizeof(bsec_config_iaq);
|
||||
}
|
||||
|
||||
void user_delay_ms(uint32_t period) { delay(period); }
|
||||
|
||||
int64_t get_timestamp_us() { return (int64_t)millis() * 1000; }
|
||||
|
||||
#endif // HAS_BME
|
@ -17,8 +17,8 @@
|
||||
|
||||
// enable only if device has these sensors, otherwise comment these lines
|
||||
// BME680 sensor on I2C bus
|
||||
// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76
|
||||
#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
||||
#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
||||
|
||||
// user defined sensors
|
||||
//#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
||||
|
@ -11,11 +11,9 @@
|
||||
// disable brownout detection (avoid unexpected reset on some boards)
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
// enable only if device has these sensors, otherwise comment these lines
|
||||
// BME680 sensor on I2C bus
|
||||
// Octopus32 has a pre-populated BME680 on i2c addr 0x76
|
||||
#define HAS_BME GPIO_NUM_23, GPIO_NUM_22 // SDA, SCL
|
||||
//#define HAS_BME 0x76
|
||||
#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
||||
|
||||
// user defined sensors
|
||||
//#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
||||
|
@ -8,12 +8,11 @@
|
||||
// Hardware related definitions for TTGO T-Beam board
|
||||
//
|
||||
// pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam
|
||||
//
|
||||
|
||||
// enable only if device has these sensors, otherwise comment these lines
|
||||
// BME680 sensor on I2C bus
|
||||
// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76
|
||||
//
|
||||
//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
||||
#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
||||
#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
|
||||
|
||||
#define HAS_LED GPIO_NUM_14 // on board green LED
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user