From 32aedbbb135a86d2e2d6168ada94c6d39fd59719 Mon Sep 17 00:00:00 2001 From: "R.P.Clark" Date: Sun, 17 Sep 2023 21:31:02 +0100 Subject: [PATCH] first commit --- Makefile | 2 + README.md | 2 + bme680.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bme680.h | 48 ++++++++++++ i2c.c | 77 +++++++++++++++++++ i2c.h | 9 +++ main.c | 16 ++++ 7 files changed, 371 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 bme680.c create mode 100644 bme680.h create mode 100644 i2c.c create mode 100644 i2c.h create mode 100644 main.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd97cd9 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + gcc -O2 -std=c99 -Wall -Wextra main.c bme680.c i2c.c -o bme680 diff --git a/README.md b/README.md new file mode 100644 index 0000000..520ca8b --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# bme680 +test diff --git a/bme680.c b/bme680.c new file mode 100644 index 0000000..6a82552 --- /dev/null +++ b/bme680.c @@ -0,0 +1,217 @@ +#include "bme680.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 +}; + +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 +}; + +const 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 double calc_temp_comp_1 ( uint32_t temp_adc , 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; + temp_comp = (var1 + var2) / 5120.0; + bme680->temp_comp_double = temp_comp; + return temp_comp; +} + +static int calc_temp_comp_2 (uint32_t temp_adc, 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; +} + +static double calc_press_comp_1 ( uint32_t press_adc , bme680_t *bme680 ) { + + double var1, var2, var3, press_comp; + bme680_calibration *cal; + + cal = &bme680->cal; + + var1 = (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; + 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); + 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; +} + + +static int calc_press_comp_2 ( uint32_t press_adc , bme680_t *bme680 ) { + + uint32_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 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * + ((int32_t)cal->par_p3 << 5)) >> 3) + (((int32_t)cal->par_p2 * var1) >> 1); + var1 = var1 >> 18; + var1 = ((32768 + var1) * (int32_t)cal->par_p1) >> 15; + press_comp = 1048576 - press_adc; // says "press_raw" in the bosch example + 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) * + (press_comp >> 3)) >> 13)) >> 12; + var2 = ((int32_t)(press_comp >> 2) * (int32_t)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; + +} + +static double calc_hum_comp_1 ( uint32_t hum_adc , bme680_t *bme680 ) { + + double var1, var2, var3, var4, hum_comp; + bme680_calibration *cal; + cal = &bme680->cal; + + var1 = hum_adc - (((double)cal->par_h1 * 16.0) + (((double)cal->par_h3 / 2.0) * bme680->temp_comp_double)); + var2 = var1 * (((double)cal->par_h2 / 262144.0) * (1.0 + (((double)cal->par_h4 / 16384.0) * + bme680->temp_comp_double) + (((double)cal->par_h5 / 1048576.0) * + bme680->temp_comp_double * bme680->temp_comp_double))); + var3 = (double)cal->par_h6 / 16384.0; + var4 = (double)cal->par_h7 / 2097152.0; + hum_comp = var2 + ((var3 + (var4 * bme680->temp_comp_double)) * var2 * var2); + bme680->hum_comp_double = hum_comp; + return hum_comp; +} + + +static 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; + + 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) / + ((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; + 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; +} + + + diff --git a/bme680.h b/bme680.h new file mode 100644 index 0000000..a11c355 --- /dev/null +++ b/bme680.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +typedef struct { + uint16_t par_t1; + uint16_t par_t2; + uint16_t par_t3; // 8 bit word + uint16_t par_p1; + uint16_t par_p2; + uint16_t par_p3; // 8 bit word + uint16_t par_p4; + uint16_t par_p5; + uint16_t par_p6; // 8 bit word + uint16_t par_p7; // 8 bit word + uint16_t par_p8; + uint16_t par_p9; + uint16_t par_p10; //8 bit word + uint16_t par_h1; + uint16_t par_h2; + uint16_t par_h3; + uint16_t par_h4; + uint16_t par_h5; + uint16_t par_h6; + uint16_t par_h7; + 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; + + double temp_comp_double; + int temp_comp_int; + + double press_comp_double; + int press_comp_int; + + double hum_comp_double; + int hum_comp_int; + + bme680_calibration cal; + +} bme680_t; diff --git a/i2c.c b/i2c.c new file mode 100644 index 0000000..4ba058e --- /dev/null +++ b/i2c.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#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; + + fd = open(dev, O_RDWR); + if (fd < 0) { + fprintf(stderr, "could not open device: %s\n", dev); + return -1; + } + + if (ioctl(fd, I2C_SLAVE, addr) < 0) { + fprintf(stderr, "failed to acquire bus/talk to slave\n"); + close(fd); + return -1; + } + + return fd; +} + + +int i2c_read_reg(int fd, uint8_t reg, uint8_t length, uint8_t *buf) { + + uint8_t cmd[2] = {reg, 0x00}; + write(fd, cmd, 2); + if (read(fd, buf, length) != length) { + fprintf(stderr, "error read()\n"); + return 1; + } + return 0; +} + +uint8_t i2c_read_reg2(int fd, uint8_t reg) { + uint8_t buf; + i2c_read_reg(fd, reg, 1, &buf); + return buf; +} + +int i2c_write_reg(int fd, uint8_t reg, uint8_t value) { + + uint8_t cmd[2] = {reg, value}; + if (write(fd, cmd, 2) != 2) { + fprintf(stderr, "error write()\n"); + return 1; + } + 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/i2c.h b/i2c.h new file mode 100644 index 0000000..753c63a --- /dev/null +++ b/i2c.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +int i2c_init(const char *, uint8_t); +int i2c_read_reg(int, uint8_t, uint8_t, uint8_t *); +uint8_t i2c_read_reg2(uint8_t, uint8_t); +int i2c_write_reg(int, uint8_t, uint8_t); + diff --git a/main.c b/main.c new file mode 100644 index 0000000..235afe1 --- /dev/null +++ b/main.c @@ -0,0 +1,16 @@ +#include +#include "bme680.h" +#include "i2c.h" + +#define DEVICE "/dev/i2c-1" +#define ADDRESS 0x77 + +int main(){ + + int fd = i2c_init(DEVICE, ADDRESS); + + printf("%X\n", i2c_read_reg2(fd, 0xD0)); + + close(fd); + return 0; +}