diff --git a/Makefile b/Makefile index fd97cd9..7534cf2 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,2 @@ all: - gcc -O2 -std=c99 -Wall -Wextra main.c bme680.c i2c.c -o bme680 + gcc -O2 -std=gnu99 -Wall -Wextra main.c bme680.c i2c.c -o bme680 diff --git a/README.md b/README.md index 520ca8b..dd19efd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,34 @@ # bme680 -test + +Temperature OK, humidity OK, pressure a bit wonky. Not sure why ! + +``` +$ ./bme680 +61 +par_t1: 26203 +par_t2: 26519 +par_t3: 3 +par_p1: 35008 +par_p2: 55252 +par_p3: 88 +par_p4: 9692 +par_p5: 65334 +par_p6: 30 +par_p7: 24 +par_p8: 65020 +par_p9: 62067 +par_p10: 30 +par_h1: 794 +par_h2: 4003 +par_h3: 0 +par_h4: 45 +par_h5: 20 +par_h6: 120 +par_h7: 156 +temperature: 22.8591 oC (floating-point) +temperature: 2286 oC (integer) +pressure: 146510 Pa (floating-point) +pressure: 60428 Pa (integer) +humidity: 639.392 (floating-point) +humidity: 639001 (integer) +``` diff --git a/bme680.c b/bme680.c index 6a82552..f2bb6ea 100644 --- a/bme680.c +++ b/bme680.c @@ -1,4 +1,6 @@ #include "bme680.h" +#include "i2c.h" +#include const double const_array1[16] = { 1, @@ -77,7 +79,7 @@ const int const_array2_int[16] = { }; -static double calc_temp_comp_1 ( uint32_t temp_adc , bme680_t *bme680) { +double calc_temp_comp_1 ( uint32_t temp_adc , bme680_t *bme680) { double var1, var2, temp_comp; bme680_calibration *cal; @@ -96,7 +98,7 @@ static double calc_temp_comp_1 ( uint32_t temp_adc , bme680_t *bme680) { return temp_comp; } -static int calc_temp_comp_2 (uint32_t temp_adc, bme680_t *bme680) { +int calc_temp_comp_2 (uint32_t temp_adc, bme680_t *bme680) { int32_t var1, var2, var3, temp_comp; bme680_calibration *cal; @@ -112,7 +114,7 @@ static int calc_temp_comp_2 (uint32_t temp_adc, bme680_t *bme680) { return temp_comp; } -static double calc_press_comp_1 ( uint32_t press_adc , bme680_t *bme680 ) { +double calc_press_comp_1 ( uint32_t press_adc , bme680_t *bme680 ) { double var1, var2, var3, press_comp; bme680_calibration *cal; @@ -137,7 +139,7 @@ static double calc_press_comp_1 ( uint32_t press_adc , bme680_t *bme680 ) { } -static int calc_press_comp_2 ( uint32_t press_adc , bme680_t *bme680 ) { +int calc_press_comp_2 ( uint32_t press_adc , bme680_t *bme680 ) { uint32_t var1, var2, var3, press_comp; bme680_calibration *cal; @@ -171,7 +173,7 @@ static int calc_press_comp_2 ( uint32_t press_adc , bme680_t *bme680 ) { } -static double calc_hum_comp_1 ( uint32_t hum_adc , bme680_t *bme680 ) { +double calc_hum_comp_1 ( uint32_t hum_adc , bme680_t *bme680 ) { double var1, var2, var3, var4, hum_comp; bme680_calibration *cal; @@ -189,7 +191,7 @@ static double calc_hum_comp_1 ( uint32_t hum_adc , bme680_t *bme680 ) { } -static int calc_hum_comp_2 ( uint32_t hum_adc , bme680_t *bme680 ) { +int calc_hum_comp_2 ( uint32_t hum_adc , bme680_t *bme680 ) { uint32_t var1, var2, var3, var4, var5, var6, temp_scaled, hum_comp; bme680_calibration *cal; @@ -213,5 +215,114 @@ static int calc_hum_comp_2 ( uint32_t hum_adc , bme680_t *bme680 ) { return hum_comp; } +int bme680_calibrate ( int fd , bme680_calibration *cal ) { + + 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 |= i2c_read_reg(fd, 0x8A, 2, buffer); + cal->par_t2 = (buffer[1] << 8) | buffer[0]; + + err |= i2c_read_reg(fd, 0x8C, 1, buffer); + cal->par_t3 = buffer[0]; + + // pressure + + err |= i2c_read_reg(fd, 0x8E, 2, buffer); + 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 |= i2c_read_reg(fd, 0x92, 1, buffer); + cal->par_p3 = buffer[0]; + + err |= i2c_read_reg(fd, 0x94, 2, buffer); + 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 |= i2c_read_reg(fd, 0x99, 1, buffer); + cal->par_p6 = buffer[0]; + + err |= i2c_read_reg(fd, 0x98, 1, buffer); // strange order + cal->par_p7 = buffer[0]; + + err |= i2c_read_reg(fd, 0x9C, 2, buffer); + 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 |= i2c_read_reg(fd, 0xA0, 1, buffer); + cal->par_p10 = buffer[0]; + + // humidity + + err |= i2c_read_reg(fd, 0xE2, 2, buffer); + cal->par_h1 = (buffer[1] << 4) | (buffer[0] & 0xF); + + err |= i2c_read_reg(fd, 0xE1, 2, buffer); + cal->par_h2 = (buffer[1] << 4) | ((buffer[0] >> 4) & 0xF); + + err |= i2c_read_reg(fd, 0xE4, 1, buffer); + cal->par_h3 = buffer[0]; + + err |= i2c_read_reg(fd, 0xE5, 1, buffer); + cal->par_h4 = buffer[0]; + + err |= i2c_read_reg(fd, 0xE6, 1, buffer); + cal->par_h5 = buffer[0]; + + err |= i2c_read_reg(fd, 0xE7, 1, buffer); + cal->par_h6 = buffer[0]; + + err |= i2c_read_reg(fd, 0xE8, 1, buffer); + cal->par_h7 = buffer[0]; + + // gas + + err |= i2c_read_reg(fd, 0xED, 1, buffer); + cal->par_g1 = buffer[0]; + + err |= i2c_read_reg(fd, 0xEB, 2, buffer); + cal->par_g2 = (buffer[1] << 8) | buffer[0]; + + err |= i2c_read_reg(fd, 0xEE, 1, buffer); + cal->par_g2 = buffer[0]; + + // todo more + + return err; +} + +void print_calibration ( bme680_calibration *cal ) { + printf("par_t1: %d\n", cal->par_t1); + printf("par_t2: %d\n", cal->par_t2); + printf("par_t3: %d\n", cal->par_t3); + printf("par_p1: %d\n", cal->par_p1); + printf("par_p2: %d\n", cal->par_p2); + printf("par_p3: %d\n", cal->par_p3); + printf("par_p4: %d\n", cal->par_p4); + printf("par_p5: %d\n", cal->par_p5); + printf("par_p6: %d\n", cal->par_p6); + printf("par_p7: %d\n", cal->par_p7); + printf("par_p8: %d\n", cal->par_p8); + printf("par_p9: %d\n", cal->par_p9); + printf("par_p10: %d\n", cal->par_p10); + printf("par_h1: %d\n", cal->par_h1); + printf("par_h2: %d\n", cal->par_h2); + printf("par_h3: %d\n", cal->par_h3); + printf("par_h4: %d\n", cal->par_h4); + 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 a11c355..f96c0ed 100644 --- a/bme680.h +++ b/bme680.h @@ -46,3 +46,16 @@ typedef struct { bme680_calibration cal; } bme680_t; + + + +void print_calibration(bme680_calibration *); +int bme680_calibrate(int, bme680_calibration *); +int calc_hum_comp_2(uint32_t, bme680_t *); +double calc_hum_comp_1(uint32_t, bme680_t *); +int calc_press_comp_2(uint32_t, bme680_t *); +double calc_press_comp_1(uint32_t, bme680_t *); +int calc_temp_comp_2(uint32_t, bme680_t *); +double calc_temp_comp_1(uint32_t, bme680_t*); + + diff --git a/i2c.c b/i2c.c index 4ba058e..0fb19a2 100644 --- a/i2c.c +++ b/i2c.c @@ -7,9 +7,6 @@ #include #include -#define MY_DEVICE "/dev/i2c-1" -#define MY_DEVICE_ADDRESS 0x77 - int i2c_init(const char *dev, uint8_t addr) { int fd = -1; @@ -56,22 +53,3 @@ int i2c_write_reg(int fd, uint8_t reg, uint8_t value) { return 0; } -int main2(void) { - - - int res; - uint8_t cmd_buf[2] = {0x00, 0x00}; - int fd = i2c_init(MY_DEVICE, MY_DEVICE_ADDRESS); - - - if (i2c_read_reg(fd, 0xD0, 1, (uint8_t *)&res) != 0) { - fprintf(stderr, "ddd\n"); - } - - printf("%X\n", res); - - printf("%X\n", i2c_read_reg2(fd, 0xD0)); - - close(fd); - return 0; -} diff --git a/main.c b/main.c index 235afe1..9251147 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ #include #include "bme680.h" #include "i2c.h" +#include #define DEVICE "/dev/i2c-1" #define ADDRESS 0x77 @@ -8,8 +9,83 @@ 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. 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 = 0b011; + 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 + } + + // now read the temp/press/hum adc and convert in order. + uint32_t temp_adc, press_adc, hum_adc; + + + 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)\n", temperature2); + + + double pressure = calc_press_comp_1 ( press_adc , &bme680 ); + printf("pressure: %g Pa (floating-point)\n", pressure); + + 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)\n", humidity2); close(fd); return 0;