diff --git a/Makefile b/Makefile index d20a631..983f8c7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ CC=gcc OPT=-O2 -std=c99 -Wall -Wextra +# OPT=-O0 -g3 -std=c99 -Wall -Wextra -pedantic CFLAGS=-I. $(OPT) CFILES=$(wildcard ./*.c) OBJECTS=$(patsubst %.c,%.o, $(CFILES)) diff --git a/bme680.c b/bme680.c index c5021d6..dd73b01 100644 --- a/bme680.c +++ b/bme680.c @@ -1,309 +1,248 @@ #include "bme680.h" -#include "i2c.h" -#include +#include "registers.h" -const double const_array1[16] = { - 1, - 1, - 1, - 1, - 1, - 0.99, - 1, - 0.992, - 1, - 1, - 0.998, - 0.995, - 1, - 0.99, - 1, - 1 + + +int bme680_init(bme680_t *bme680) { + + uint8_t car; + + if (bme680->dev.init() != 0) { + return 1; + } + + if (bme680->dev.read(REG_ID, &car, 1) != 0) { + return 1; + } + + if (car != 0x61) { + return 1; + } + + return 0; +} + + +static double const_array1[16] = { + 1, 1, 1, 1, 1, 0.99, 1, 0.992, 1, + 1, 0.998, 0.995, 1, 0.99, 1, 1 }; -const double const_array2[16] = { - 8000000, - 4000000, - 2000000, - 1000000, - 499500.4995, - 248262.1648, - 125000, - 63004.03226, - 31281.28128, - 15625, - 7812.5, - 3906.25, - 1953.125, - 976.5625, - 488.28125, - 244.140625 +static double const_array2[16] = { + 8000000, 4000000, 2000000, 1000000, 499500.4995, 248262.1648, + 125000, 63004.03226, 31281.28128, 15625, 7812.5, 3906.25, + 1953.125, 976.5625, 488.28125, 244.140625 }; -const int const_array1_int[16] = { - 2147483647, - 2147483647, - 2147483647, - 2147483647, - 2147483647, - 2126008810, - 2147483647, - 2130303777, - 2147483647, - 2147483647, - 2143188679, - 2136746228, - 2147483647, - 2126008810, - 2147483647, +static int const_array1_int[16] = { + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2126008810, 2147483647, 2130303777, 2147483647, 2147483647, + 2143188679, 2136746228, 2147483647, 2126008810, 2147483647, 2147483647 }; -const int const_array2_int[16] = { - 4096000000, // too big ? - 2048000000, - 1024000000, - 512000000, - 255744255, - 127110228, - 64000000, - 32258064, - 16016016, - 8000000, - 4000000, - 2000000, - 1000000, - 500000, - 250000, - 125000 +static int const_array2_int[16] = { + 4096000000, 2048000000, 1024000000, 512000000, 255744255, + 127110228, 64000000, 32258064, 16016016, 8000000, 4000000, + 2000000, 1000000, 500000, 250000, 125000 }; -double calc_temp_comp_1 ( uint32_t temp_adc , bme680_t *bme680) { +static void calc_temp_comp_1 (bme680_t *bme680) { double var1, var2, temp_comp; - bme680_calibration *cal; - cal = &bme680->cal; - - - var1 = (((double)temp_adc / 16384.0) - ((double)cal->par_t1 / 1024.0)) * - (double)cal->par_t2; - var2 = ((((double)temp_adc / 131072.0) - ((double)cal->par_t1 / 8192.0)) * - (((double)temp_adc / 131072.0) - ((double)cal->par_t1 / 8192.0))) * - ((double)cal->par_t3 * 16.0); - bme680->tfine_double = var1 + var2; + var1 = (((double)bme680->adc.temp / 16384.0) - ((double)bme680->cal.par_t1 / 1024.0)) * + (double)bme680->cal.par_t2; + var2 = ((((double)bme680->adc.temp / 131072.0) - ((double)bme680->cal.par_t1 / 8192.0)) * + (((double)bme680->adc.temp / 131072.0) - ((double)bme680->cal.par_t1 / 8192.0))) * + ((double)bme680->cal.par_t3 * 16.0); + bme680->fcomp.tfine = var1 + var2; temp_comp = (var1 + var2) / 5120.0; - bme680->temp_comp_double = temp_comp; - return temp_comp; + bme680->fcomp.temp = temp_comp; } -int calc_temp_comp_2 (uint32_t temp_adc, bme680_t *bme680) { +static void calc_temp_comp_2 (bme680_t *bme680) { int32_t var1, var2, var3, temp_comp; - bme680_calibration *cal; - cal = &bme680->cal; - - var1 = ((int32_t)temp_adc >> 3) - ((int32_t) cal->par_t1 << 1); - var2 = (var1 * (int32_t)cal->par_t2) >> 11; - var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) * ((int32_t)cal->par_t3 << 4)) >> 14; - bme680->tfine_int = var2 + var3; - temp_comp = (( (var2 + var3) * 5) + 128) >> 8; - bme680->temp_comp_int = temp_comp; - return temp_comp; + var1 = ((int32_t)bme680->adc.temp >> 3) - ((int32_t) bme680->cal.par_t1 << 1); + var2 = (var1 * (int32_t)bme680->cal.par_t2) >> 11; + var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) * ((int32_t)bme680->cal.par_t3 << 4)) >> 14; + bme680->icomp.tfine = var2 + var3; + temp_comp = (((var2 + var3) * 5) + 128) >> 8; + bme680->icomp.temp = temp_comp; } -double calc_press_comp_1 ( uint32_t press_adc , bme680_t *bme680 ) { +static void calc_press_comp_1 (bme680_t *bme680) { double var1, var2, var3, press_comp; - bme680_calibration *cal; - cal = &bme680->cal; - - var1 = ((double)bme680->tfine_double / 2.0) - 64000.0; - var2 = var1 * var1 * ((double)cal->par_p6 / 131072.0); - var2 = var2 + (var1 * (double)cal->par_p5 * 2.0); - var2 = (var2 / 4.0) + ((double)cal->par_p4 * 65536.0); - var1 = ((((double)cal->par_p3 * var1 * var1) / 16384.0) + - ((double)cal->par_p2 * var1)) / 524288.0; - var1 = (1.0 + (var1 / 32768.0)) * (double)cal->par_p1; - press_comp = 1048576.0 - (double)press_adc; + var1 = ((double)bme680->fcomp.tfine / 2.0) - 64000.0; + var2 = var1 * var1 * ((double)bme680->cal.par_p6 / 131072.0); + var2 = var2 + (var1 * (double)bme680->cal.par_p5 * 2.0); + var2 = (var2 / 4.0) + ((double)bme680->cal.par_p4 * 65536.0); + var1 = ((((double)bme680->cal.par_p3 * var1 * var1) / 16384.0) + + ((double)bme680->cal.par_p2 * var1)) / 524288.0; + var1 = (1.0 + (var1 / 32768.0)) * (double)bme680->cal.par_p1; + press_comp = 1048576.0 - (double)bme680->adc.press; press_comp = ((press_comp - (var2 / 4096.0)) * 6250.0) / var1; - var1 = ((double)cal->par_p9 * press_comp * press_comp) / 2147483648.0; - var2 = press_comp * ((double)cal->par_p8 / 32768.0); + var1 = ((double)bme680->cal.par_p9 * press_comp * press_comp) / 2147483648.0; + var2 = press_comp * ((double)bme680->cal.par_p8 / 32768.0); var3 = (press_comp / 256.0) * (press_comp / 256.0) * - (press_comp / 256.0) * (cal->par_p10 / 131072.0); - press_comp = press_comp + (var1 + var2 + var3 + ((double)cal->par_p7 * 128.0)) / 16.0; - - - bme680->press_comp_double = press_comp; - return press_comp; + (press_comp / 256.0) * (bme680->cal.par_p10 / 131072.0); + press_comp = press_comp + (var1 + var2 + var3 + ((double)bme680->cal.par_p7 * 128.0)) / 16.0; + bme680->fcomp.press = press_comp; } -int calc_press_comp_2 ( uint32_t press_adc , bme680_t *bme680 ) { +static void calc_press_comp_2 (bme680_t *bme680 ) { int32_t var1, var2, var3, press_comp; - bme680_calibration *cal; - cal = &bme680->cal; - - var1 = ((int32_t)bme680->tfine_int >> 1) - 64000; - var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)cal->par_p6) >> 2; - var2 = var2 + ((var1 * (int32_t)cal->par_p5) << 1); - var2 = (var2 >> 2) + ((int32_t)cal->par_p4 << 16); + var1 = ((int32_t)bme680->icomp.tfine >> 1) - 64000; + var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)bme680->cal.par_p6) >> 2; + var2 = var2 + ((var1 * (int32_t)bme680->cal.par_p5) << 1); + var2 = (var2 >> 2) + ((int32_t)bme680->cal.par_p4 << 16); var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * - ((int32_t)cal->par_p3 << 5)) >> 3) + (((int32_t)cal->par_p2 * var1) >> 1); + ((int32_t)bme680->cal.par_p3 << 5)) >> 3) + (((int32_t)bme680->cal.par_p2 * var1) >> 1); var1 = var1 >> 18; - var1 = ((32768 + var1) * (int32_t)cal->par_p1) >> 15; - press_comp = 1048576 - press_adc; // bosch code pg 19 says "press_raw" here ??? + var1 = ((32768 + var1) * (int32_t)bme680->cal.par_p1) >> 15; + press_comp = 1048576 - bme680->adc.press; // bosch code pg 19 says "press_raw" here ??? press_comp = (uint32_t)((press_comp - (var2 >> 12)) * ((uint32_t)3125)); if (press_comp >= (1 << 30)) press_comp = ((press_comp / (uint32_t)var1) << 1); else press_comp = ((press_comp << 1) / (uint32_t)var1); - var1 = ((int32_t)cal->par_p9 * (int32_t)(((press_comp >> 3) * + var1 = ((int32_t)bme680->cal.par_p9 * (int32_t)(((press_comp >> 3) * (press_comp >> 3)) >> 13)) >> 12; - var2 = ((int32_t)(press_comp >> 2) * (int32_t)cal->par_p8) >> 13; + var2 = ((int32_t)(press_comp >> 2) * (int32_t)bme680->cal.par_p8) >> 13; var3 = ((int32_t)(press_comp >> 8) * (int32_t)(press_comp >> 8) * - (int32_t)(press_comp >> 8) * (int32_t)cal->par_p10) >> 17; - press_comp = (int32_t)(press_comp) + ((var1 + var2 + var3 + ((int32_t)cal->par_p7 << 7)) >> 4); - - - bme680->press_comp_int = press_comp; - - return press_comp; + (int32_t)(press_comp >> 8) * (int32_t)bme680->cal.par_p10) >> 17; + press_comp = (int32_t)(press_comp) + ((var1 + var2 + var3 + ((int32_t)bme680->cal.par_p7 << 7)) >> 4); + bme680->icomp.press = press_comp; } -double calc_hum_comp_1 ( uint32_t hum_adc , bme680_t *bme680 ) { +static void calc_hum_comp_1 (bme680_t *bme680) { double var1, var2, var3, var4, hum_comp, temp_comp; - bme680_calibration *cal; - cal = &bme680->cal; - temp_comp = bme680->temp_comp_double; + temp_comp = bme680->fcomp.temp; - var1 = hum_adc - (((double)cal->par_h1 * 16.0) + (((double)cal->par_h3 / 2.0) * temp_comp)); - var2 = var1 * (((double)cal->par_h2 / 262144.0) * (1.0 + (((double)cal->par_h4 / 16384.0) * - temp_comp) + (((double)cal->par_h5 / 1048576.0) * temp_comp * temp_comp))); - var3 = (double)cal->par_h6 / 16384.0; - var4 = (double)cal->par_h7 / 2097152.0; + var1 = bme680->adc.hum - (((double)bme680->cal.par_h1 * 16.0) + (((double)bme680->cal.par_h3 / 2.0) * temp_comp)); + var2 = var1 * (((double)bme680->cal.par_h2 / 262144.0) * (1.0 + (((double)bme680->cal.par_h4 / 16384.0) * + temp_comp) + (((double)bme680->cal.par_h5 / 1048576.0) * temp_comp * temp_comp))); + var3 = (double)bme680->cal.par_h6 / 16384.0; + var4 = (double)bme680->cal.par_h7 / 2097152.0; hum_comp = var2 + ((var3 + (var4 * temp_comp)) * var2 * var2); - - bme680->hum_comp_double = hum_comp; - return hum_comp; + bme680->fcomp.hum = hum_comp; } -int calc_hum_comp_2 ( uint32_t hum_adc , bme680_t *bme680 ) { +static void calc_hum_comp_2 (bme680_t *bme680) { int32_t var1, var2, var3, var4, var5, var6, temp_scaled, hum_comp; - bme680_calibration *cal; - cal = &bme680->cal; - - temp_scaled = (int32_t)bme680->temp_comp_int; - var1 = (int32_t)hum_adc - (int32_t)((int32_t)cal->par_h1 << 4) - - (((temp_scaled * (int32_t)cal->par_h3) / ((int32_t)100)) >> 1); - var2 = ((int32_t)cal->par_h2 * (((temp_scaled * (int32_t)cal->par_h4) / ((int32_t)100)) + - (((temp_scaled * ((temp_scaled * (int32_t)cal->par_h5) / + temp_scaled = (int32_t)bme680->icomp.temp; + var1 = (int32_t)bme680->adc.hum - (int32_t)((int32_t)bme680->cal.par_h1 << 4) - + (((temp_scaled * (int32_t)bme680->cal.par_h3) / ((int32_t)100)) >> 1); + var2 = ((int32_t)bme680->cal.par_h2 * (((temp_scaled * (int32_t)bme680->cal.par_h4) / ((int32_t)100)) + + (((temp_scaled * ((temp_scaled * (int32_t)bme680->cal.par_h5) / ((int32_t)100))) >> 6) / ((int32_t)100)) + ((int32_t)(1 << 14)))) >> 10; var3 = var1 * var2; - var4 = (((int32_t)cal->par_h6 << 7) + - ((temp_scaled * (int32_t)cal->par_h7) / ((int32_t)100))) >> 4; + var4 = (((int32_t)bme680->cal.par_h6 << 7) + + ((temp_scaled * (int32_t)bme680->cal.par_h7) / ((int32_t)100))) >> 4; var5 = ((var3 >> 14) * (var3 >> 14)) >> 10; var6 = (var4 * var5) >> 1; hum_comp = (((var3 + var6) >> 10) * ((int32_t) 1000)) >> 12; - - bme680->hum_comp_int = hum_comp; - return hum_comp; + bme680->icomp.hum = hum_comp; } -int bme680_calibrate ( int fd , bme680_calibration *cal ) { + +int bme680_calibrate(bme680_t *bme680) { uint8_t buffer[3] = {0, 0 ,0}; int err = 0; // start with temp params - err |= i2c_read_reg(fd, 0xE9, 2, buffer); - cal->par_t1 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0xE9, buffer, 2); + bme680->cal.par_t1 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x8A, 2, buffer); - cal->par_t2 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x8A, buffer, 2); + bme680->cal.par_t2 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x8C, 1, buffer); - cal->par_t3 = buffer[0]; + err |= bme680->dev.read(0x8C, buffer, 1); + bme680->cal.par_t3 = buffer[0]; // pressure - err |= i2c_read_reg(fd, 0x8E, 2, buffer); - cal->par_p1 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x8E, buffer, 2); + bme680->cal.par_p1 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x90, 2 , buffer); - cal->par_p2 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x90, buffer, 2); + bme680->cal.par_p2 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x92, 1, buffer); - cal->par_p3 = buffer[0]; + err |= bme680->dev.read(0x92, buffer, 1); + bme680->cal.par_p3 = buffer[0]; - err |= i2c_read_reg(fd, 0x94, 2, buffer); - cal->par_p4 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x94, buffer, 2); + bme680->cal.par_p4 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x96, 2, buffer); - cal->par_p5 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x96, buffer, 2); + bme680->cal.par_p5 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x99, 1, buffer); - cal->par_p6 = buffer[0]; + err |= bme680->dev.read(0x99, buffer, 1); + bme680->cal.par_p6 = buffer[0]; - err |= i2c_read_reg(fd, 0x98, 1, buffer); // strange order - cal->par_p7 = buffer[0]; + err |= bme680->dev.read(0x98, buffer, 1); // strange order + bme680->cal.par_p7 = buffer[0]; - err |= i2c_read_reg(fd, 0x9C, 2, buffer); - cal->par_p8 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x9C, buffer, 1); + bme680->cal.par_p8 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0x9E, 2, buffer); - cal->par_p9 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0x9E, buffer, 2); + bme680->cal.par_p9 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0xA0, 1, buffer); - cal->par_p10 = buffer[0]; + err |= bme680->dev.read(0xA0, buffer, 1); + bme680->cal.par_p10 = buffer[0]; // humidity - err |= i2c_read_reg(fd, 0xE2, 2, buffer); - cal->par_h1 = (buffer[1] << 4) | (buffer[0] & 0xF); + err |= bme680->dev.read(0xE2, buffer, 2); + bme680->cal.par_h1 = (buffer[1] << 4) | (buffer[0] & 0xF); - err |= i2c_read_reg(fd, 0xE1, 2, buffer); - cal->par_h2 = (buffer[0] << 4) | ((buffer[1] >> 4) & 0xF); + err |= bme680->dev.read(0xE1, buffer, 2); + bme680->cal.par_h2 = (buffer[0] << 4) | ((buffer[1] >> 4) & 0xF); - err |= i2c_read_reg(fd, 0xE4, 1, buffer); - cal->par_h3 = buffer[0]; + err |= bme680->dev.read(0xE4, buffer, 1); + bme680->cal.par_h3 = buffer[0]; - err |= i2c_read_reg(fd, 0xE5, 1, buffer); - cal->par_h4 = buffer[0]; + err |= bme680->dev.read(0xE5, buffer, 1); + bme680->cal.par_h4 = buffer[0]; - err |= i2c_read_reg(fd, 0xE6, 1, buffer); - cal->par_h5 = buffer[0]; + err |= bme680->dev.read(0xE6, buffer, 1); + bme680->cal.par_h5 = buffer[0]; - err |= i2c_read_reg(fd, 0xE7, 1, buffer); - cal->par_h6 = buffer[0]; + err |= bme680->dev.read(0xE7, buffer, 1); + bme680->cal.par_h6 = buffer[0]; - err |= i2c_read_reg(fd, 0xE8, 1, buffer); - cal->par_h7 = buffer[0]; + err |= bme680->dev.read(0xE8, buffer, 1); + bme680->cal.par_h7 = buffer[0]; // gas - err |= i2c_read_reg(fd, 0xED, 1, buffer); - cal->par_g1 = buffer[0]; + err |= bme680->dev.read(0xED, buffer, 1); + bme680->cal.par_g1 = buffer[0]; - err |= i2c_read_reg(fd, 0xEB, 2, buffer); - cal->par_g2 = (buffer[1] << 8) | buffer[0]; + err |= bme680->dev.read(0xEB, buffer, 2); + bme680->cal.par_g2 = (buffer[1] << 8) | buffer[0]; - err |= i2c_read_reg(fd, 0xEE, 1, buffer); - cal->par_g2 = buffer[0]; + err |= bme680->dev.read(0xEE, buffer, 1); + bme680->cal.par_g2 = buffer[0]; // todo more @@ -312,6 +251,7 @@ int bme680_calibrate ( int fd , bme680_calibration *cal ) { return err; } +/* void print_calibration ( bme680_calibration *cal ) { printf("par_t1: %d\n", cal->par_t1); printf("par_t2: %d\n", cal->par_t2); @@ -333,4 +273,6 @@ void print_calibration ( bme680_calibration *cal ) { printf("par_h5: %d\n", cal->par_h5); printf("par_h6: %d\n", cal->par_h6); printf("par_h7: %d\n", cal->par_h7); -} +} */ + + diff --git a/bme680.h b/bme680.h index 62fea15..a89081a 100644 --- a/bme680.h +++ b/bme680.h @@ -1,64 +1,128 @@ -#pragma once +#ifndef BME680_H +#define BME680 #include -typedef struct { +/* connection modes */ +#define BME680_SPI 1 +#define BME680_I2C 0 +/* calculation modes; int or float calc */ +#define BME680_MODE_INT 2 +#define BME680_MODE_FLOAT 0 + +#define BME680_MAX_XFER_SIZE 128 + +/* config values */ +#define BME680_OVERSAMPLE_1X 0b001 +#define BME680_OVERSAMPLE_2X 0b010 +#define BME680_OVERSAMPLE_4X 0b011 +#define BME680_OVERSAMPLE_8X 0b100 +#define BME680_OVERSAMPLE_16X 0b101 + +/* IIR filter */ +#define BME680_IIR_COEFF_0 0b000 +#define BME680_IIR_COEFF_1 0b001 +#define BME680_IIR_COEFF_3 0b010 +#define BME680_IIR_COEFF_7 0b011 +#define BME680_IIR_COEFF_15 0b100 +#define BME680_IIR_COEFF_31 0b101 +#define BME680_IIR_COEFF_63 0b110 +#define BME680_IIR_COEFF_127 0b111 + + +/* user supplied spi/i2c functions */ +struct bme680_dev { + int (*init) (void); + int (*read) (uint8_t reg, uint8_t *dst, uint32_t size); + int (*write) (uint8_t reg, uint8_t *src, uint32_t size); + int (*xfer) (uint8_t reg, uint8_t *src, uint8_t *dst, uint32_t size); + int (*deinit) (void); +}; + +struct bme680_cal { + /* temp calibration */ uint16_t par_t1; - int16_t par_t2; - int8_t par_t3; + int16_t par_t2; + int8_t par_t3; + /* press calibration */ uint16_t par_p1; - int16_t par_p2; - int8_t par_p3; - int16_t par_p4; - int16_t par_p5; - int8_t par_p6; - int8_t par_p7; - int16_t par_p8; - int16_t par_p9; - uint8_t par_p10; + int16_t par_p2; + int8_t par_p3; + int16_t par_p4; + int16_t par_p5; + int8_t par_p6; + int8_t par_p7; + int16_t par_p8; + int16_t par_p9; + uint8_t par_p10; + /* humidity calibration */ uint16_t par_h1; uint16_t par_h2; - int8_t par_h3; - int8_t par_h4; - int8_t par_h5; - uint8_t par_h6; - int8_t par_h7; + int8_t par_h3; + int8_t par_h4; + int8_t par_h5; + uint8_t par_h6; + int8_t par_h7; + /* gas maybe */ uint16_t par_g1; uint16_t par_g2; uint16_t par_g3; uint16_t range_switching_error; -} bme680_calibration; +}; -typedef struct { - int tfine_int; - double tfine_double; +struct bme680_config { + uint8_t osrs_t; + uint8_t osrs_p; + uint8_t osrs_h; + uint8_t fir; + uint8_t heater_setpoint[10]; + uint8_t heater_exposure_ms[10]; + uint8_t heater_exposure_scalar[10]; +}; - double temp_comp_double; - int temp_comp_int; +struct bme680_comp_float { + double tfine; + double temp; + double press; + double hum; +}; - double press_comp_double; - int press_comp_int; +struct bme680_comp_int { + int32_t tfine; + int32_t temp; + int32_t press; + int32_t hum; +}; - double hum_comp_double; - int hum_comp_int; +struct bme680_adc { + uint32_t temp; + uint32_t press; + uint32_t hum; + uint16_t gas; +}; - bme680_calibration cal; +struct bme680 { + struct bme680_comp_float fcomp; + struct bme680_comp_int icomp; + struct bme680_cal cal; + struct bme680_dev dev; + struct bme680_config cfg; + struct bme680_adc adc; + uint8_t mode; +}; -} bme680_t; +typedef struct bme680 bme680_t; + + +int bme680_init(bme680_t *bme680); +int bme680_calibrate(bme680_t *bme680); -void print_calibration(bme680_calibration *); -int bme680_calibrate(int, bme680_calibration *); -int calc_hum_comp_2(uint32_t, bme680_t *); -int calc_press_comp_2(uint32_t, bme680_t *); -int calc_temp_comp_2(uint32_t, bme680_t *); -double calc_temp_comp_1(uint32_t, bme680_t*); -double calc_press_comp_1(uint32_t, bme680_t *); -double calc_hum_comp_1(uint32_t, bme680_t *); +#endif diff --git a/bst-bme680-ds001.pdf b/bst-bme680-ds001.pdf new file mode 100644 index 0000000..3be3044 Binary files /dev/null and b/bst-bme680-ds001.pdf differ diff --git a/main.c b/main.c index 1fa69ce..83c8f0c 100644 --- a/main.c +++ b/main.c @@ -2,94 +2,94 @@ #define _DEFAULT_SOURCE #include +#include #include + #include "bme680.h" #include "i2c.h" #define DEVICE "/dev/i2c-1" #define ADDRESS 0x77 +int i2c_dev_fd; + +int linux_i2c_init (void); +int linux_i2c_read (uint8_t reg, uint8_t *dst, uint32_t size); +int linux_i2c_write (uint8_t reg, uint8_t *src, uint32_t size); +int linux_i2c_deinit (void); + int main(){ - int fd = i2c_init(DEVICE, ADDRESS); bme680_t bme680; - printf("%X\n", i2c_read_reg2(fd, 0xD0)); - if (bme680_calibrate(fd, &bme680.cal) != 0) { - fprintf(stderr, "error bme680 calibration\n"); - } else { - print_calibration(&bme680.cal); - } + /* 1. Assign functions for interacting with the device */ + bme680.dev.init = linux_i2c_init; + bme680.dev.read = linux_i2c_read; + bme680.dev.write = linux_i2c_write; + bme680.dev.deinit = linux_i2c_deinit; + bme680.dev.xfer = NULL; + + /* 2. set the device mode */ + bme680.mode = BME680_MODE_FLOAT | BME680_I2C; + /* BME680_MODE_INT | BME680_SPI; */ - - //1. write osrs fields to diff regs - uint8_t ctrl_meas, ctrl_hum; - - uint8_t osrs_t, osrs_p, osrs_h, ctrl_mode; - osrs_t = osrs_p = osrs_h = 0b110; - ctrl_mode = 0; - - ctrl_meas = (osrs_t << 5) | (osrs_p << 2) | ctrl_mode; - ctrl_hum = osrs_h; - - i2c_write_reg(fd, 0x74, ctrl_meas); - i2c_write_reg(fd, 0x72, ctrl_hum); - - // set filter mode - - uint8_t filter_reg = 0b101 << 2; - i2c_write_reg(fd, 0x75, filter_reg); - - // todo gas stuff - - // resend ctrl_meas but with ctrl_mode set to 0b01 in it, then it should work - ctrl_meas |= 1; - i2c_write_reg(fd, 0x74, ctrl_meas); - - // poll reg `meas_status_0 bit 5. It will be 0 when all scheduled conversions are done. - uint8_t qq; - while ((qq = i2c_read_reg2(fd, 0x1D)) >> 4) { - usleep(2000); // 2 ms + /* 3. initialise device, and check its id */ + if (bme680_init(&bme680) != 0) { + fprintf(stderr, "bme680_init()\n"); + exit(EXIT_FAILURE); } - // now read the temp/press/hum adc and convert in order. - uint32_t temp_adc, press_adc, hum_adc; + /* 4. read calibration parameters from the device and store in memory */ + if (bme680_calibrate(&bme680) != 0) { + fprintf(stderr, "bme680_calibrate()\n"); + bme680.dev.deinit(); + exit(EXIT_FAILURE); + } + + /* 5. set up device config */ + bme680.cfg.osrs_t = BME680_OVERSAMPLE_16X; + bme680.cfg.osrs_p = BME680_OVERSAMPLE_8X; + bme680.cfg.osrs_h = BME680_OVERSAMPLE_4X; - uint8_t buffer[3]; - - i2c_read_reg(fd, 0x22, 3, buffer); - temp_adc = (buffer[0] << 12) | (buffer[1] << 4) | (buffer[2] >> 4); - - i2c_read_reg(fd, 0x1F, 3, buffer); - press_adc = (buffer[0] << 12) | (buffer[1] << 4) | (buffer[2] >> 4); - - i2c_read_reg(fd, 0x25, 2, buffer); - hum_adc = (buffer[0] << 8) | buffer[1]; - - // adc readings are only 20-bit when the IIR filter is enabled, otherwise - // the size depends on the oversample settings (osrs_X). - - double temperature = calc_temp_comp_1 ( temp_adc , &bme680 ); - printf("temperature: %g oC (floating-point)\n", temperature); - - int temperature2 = calc_temp_comp_2 (temp_adc, &bme680 ); - printf("temperature: %d oC (integer x100)\n", temperature2); - double pressure = calc_press_comp_1 ( press_adc , &bme680 ); - printf("pressure: %g Pa or %g bar (floating-point)\n", pressure, pressure/1e5); - - int pressure2 = calc_press_comp_2 (press_adc , &bme680 ); - printf("pressure: %d Pa (integer)\n", pressure2); - - double humidity = calc_hum_comp_1 ( hum_adc, &bme680 ); - printf("humidity: %g (floating-point)\n", humidity); - - int humidity2 = calc_hum_comp_2 ( hum_adc, &bme680 ); - printf("humidity: %d (integer x1000)\n", humidity2); - - close(fd); + return 0; +} + +// STUBS + +int linux_i2c_init (void) { + puts("linux_i2c_init"); + int ret = i2c_init(DEVICE, ADDRESS); + if (ret > 0) { + i2c_dev_fd = ret; + return 0; + } + + return 1; +} + +int linux_i2c_read (uint8_t reg, uint8_t *dst, uint32_t size) { + puts("linux_i2c_read"); + if (i2c_read_reg(i2c_dev_fd, reg, (uint8_t)size, dst) != 0) { + printf("panic read: %d %p %d\n", reg, dst, size); + return 1; + } + return 0; +} + +int linux_i2c_write (uint8_t reg, uint8_t *src, uint32_t size) { + puts("linux_i2c_write"); + if (i2c_write_reg(i2c_dev_fd, reg, *src) != 0) { + puts("panic!"); + return 1; + } + return 0; +} + +int linux_i2c_deinit (void) { + close(i2c_dev_fd); return 0; } diff --git a/registers.h b/registers.h new file mode 100644 index 0000000..1566ec3 --- /dev/null +++ b/registers.h @@ -0,0 +1,67 @@ +#ifndef REGISTERS_H +#define REGISTERS_H + +#define REG_SPI_PAGE(v) ((v > 0x7F) ? 0 : 1) + +#define REG_STATUS 0x73 +#define REG_RESET 0xE0 +#define REG_ID 0xD0 +#define REG_CONFIG 0x75 +#define REG_CTRL_MEAS 0x74 +#define REG_CTRL_HUM 0x72 + +#define REG_CTRL_GAS_1 0x71 +#define REG_CTRL_GAS_0 0x70 + +#define REG_GAS_WAIT_9 0x6D +#define REG_GAS_WAIT_8 0x6C +#define REG_GAS_WAIT_7 0x6B +#define REG_GAS_WAIT_6 0x6A +#define REG_GAS_WAIT_5 0x69 +#define REG_GAS_WAIT_4 0x68 +#define REG_GAS_WAIT_3 0x67 +#define REG_GAS_WAIT_2 0x66 +#define REG_GAS_WAIT_1 0x65 +#define REG_GAS_WAIT_0 0x64 + +#define REG_RES_HEAT_9 0x63 +#define REG_RES_HEAT_8 0x62 +#define REG_RES_HEAT_7 0x61 +#define REG_RES_HEAT_6 0x60 +#define REG_RES_HEAT_5 0x5F +#define REG_RES_HEAT_4 0x5E +#define REG_RES_HEAT_3 0x5D +#define REG_RES_HEAT_2 0x5C +#define REG_RES_HEAT_1 0x5B +#define REG_RES_HEAT_0 0x5A + +#define REG_IDAC_HEAT_9 0x59 +#define REG_IDAC_HEAT_8 0x58 +#define REG_IDAC_HEAT_7 0x57 +#define REG_IDAC_HEAT_6 0x56 +#define REG_IDAC_HEAT_5 0x55 +#define REG_IDAC_HEAT_4 0x54 +#define REG_IDAC_HEAT_3 0x53 +#define REG_IDAC_HEAT_2 0x52 +#define REG_IDAC_HEAT_1 0x51 +#define REG_IDAC_HEAT_0 0x50 + +#define REG_GAS_R_LSB 0x2B +#define REG_GAS_R_MSB 0x2A + +#define REG_HUM_LSB 0x26 +#define REG_HUM_MSB 0x25 + +#define REG_TEMP_XLSB 0x24 +#define REG_TEMP_LSB 0x23 +#define REG_TEMP_MSB 0x22 + +#define REG_PRESS_XLSB 0x21 +#define REG_PRESS_LSB 0x20 +#define REG_PRESS_MSB 0x1F + +#define REG_EAS_STATUS 0x1D + + + +#endif