diff --git a/bsec_bme680.c b/bsec_bme680.c new file mode 100644 index 0000000..7168ba8 --- /dev/null +++ b/bsec_bme680.c @@ -0,0 +1,368 @@ +/* Copyright (C) 2017 alexh.name */ +/* I2C code by twartzek 2017 */ + +/* + * Read the BME680 sensor with the BSEC library by running an endless loop in + * the bsec_iot_loop() function under Linux. + * + */ + +/*#define _POSIX_C_SOURCE 200809L*/ +#define _XOPEN_SOURCE 700 + +/* header files */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bsec_integration.h" + +/* definitions */ + +#define DESTZONE "TZ=Europe/Berlin" +#define temp_offset (5.0f) +#define sample_rate_mode (BSEC_SAMPLE_RATE_LP) + +int g_i2cFid; // I2C Linux device handle + +int i2#_address = BME600_I2C_ADDR_SECONDARY; // was BME680_I2C_ADDR_PRIMARY - 76,secundary is 77 +int i2c_address = BME680_I2C_ADDR_PRIMARY; +char *filename_state = "bsec_iaq.state"; +char *filename_config = "bsec_iaq.config"; + +/* functions */ + +// open the Linux device +void i2cOpen() +{ + g_i2cFid = open("/dev/i2c-1", O_RDWR); + if (g_i2cFid < 0) { + perror("i2cOpen"); + exit(1); + } +} + +// close the Linux device +void i2cClose() +{ + close(g_i2cFid); +} + +// set the I2C slave address for all subsequent I2C device transfers +void i2cSetAddress(int address) +{ + if (ioctl(g_i2cFid, I2C_SLAVE, address) < 0) { + perror("i2cSetAddress"); + exit(1); + } +} + +/* + * 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) +{ + int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ + + uint8_t reg[16]; + reg[0]=reg_addr; + int i; + + for (i=1; i n_buffer) { + fprintf(stderr,"%s: %d > %d\n", "binary data bigger than buffer", filesize, + n_buffer); + return 0; + } else { + FILE *file_ptr; + file_ptr = fopen(filename,"rb"); + if (!file_ptr) { + perror("fopen"); + return 0; + } + fseek(file_ptr,offset,SEEK_SET); + copied_bytes = fread(b_buffer,sizeof(char),filesize,file_ptr); + if (copied_bytes == 0) { + fprintf(stderr,"%s empty\n",filename); + } + fclose(file_ptr); + return copied_bytes; + } +} + +/* + * 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 or zero on failure + */ +uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer) +{ + int32_t rslt = 0; + rslt = binary_load(state_buffer, n_buffer, filename_state, 0); + return rslt; +} + +/* + * 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) +{ + FILE *state_w_ptr; + state_w_ptr = fopen(filename_state,"wb"); + fwrite(state_buffer,length,1,state_w_ptr); + fclose(state_w_ptr); +} + +/* + * 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 or zero on failure + */ +uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer) +{ + int32_t rslt = 0; + /* + * Provided config file is 4 bytes larger than buffer. + * Apparently skipping the first 4 bytes works fine. + * + */ + rslt = binary_load(config_buffer, n_buffer, filename_config, 4); + return rslt; +} + +/* main */ + +/* + * Main function which configures BSEC library and then reads and processes + * the data from sensor based on timer ticks + * + * return result of the processing + */ +int main() +{ + putenv(DESTZONE); // Switch to destination time zone + + i2cOpen(); + i2cSetAddress(i2c_address); + + return_values_init ret; + + ret = bsec_iot_init(sample_rate_mode, temp_offset, 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; + } + + /* 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 (depending on the config). + * NOTAJOTA: CHANGED TO 4 hours = 4800 + * + */ + bsec_iot_loop(_sleep, get_timestamp_us, output_ready, state_save, 4800); + + i2cClose(); + return 0; +} \ No newline at end of file