432|2

290

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

【2024 DigiKey 创意大赛】智能睡眠环境监测--05采集温湿度和气压传感器数据 [复制链接]

 

背景

由于智能睡眠环境监测,最主要的数据是温度、湿度、空气质量、气压,那么最好是采用四合一的传感器,那么博世正好有这一款传感器BME680,因此本篇文章主要是记录一下驱动BME680。

一、BME680传感器介绍

BME680是一款气压、气体、温湿度的四合一传感器,主要特性有低功耗,能够计算出空气质量。

并且1s内能够显示计算出气体电阻。数据手册的特性如下图:

 

二、编写代码

主要参照网络大神使用wiringPi库进行I2C驱动,大神,直接造了轮子,就拿来用了。个人主要是把微雪的代码拿来用就可以了。

参考链接:BME680 Environmental Sensor - Waveshare Wiki

主要代码如下:

#include "main.h"

#define BME68X_VALID_DATA  UINT8_C(0xB0)

//Raspberry 5 platform's default I2C device file
#define IIC_Dev  "/dev/i2c-1"

struct bme68x_dev dev;

int fd;

void user_delay_us(uint32_t period, void *intf_ptr)
{
  usleep(period);
}

int8_t user_i2c_read(uint8_t reg_addr, uint8_t *data, uint32_t len,void *intf_ptr)
{
  write(fd, ®_addr,1);
  read(fd, data, len);
  return 0;
}

int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *data, uint32_t len,void *intf_ptr)
{
  int8_t *buf;
  buf = malloc(len +1);
  buf[0] = reg_addr;
  memcpy(buf +1, data, len);
  write(fd, buf, len +1);
  free(buf);
  return 0;
}

void print_sensor_data(struct bme68x_data *comp_data)
{
#ifdef BME68X_USE_FPU
	printf("temperature:%0.2f*C   pressure:%0.2fhPa   humidity:%0.2f%%   Gas resistance:%0.2f ohm\r\n",\
    comp_data->temperature, comp_data->pressure/100, comp_data->humidity, comp_data->gas_resistance         );
    sysData.envTemp = comp_data->temperature;
    sysData.envHumidity = comp_data->humidity;
    sysData.airPressure = comp_data->pressure / 100;
    //sysData.airQuality = comp_data->gas_resistance / 100;
    printf("\r\b\r");
#else
	printf("temperature:%ld*C   pressure:%ldhPa   humidity:%ld%%   Gas resistance:%lu ohm\r\n",comp_data->temperature, comp_data->pressure/100, comp_data->humidity, comp_data->gas_resistance         );
    printf("\r\b\r");
#endif
}

int8_t stream_sensor_data_forced_mode(struct bme68x_dev *dev)
{
    int8_t rslt;
	uint8_t n_fields;
    uint32_t del_period;
	struct bme68x_conf conf;
    struct bme68x_heatr_conf heatr_conf;
    struct bme68x_data comp_data;

    /* Recommended mode of operation: Indoor navigation */
    conf.os_hum = BME68X_OS_1X;
    conf.os_pres = BME68X_OS_16X;
    conf.os_temp = BME68X_OS_2X;
    conf.filter = BME68X_FILTER_SIZE_15;

    rslt = bme68x_set_conf(&conf, dev);
    dev->delay_us(40*1000,dev->intf_ptr);
    
    heatr_conf.enable = BME68X_ENABLE;
    heatr_conf.heatr_temp = 300;
    heatr_conf.heatr_dur = 100;
    
    rslt = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &heatr_conf, dev);
    dev->delay_us(40*1000,dev->intf_ptr);
    
    printf("Temperature           Pressure             Humidity             Gas resistance\r\n");
    /* Continuously stream sensor data */
    rslt = bme68x_set_op_mode(BME68X_FORCED_MODE, dev);
    /* Wait for the measurement to complete and print data [url=home.php?mod=space&uid=1140227]@25Hz[/url] */
    del_period = bme68x_get_meas_dur(BME68X_FORCED_MODE, &conf, dev) + (heatr_conf.heatr_dur * 1000);
    dev->delay_us(del_period*5, dev->intf_ptr);
    rslt = bme68x_get_data(BME68X_FORCED_MODE, &comp_data, &n_fields, dev);
    if(n_fields)
    {
        print_sensor_data(&comp_data);
    }
    return rslt;
}


int8_t stream_sensor_data_parallel_mode(struct bme68x_dev *dev)
{
	int8_t rslt;
    uint8_t n_fields;
	struct bme68x_conf conf;
    struct bme68x_heatr_conf heatr_conf;
	struct bme68x_data comp_data[3];
    
    uint16_t temp_prof[10] = { 320, 100, 100, 100, 200, 200, 200, 320, 320, 320 };
    uint16_t mul_prof[10] = { 5, 2, 10, 30, 5, 5, 5, 5, 5, 5 };

	/* Recommended mode of operation: Indoor navigation */
	conf.os_hum = BME68X_OS_1X;
    conf.os_pres = BME68X_OS_16X;
    conf.os_temp = BME68X_OS_2X;
    conf.filter = BME68X_FILTER_SIZE_15;
	conf.odr = BME68X_ODR_62_5_MS;

	rslt = bme68x_set_conf(&conf, dev);
    dev->delay_us(40*1000,dev->intf_ptr);
    
    heatr_conf.enable = BME68X_ENABLE;
    heatr_conf.heatr_temp_prof = temp_prof;
    heatr_conf.heatr_dur_prof = mul_prof;

    heatr_conf.shared_heatr_dur = 140 - (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &conf, dev) / 1000);

    heatr_conf.profile_len = 10;
    
    rslt = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &heatr_conf, dev);
    dev->delay_us(40*1000,dev->intf_ptr);
    
    rslt = bme68x_set_op_mode(BME68X_PARALLEL_MODE, dev);
    dev->delay_us(40*1000,dev->intf_ptr);

	printf("Temperature           Pressure             Humidity             Gas resistance\r\n");
	while (1) {
		/* Delay while the sensor completes a measurement */
		dev->delay_us(70*1000,dev->intf_ptr);
        rslt = bme68x_get_data(BME68X_FORCED_MODE, comp_data, &n_fields, dev);
        for (uint8_t i = 0; i < n_fields; i++)
        {
            if (comp_data[i].status == BME68X_VALID_DATA)
            {
                print_sensor_data(&comp_data[i]);
            }
        }
	}

	return rslt;
}

void bme680Init(void) {
    
    static uint8_t dev_addr=BME68X_I2C_ADDR_HIGH;
    int8_t rslt = BME68X_OK;
    int8_t bsec_ret = BSEC_OK;
    uint8_t bsec_state[BSEC_MAX_STATE_BLOB_SIZE] = {0};
    uint8_t bsec_config[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0};
    uint8_t work_buffer[BSEC_MAX_WORKBUFFER_SIZE] = {0};
    int bsec_state_len, bsec_config_len;

    if ((fd = open(IIC_Dev, O_RDWR)) < 0) {
        printf("Failed to open the i2c bus");
        exit(1);
    }
    if (ioctl(fd, I2C_SLAVE, 0x77) < 0) {
        printf("Failed to acquire bus access and/or talk to slave.\n");
        exit(1);
    }
    //dev.dev_id = BME68X_I2C_ADDR_PRIM;//0x76
    dev.intf_ptr = &dev_addr; //0x77
    dev.intf = BME68X_I2C_INTF;
    dev.read = user_i2c_read;
    dev.write = user_i2c_write;
    dev.delay_us = user_delay_us;

    rslt = bme68x_init(&dev);
    printf("\r\n BME68X Init Result is:%d \r\n",rslt);

    /* Initialize BSEC library */
    bsec_ret = bsec_init();
    if (bsec_ret != BSEC_OK)
    {
        printf("\r\n bsec_init Result is:%d \r\n",rslt);
    }

   /* Load library config, if available */
    bsec_config_len = config_load(bsec_config, sizeof(bsec_config));
    if (bsec_config_len != 0)
    {       
        bsec_ret = bsec_set_configuration(bsec_config, bsec_config_len, work_buffer, sizeof(work_buffer));     
        if (bsec_ret != BSEC_OK)
        {
            return ret;
        }
    }
    
    /* Load previous library state, if available */
    bsec_state_len = state_load(bsec_state, sizeof(bsec_state));
    if (bsec_state_len != 0)
    {       
        bsec_ret = bsec_set_state(bsec_state, bsec_state_len, work_buffer, sizeof(work_buffer));     
        if (bsec_ret != BSEC_OK)
        {
            return ret;
        }
    }
    
    /* Set temperature offset */
    //bme680_temperature_offset_g = temperature_offset;
    
    /* Call to the function which sets the library with subscription information */
    bsec_ret = bme680_bsec_update_subscription(BSEC_SAMPLE_RATE_LP);
    if (bsec_ret != BSEC_OK)
    {
        return ret;
    }
}
void bme680_test(void)
{
  stream_sensor_data_forced_mode(&dev);
  //stream_sensor_data_parallel_mode(&dev);
}

三、硬件连接

使用树莓派的I2C1,将如图的I2C1的引脚与BME680的I2C1的SDA&SCL连接即可。

 

四、验证

1、使能I2C

1) 运行sudo raspi-config

选择Interface Option

 

2)选择I2C接口

 

3)进行使能即可

 

2、检测I2C器件

1)查看i2c设备

ls /dev/ | grep i2c*

 

2)安装i2c-tools

sudo apt-get install -y i2c-tools

3)检测IC设备器件

一开始全是0,找不到数据,进行如下操作就可以了。记得重启

sudo modprobe -r i2c_bcm2708 #卸载设备 -r代表remove sudo modprobe i2c_bcm2708 #重新载入设备

检测到BME680的器件地址为0x77,与实际器件地址一致

 

3、编译代码

gcc -Wall *.c -o bme68x -lwiringPi

4、运行

运行之后可以看到打印气体电阻、气压、温湿度的值

 

5、与OLED联合显示

 

最新回复

温度、湿度、空气质量、气压,四合一的传感器,以后集成传感器可能就是一种趋势了   详情 回复 发表于 2024-9-26 07:29
点赞 关注
个人签名

阅读改变人生

 
 

回复
举报

6828

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

温度、湿度、空气质量、气压,四合一的传感器,以后集成传感器可能就是一种趋势了

点评

是的,主要是尺寸小,功能强大。不过价格贵  详情 回复 发表于 2024-9-26 10:52
 
 
 

回复

290

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
Jacktang 发表于 2024-9-26 07:29 温度、湿度、空气质量、气压,四合一的传感器,以后集成传感器可能就是一种趋势了

是的,主要是尺寸小,功能强大。不过价格贵

个人签名

阅读改变人生

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表