#include "bme_user.h" #include "app_timer.h" #include "nrf_drv_twi.h" #include "nrf_delay.h" #include "bsec_integration.h" static const nrf_drv_twi_t m_twi_master = NRF_DRV_TWI_INSTANCE(0); APP_TIMER_DEF(ms_timer); #define MS_1_INTERVAL APP_TIMER_TICKS(1) int64_t timestamp_ms = 0; /**@brief Function for initializing the 5 ms timer module for BME680 */ static void app_ms_timer_start(void) { ret_code_t err_code; err_code = app_timer_start(ms_timer, MS_1_INTERVAL, NULL); APP_ERROR_CHECK(err_code); } /**@brief Mili Second interval timeout handler increments timestamp for BME680 */ static void ms_timeout_handler(void * p_context) { timestamp_ms += 1; app_ms_timer_start(); } /** * @brief Initialize the master TWI. * * Function used to initialize the master TWI interface that would communicate with simulated EEPROM. * * @return NRF_SUCCESS or the reason of failure. */ static ret_code_t twi_master_init(void) { ret_code_t ret; const nrf_drv_twi_config_t config = { .scl = 32 + 9, .sda = 8, .frequency = TWI_FREQUENCY_FREQUENCY_K100, .interrupt_priority = 2, .clear_bus_init = false }; ret = nrf_drv_twi_init(&m_twi_master, &config, NULL, NULL); if (NRF_SUCCESS == ret) { nrf_drv_twi_enable(&m_twi_master); } return ret; } /*! * @brief Write operation in either I2C or SPI * * param[in] dev_addr I2C or SPI device address * param[in] reg_addr register address * param[in] reg_data_ptr pointer to the data to be written * param[in] data_len number of bytes to be written * * @return result of the bus communication function */ int8_t bus_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len) { // ... // Please insert system specific function to write to the bus where BME680 is connected // ... ret_code_t ret; data_len = (uint8_t) data_len; reg_data_ptr--; *reg_data_ptr = reg_addr; ret = nrf_drv_twi_tx(&m_twi_master, dev_addr, reg_data_ptr, data_len+1, false); return 0; } /*! * @brief Read operation in either I2C or SPI * * param[in] dev_addr I2C or SPI device address * param[in] reg_addr register address * param[out] reg_data_ptr pointer to the memory to be used to store the read data * param[in] data_len number of bytes to be read * * @return result of the bus communication function */ int8_t bus_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len) { // ... // Please insert system specific function to read from bus where BME680 is connected // ... ret_code_t ret; data_len = (uint8_t) data_len; uint8_t tx_data[] = {reg_addr}; ret = nrf_drv_twi_tx(&m_twi_master, dev_addr, tx_data, 1, true); ret = nrf_drv_twi_rx(&m_twi_master, dev_addr, reg_data_ptr, data_len); return 0; } /*! * @brief System specific implementation of sleep function * * @param[in] t_ms time in milliseconds * * @return none */ void sleep(uint32_t t_ms) { // Please insert system specific function sleep or delay for t_ms milliseconds nrf_delay_ms(t_ms); } /*! * @brief Capture the system time in microseconds * * @return system_current_time current system timestamp in microseconds */ int64_t get_timestamp_us() { int64_t system_current_time = timestamp_ms * 1000; // ... // Please insert system specific function to retrieve a timestamp (in microseconds) // ... return system_current_time; } /*! * @brief Handling of the ready outputs * * @param[in] timestamp time in nanoseconds * @param[in] iaq IAQ signal * @param[in] iaq_accuracy accuracy of IAQ signal * @param[in] temperature temperature signal * @param[in] humidity humidity signal * @param[in] pressure pressure signal * @param[in] raw_temperature raw temperature signal * @param[in] raw_humidity raw humidity signal * @param[in] gas raw gas sensor signal * @param[in] bsec_status value returned by the bsec_do_steps() call * * @return none */ int64_t g_timestamp; float g_iaq; uint8_t g_iaq_accuracy; float g_temperature, g_humidity, g_pressure, g_raw_temperature, g_raw_humidity, g_gas,g_static_iaq, g_co2_equivalent, g_breath_voc_equivalent; bsec_library_return_t g_bsec_status; 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) { // ... // Please insert system specific code to further process or display the BSEC outputs // ... g_timestamp = timestamp; g_iaq = iaq; g_iaq_accuracy = iaq_accuracy; g_temperature = temperature; g_humidity = humidity; g_pressure = pressure; g_raw_temperature = raw_temperature; g_raw_humidity = raw_humidity; g_gas = gas; g_static_iaq = static_iaq; g_co2_equivalent = co2_equivalent; g_breath_voc_equivalent = breath_voc_equivalent; g_bsec_status = bsec_status; uint8_t data_to_send[]={0x00,0x00,0x00,0x00}; uint16_t length = sizeof(data_to_send); //uint32_t err_code = ble_nus_data_send(&m_nus, data_to_send, &length, m_conn_handle); } /*! * @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. // ... } /*! * @brief Load library config from non-volatile memory * * @param[in,out] config_buffer buffer to hold the loaded state string * @param[in] n_buffer size of the allocated state buffer * * @return number of bytes copied to config_buffer */ 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. // ... return 0; } int8_t bme_metering_enable() { ret_code_t err_code; err_code = twi_master_init(); return_values_init ret; err_code = app_timer_create(&ms_timer, APP_TIMER_MODE_SINGLE_SHOT, ms_timeout_handler); app_ms_timer_start(); /* Call to the function which initializes the BSEC library * Switch on low-power mode and provide no temperature offset */ ret = bsec_iot_init(BSEC_SAMPLE_RATE_CONTINUOUS, 10.0f, bus_write, bus_read, sleep, state_load, config_load); if (ret.bme680_status) { /* Could not intialize BME680 */ return (int)ret.bme680_status; } else if (ret.bsec_status) { /* Could not intialize BSEC library */ return (int)ret.bsec_status; } } void bme_metering_start() { /* Call to endless loop function which reads and processes data based on sensor settings */ /* State is saved every 10.000 samples, which means every 10.000 * 3 secs = 500 minutes */ bsec_iot_loop(sleep, get_timestamp_us, output_ready, state_save, 10000); }