树莓派开发笔记(八):GPIO口的I2C使用(BME280三合一传感器:温度、湿度、气压测量)

简介: 树莓派开发笔记(八):GPIO口的I2C使用(BME280三合一传感器:温度、湿度、气压测量)

若该文为原创文章,未经允许不得转载

原博主博客地址:https://blog.csdn.net/qq21497936

原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062

本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79775665

各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)

树莓派开发专栏(点击传送门)

上一篇:《树莓派开发笔记(七):GPIO口的SPI使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度)

下一篇:《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)

 

前话

前面介绍了SPI的使用,本章节我们开发GPIO口的I2C使用,同样适用BME280三合一传感器,采集气压、温度、适度,计算海拔高度。

 

Demo:GPIO口的I2C通讯

I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向:

  • 如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;
  • 如果主机要接收从器件的数据,则主机器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下,主机主要是负责产生定时时钟和终止数据传送。

BME280

BME280是一款集成温度、湿度、气压,三位一体的环境传感器。具有高精度,多功能,小尺寸等特点,如下图:

BME280模块,设备地址默认为0x77。下面是读取数据的指令,数据的读出是从0xf70xfc读做(温度和压力)或从0xf70xfe(温度、压力、湿度等)数据以无符号形式读出。

制指令集,如下图:

读取数据指令集,分为压力,温度,适度,如下图:

开启I2C接口

sudo raspi-config

按照下图步骤选取

然后重启。

查看系统是否启动i2c,如下图:

电路原理图

检测I2C设备是否在线

   我们按照图纸连接好后,使用三方查看设备是否在线来判断设备是否正常连接。

sudo apt-get install i2c-tools
sudo i2cdetect -y 1

注意:笔者对传感器不连接电源进行测试,只连接通讯的I2C线和GND(断开VCC,使用该指令也检测不到,但是程序用wiring库却可以读到,具体原因可能是供电不足(不接VCC也供电但低于3.3V)和指令检测方式的我呢提,笔者没有细究。总之,为保持硬件稳定,需要让指令检测到才算可靠。

关键代码

初始化代码

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    _bme280.initPressureTemperatureMode();
    _bme280.initHumidity();
    startTimer(1000);
}

每隔1s读取数据

void MainWindow::timerEvent(QTimerEvent *event)
{
    ui->label_i2cP->setText(QString("%1 Pa").arg(_bme280.getPressure()));
    ui->label_i2cT->setText(QString("%1 ℃").arg(_bme280.getTemperatureC()));
    ui->label_i2cH->setText(QString("%1 %").arg(_bme280.getHumidity()));
    ui->label_i2cA->setText(QString("%1 m").arg(_bme280.getAltitudeMeters()));
}

模块代码

bme280.h

#ifndef BME280_H
#define BME280_H
#include <QObject>
#include "i2c.h"
//Register names:
#define BME280_DIG_T1_LSB_REG     0x88
#define BME280_DIG_T1_MSB_REG     0x89
#define BME280_DIG_T2_LSB_REG     0x8A
#define BME280_DIG_T2_MSB_REG     0x8B
#define BME280_DIG_T3_LSB_REG     0x8C
#define BME280_DIG_T3_MSB_REG     0x8D
#define BME280_DIG_P1_LSB_REG     0x8E
#define BME280_DIG_P1_MSB_REG     0x8F
#define BME280_DIG_P2_LSB_REG     0x90
#define BME280_DIG_P2_MSB_REG     0x91
#define BME280_DIG_P3_LSB_REG     0x92
#define BME280_DIG_P3_MSB_REG     0x93
#define BME280_DIG_P4_LSB_REG     0x94
#define BME280_DIG_P4_MSB_REG     0x95
#define BME280_DIG_P5_LSB_REG     0x96
#define BME280_DIG_P5_MSB_REG     0x97
#define BME280_DIG_P6_LSB_REG     0x98
#define BME280_DIG_P6_MSB_REG     0x99
#define BME280_DIG_P7_LSB_REG     0x9A
#define BME280_DIG_P7_MSB_REG     0x9B
#define BME280_DIG_P8_LSB_REG     0x9C
#define BME280_DIG_P8_MSB_REG     0x9D
#define BME280_DIG_P9_LSB_REG     0x9E
#define BME280_DIG_P9_MSB_REG     0x9F
#define BME280_DIG_H1_REG       0xA1
#define BME280_CHIP_ID_REG        0xD0 //Chip ID Online value is 0x60 all the time
#define BME280_RST_REG          0xE0 //Softreset Reg
#define BME280_DIG_H2_LSB_REG     0xE1
#define BME280_DIG_H2_MSB_REG     0xE2
#define BME280_DIG_H3_REG       0xE3
#define BME280_DIG_H4_MSB_REG     0xE4
#define BME280_DIG_H4_LSB_REG     0xE5
#define BME280_DIG_H5_MSB_REG     0xE6
#define BME280_DIG_H6_REG       0xE7
#define BME280_CTRL_HUMIDITY_REG    0xF2 //Ctrl Humidity Reg
#define BME280_STAT_REG         0xF3 //Status Reg
#define BME280_CTRL_MEAS_REG      0xF4 //Ctrl Measure Reg
#define BME280_CONFIG_REG       0xF5 //Configuration Reg
#define BME280_PRESSURE_MSB_REG     0xF7 //Pressure MSB
#define BME280_PRESSURE_LSB_REG     0xF8 //Pressure LSB
#define BME280_PRESSURE_XLSB_REG    0xF9 //Pressure XLSB
#define BME280_TEMPERATURE_MSB_REG    0xFA //Temperature MSB
#define BME280_TEMPERATURE_LSB_REG    0xFB //Temperature LSB
#define BME280_TEMPERATURE_XLSB_REG   0xFC //Temperature XLSB
#define BME280_HUMIDITY_MSB_REG     0xFD //Humidity MSB
#define BME280_HUMIDITY_LSB_REG     0xFE //Humidity LSB
class BME280 : public QObject
{
    Q_OBJECT
public:
    enum PRESSURE_OVERSAMPLING
    {
        PRESSURE_OVERSAMPLING_SKIPPED         = 0x00,
        PRESSURE_OVERSAMPLING_PLUS_ONE        = 0x01,
        PRESSURE_OVERSAMPLING_PLUS_TWO        = 0x02,
        PRESSURE_OVERSAMPLING_PLUS_FOUR       = 0x03,
        PRESSURE_OVERSAMPLING_PLUS_EIGHT      = 0x04,
        PRESSURE_OVERSAMPLING_PLUS_SIXTEEN    = 0x05
    };
    enum TEMPERATURE_OVERSAMPLING
    {
        TEMPERATURE_OVERSAMPLING_SKIPPED      = 0x00,
        TEMPERATURE_OVERSAMPLING_PLUS_ONE     = 0x01,
        TEMPERATURE_OVERSAMPLING_PLUS_TWO     = 0x02,
        TEMPERATURE_OVERSAMPLING_PLUS_FOUR    = 0x03,
        TEMPERATURE_OVERSAMPLING_PLUS_EIGHT   = 0x04,
        TEMPERATURE_OVERSAMPLING_PLUS_SIXTEEN = 0x05
    };
    enum MODE_OF_PRESSURE_TEMPERATUR
    {
        MODE_OF_PRESSURE_TEMPERATUR_SLEEP     = 0x00,
        MODE_OF_PRESSURE_TEMPERATUR_FORCED    = 0x01,
        MODE_OF_PRESSURE_TEMPERATUR_MORMAL    = 0x03
    };
    enum HUMIDITY_OVERSAMPLING
    {
        HUMIDITY_OVERSAMPLING_SKIPPED        = 0x00,
        HUMIDITY_OVERSAMPLING_PLUS_ONE       = 0x01,
        HUMIDITY_OVERSAMPLING_PLUS_TWO       = 0x02,
        HUMIDITY_OVERSAMPLING_PLUS_FOUR      = 0x03,
        HUMIDITY_OVERSAMPLING_PLUS_EIGHT     = 0x04,
        HUMIDITY_OVERSAMPLING_PLUS_SIXTEEN   = 0x05
    };
    struct Calibration
    {
        uint16_t dig_T1;
        int16_t dig_T2;
        int16_t dig_T3;
        uint16_t dig_P1;
        int16_t dig_P2;
        int16_t dig_P3;
        int16_t dig_P4;
        int16_t dig_P5;
        int16_t dig_P6;
        int16_t dig_P7;
        int16_t dig_P8;
        int16_t dig_P9;
        uint8_t dig_H1;
        int16_t dig_H2;
        uint8_t dig_H3;
        int16_t dig_H4;
        int16_t dig_H5;
        uint8_t dig_H6;
    };
public:
    explicit BME280(int devId = 0x77, QObject *parent = 0);
    bool isOnline();
    void initPressureTemperatureMode(
            PRESSURE_OVERSAMPLING p = PRESSURE_OVERSAMPLING_PLUS_ONE,
            TEMPERATURE_OVERSAMPLING t = TEMPERATURE_OVERSAMPLING_PLUS_ONE,
            MODE_OF_PRESSURE_TEMPERATUR m = MODE_OF_PRESSURE_TEMPERATUR_MORMAL);
    void initHumidity(HUMIDITY_OVERSAMPLING h = HUMIDITY_OVERSAMPLING_PLUS_ONE);
    void reset();
public slots:
    float getTemperatureC();
    float getTemperatureF();
    float getPressure();
    float getHumidity();
    float getAltitudeMeters();
    float getAltitudeFeet();
private:
    I2c _i2c;
    int _devId;
    Calibration _calibration;
    int32_t _tFine;
};
#endif // BME280_H

bme280.cpp

#include "bme280.h"
#include <QDebug>
BME280::BME280(int devId, QObject *parent)
    : QObject(parent),
      _devId(devId)
{
    _i2c.open(devId);
}
bool BME280::isOnline()
{
    // according to 0xD0 "id", value is 0x60
    return _i2c.readData(BME280_CHIP_ID_REG) == 0x60;
}
void BME280::initPressureTemperatureMode(BME280::PRESSURE_OVERSAMPLING p, BME280::TEMPERATURE_OVERSAMPLING t, BME280::MODE_OF_PRESSURE_TEMPERATUR m)
{
    uchar uc;
    _i2c.writeData(BME280_CTRL_MEAS_REG, uc);
    _i2c.readData(BME280_CTRL_MEAS_REG);
}
void BME280::initHumidity(BME280::HUMIDITY_OVERSAMPLING h)
{
    uchar uc;
    _i2c.writeData(BME280_CTRL_HUMIDITY_REG, uc);
}
void BME280::reset()
{
    _i2c.writeData(BME280_RST_REG, 0xB6);
}
float BME280::getTemperatureC()
{
    int32_t adc_T = ((uint32_t)_i2c.readData(BME280_TEMPERATURE_MSB_REG) << 12) | ((uint32_t)_i2c.readData(BME280_TEMPERATURE_LSB_REG) << 4) | ((_i2c.readData(BME280_TEMPERATURE_XLSB_REG) >> 4) & 0x0F);
    float output = (_tFine * 5 + 128) >> 8;
    output = output / 100;
    return output;
}
float BME280::getTemperatureF()
{
    float output = getTemperatureC();
    output = (output * 9) / 5 + 32;
    return output;
}
float BME280::getPressure()
{
   int32_t adc_P = ((uint32_t)_i2c.readData(BME280_PRESSURE_MSB_REG) << 12) | ((uint32_t)_i2c.readData(BME280_PRESSURE_LSB_REG) << 4) | ((_i2c.readData(BME280_PRESSURE_XLSB_REG) >> 4) & 0x0F);
    int64_t var1, var2, p_acc;
    p_acc = p_acc >> 8; // /256
    return (float)p_acc;
}
float BME280::getHumidity()
{
    int32_t adc_H = ((uint32_t)_i2c.readData(BME280_HUMIDITY_MSB_REG) << 8) | ((uint32_t)_i2c.readData(BME280_HUMIDITY_LSB_REG));
    int32_t var1;
    return (float)((var1>>12) >> 10);
}
float BME280::getAltitudeMeters()
{
    float heightOutput = 0;
    return heightOutput;
}
float BME280::getAltitudeFeet()
{
    float heightOutput = 0;
    heightOutput = getAltitudeMeters() * 3.28084;
    return heightOutput;
}

I2C模块代码

i2c.h

#ifndef I2C_H
#define I2C_H
#include <QObject>
#include <QByteArray>
class I2c : public QObject
{
    Q_OBJECT
public:
    explicit I2c(QObject *parent = 0);
signals:
public slots:
    bool open(uchar addr);
    void writeData(int reg, uchar data);
    uchar readData(int reg);
private:
    int _fd;
};
#endif // I2C_H

i2c.cpp

#include "i2c.h"
#include "wiringPi.h"
#include "wiringPiI2C.h"
#include <QDebug>
#include <QByteArray>
I2c::I2c(QObject *parent) : QObject(parent)
{
    wiringPiSetup();
    _fd = 0;
}
bool I2c::open(uchar addr)
{
_fd = wiringPiI2CSetup(addr);
}
void I2c::writeData(int reg, uchar data)
{
    ret = wiringPiI2CWriteReg8(_fd, reg, data);
}
uchar I2c::readData(int reg)
{
    data = wiringPiI2CReadReg8(_fd, reg);
}

运行效果

办公室正常效果(笔者在十多层,差不多吧95m左右的水平高度)

10s的气(主要是th)

放到特定环境挤压空气一下(主要是p)

 

上一篇:《树莓派开发笔记(七):GPIO口的SPI使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度)

下一篇:《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)

 

原博主博客地址:https://blog.csdn.net/qq21497936

原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062

本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79775665


相关文章
|
安全 Linux 数据中心
CentOS Stream的阿里云镜像站下载地址
CentOS Stream的阿里云镜像站下载地址
3178 0
|
3月前
|
数据采集 人工智能 机器人
2026年 智能体来了!什么是 AI 智能体工程化?为什么金加德强调 Workflow + Code 才能真正落地?
AI智能体工程化是将AI从聊天工具升级为“数字员工”,通过流程编排(Workflow)、代码逻辑(Code)与知识增强(RAG),让其稳定执行重复性业务流程,实现可复用、可落地的自动化生产。
509 7
|
机器学习/深度学习 人工智能 自然语言处理
用ChatGPT生成Excel公式,太方便了
用ChatGPT生成Excel公式,太方便了
319 1
|
Web App开发 存储 文字识别
云笔记横向评测:印象笔记、有道云笔记、为知笔记、OneNote、Notion、FlowUs、Wolai、飞书、语雀
某款软件是否好用,既需要根据其功能特性评估其优点和缺点,也需要分析用户的基本需求。以下是常见云笔记的深度评测。 云笔记评测标准:分析每款笔记软件的核心特色、优点、缺点及使用场景。 具体包括:印象笔记、有道云笔记、为知笔记、OneNote、Notion、FlowUs、Wolai、飞书、语雀
4986 0
云笔记横向评测:印象笔记、有道云笔记、为知笔记、OneNote、Notion、FlowUs、Wolai、飞书、语雀
|
网络协议 Linux
如何在 Linux 中禁用 IPv6?
【5月更文挑战第2天】
3400 8
如何在 Linux 中禁用 IPv6?
|
编解码 人工智能 Linux
SD中的VAE,你不能不懂
要想生成一幅美丽的图片,没有VAE可不行
SD中的VAE,你不能不懂
|
SQL 关系型数据库 数据库
DB2数据库优化器介绍
背景因为曾经从事DB2内核开发工作,所以一直想写一篇关于DB2优化器相关的文章。DB2和Oracle数据库一样,作为老的企业级数据库的代表,从诞生到现在已经多年了。1973年,IBM研究中心启动System R项目,为DB2的诞生打下良好基础。System R 是 IBM 研究部门开发的一种产品,这种原型语言促进了技术的发展并最终在1983年将 DB2 带到了商业市场。在这期间,IBM发表了很多数
797 1
DB2数据库优化器介绍
|
编解码 网络协议 网络性能优化
RTP/RTCP 协议讲解
RTP/RTCP 协议讲解
4423 0
|
缓存 算法 开发者
【Conan 入门教程 】了解 Conan2.1 中内置部署策略
【Conan 入门教程 】了解 Conan2.1 中内置部署策略
465 1
|
算法
版本号大小比较算法
版本号之间比较大小,本质上是比较字符串之间的关系。这里给定两个版本号,你一定能迅速地区分出大小: 0.0.2 0.0.3 想要让计算机程序分辨她们的关系,可以直接使用strcmp()函数获取返回值,如果你在 iOS 系统下编程,也可以使用 NSString 类提供的- (NSComparisonResult)compare:(NSNumber *)decimalNumber方法。
1914 0

热门文章

最新文章

下一篇
开通oss服务