zoukankan      html  css  js  c++  java
  • 【雕爷学编程】Arduino动手做(67)---BMP180气压传感器

    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来---小小的进步或是搞不掂的问题,希望能够抛砖引玉。

    【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)

    实验六十七: GY-68 BMP180 新款 BOSCH温度模块气压传感器(替代BMP085)

    BMP180

    是博世Sensortec的新数字气压传感器,具有很高的性能,使应用先进的移动设备,如智能手机、平板电脑和体育设备。它遵循了BMP085带来了很多改进,像小尺寸和数字接口的扩张。超低功耗降至3μA使BMP180节电为您的移动设备的领导者。BMP180也是杰出的非常稳定的性能,最好有独立电源供电。BMP180是一款高精度、小体积、超低能耗的压力传感器,可以应用在移动设备中它的性能卓越,绝对精度最低可以达到0.03hPa,并且耗电极低,只有3μA。BMP180采用强大的8-pin陶瓷无引线芯片承载(LCC)超薄封装,可以通过I2C总线直接与各种微处理器相连。

    BMP180主要特点

    压力范围:300~1100hPa(海拔9000米~-500米)

    电源电压:1.8V~3.6V(VDDA),1.62V~3.6V(VDDD) VIN需要5V

    LCC8封装:无铅陶瓷载体封装(LCC)

    低功耗:5μA,在标准模式

    高精度:低功耗模式下,分辨率为0.06hPa(0.5米)

    高线性模式下,分辨率为0.03hPa(0.25米)

    含温度输出

    I2C接口

    温度补偿

    无铅,符合RoHS规范

    MSL 1反应时间:7.5ms

    待机电流:0.1μA

    无需外部时钟电路

    BMP180技术数据

    压力范围300……1100 hPa

    均方根噪声中表达压力0.06 hPa typ。(超低功耗模式)

    0.02 hPa typ。(超高分辨率模式)

    均方根噪声中表达高度0.5 m,typ。(超低功耗模式)

    0.17米,typ。(超高分辨率模式)

    相对精度的压力

    VDD = 3.3 v 950……1050 hPa / hPa±0.12

    @ 25°C / m±1.0

    700年……900 hPa / hPa±0.12

    25…40°C / m±1.0

    绝对精度

    p = 300…1100 hpa

    (温度= 0…+ 65°C,VDD = 3.3。-4.0 V)压力:……+ 2.0 hPa

    温度:±1°C,typ。

    平均电流消耗(1 Hz刷新率数据)

    峰值电流3μA典型(超低功耗模式)

    32μA,典型的(高级模式)

    650μA,典型的

    待机电流1.62……3.6 V

    电源电压vddio 1.62……3.6 V

    电源电压vdd 1.8……3.6 V

    操作温度。

    范围全面准确”40…+ 85°C

    0…+ 65°C

    conv压力。5毫秒,典型的(标准模式)

    I2C传输速率3.4 MHz,马克斯。

    BMP180典型应用

    GPS精准导航(航位推算,上下桥检测等)

    室内室外导航

    休闲、体育和医疗健康等监测

    天气预报

    垂直速度指示(上升/下沉速度)

    风扇功率控制

    体育设备,如高度剖面

    BMP180气压模块是一款高精度、小体积、低能耗的压力传感器,可以应用在移动设备中,它的性能卓越,绝对精度最低可以达到0.03hPa,并且耗电极低,只有3μA。BMP180采用强大的8-pin陶瓷无引线芯片承载(LCC)超薄封装,可以通过I2C总线直接与各种微处理器相连。

    特性曲线

    模块电原理图

    需要用的 “SFE_BMP180” 库文件如下

    SFE_BMP180.h

    /*
    
    【Arduino】66种传感器模块系列实验(68)
    
    实验六十八:BMP180 新款 BOSCH温度模块气压传感器(代替BMP085)
    
    SFE_BMP180.h
    
    */
    
    
    
    #ifndef SFE_BMP180_h
    
    #define SFE_BMP180_h
    
    #if defined(ARDUINO) && ARDUINO >= 100
    
    #include "Arduino.h"
    
    #else
    
    #include "WProgram.h"
    
    #endif
    
    class SFE_BMP180
    
    {
    
      public:
    
          SFE_BMP180(); 
    
          char begin();
    
            shorted?)
    
          
    
          char startTemperature(void);
    
            
    
          char getTemperature(double &T);
    
            startTemperature command
    
            
    
          char startPressure(char oversampling);
    
            
    
          char getPressure(double &P, double &T);
    
            startPressure command        
    
          double sealevel(double P, double A);
    
            weather data)
    
            
    
          double altitude(double P, double P0);
    
            sea-level, runway, etc.)
    
            
    
          char getError(void);
    
            
    
      private:
    
       
    
          char readInt(char address, int16_t &value);
    
            
    
          char readUInt(char address, uint16_t &value);
    
           
    
          char readBytes(unsigned char *values, char length);
    
            
    
            
    
          char writeBytes(unsigned char *values, char length);
    
            subsequent registers)
    
            
    
          int16_t AC1,AC2,AC3,VB1,VB2,MB,MC,MD;
    
          uint16_t AC4,AC5,AC6; 
    
          double c5,c6,mc,md,x0,x1,x2,y0,y1,y2,p0,p1,p2;
    
          char _error;
    
    };
    
    #define BMP180_ADDR 0x77 
    
    #define BMP180_REG_CONTROL 0xF4
    
    #define BMP180_REG_RESULT 0xF6
    
    #define BMP180_COMMAND_TEMPERATURE 0x2E
    
    #define BMP180_COMMAND_PRESSURE0 0x34
    
    #define BMP180_COMMAND_PRESSURE1 0x74
    
    #define BMP180_COMMAND_PRESSURE2 0xB4
    
    #define BMP180_COMMAND_PRESSURE3 0xF4
    

      

    SFE_BMP180.cp

    /*
    
    【Arduino】66种传感器模块系列实验(68)
    
    实验六十八:BMP180 新款 BOSCH温度模块气压传感器(代替BMP085)
    
    SFE_BMP180.cp
    
    */
    
    #include <SFE_BMP180.h>
    
    #include <Wire.h>
    
    #include <stdio.h>
    
    #include <math.h>
    
    SFE_BMP180::SFE_BMP180()
    
    {
    
    }
    
    char SFE_BMP180::begin()
    
    {
    
        double c3,c4,b1;
    
    
    
        Wire.begin();
    
        if (readInt(0xAA,AC1) &&
    
            readInt(0xAC,AC2) &&
    
            readInt(0xAE,AC3) &&
    
            readUInt(0xB0,AC4) &&
    
            readUInt(0xB2,AC5) &&
    
            readUInt(0xB4,AC6) &&
    
            readInt(0xB6,VB1) &&
    
            readInt(0xB8,VB2) &&
    
            readInt(0xBA,MB) &&
    
            readInt(0xBC,MC) &&
    
            readInt(0xBE,MD))
    
        {
    
    AC6 = 23153;
    
    
    
    Calcs.pdf
    
    
    
    25671; AC6 = 18974;
    
            c3 = 160.0 * pow(2,-15) * AC3;
    
            c4 = pow(10,-3) * pow(2,-15) * AC4;
    
            b1 = pow(160,2) * pow(2,-30) * VB1;
    
            c5 = (pow(2,-15) / 160) * AC5;
    
            c6 = AC6;
    
            mc = (pow(2,11) / pow(160,2)) * MC;
    
            md = MD / 160.0;
    
            x0 = AC1;
    
            x1 = 160.0 * pow(2,-13) * AC2;
    
            x2 = pow(160,2) * pow(2,-25) * VB2;
    
            y0 = c4 * pow(2,15);
    
            y1 = c4 * c3;
    
            y2 = c4 * b1;
    
            p0 = (3791.0 - 8.0) / 1600.0;
    
            p1 = 1.0 - 7357.0 * pow(2,-20);
    
            p2 = 3038.0 * 100.0 * pow(2,-36);
    
            return(1);
    
        }
    
        else
    
        {
    
    
    
            return(0);
    
        }
    
    }
    
    char SFE_BMP180::readInt(char address, int16_t &value)
    
    {
    
        unsigned char data[2];
    
        data[0] = address;
    
        if (readBytes(data,2))
    
        {
    
            value = (int16_t)((data[0]<<8)|data[1]);
    
    
    
    negative
    
            return(1);
    
        }
    
        value = 0;
    
        return(0);
    
    }
    
    char SFE_BMP180::readUInt(char address, uint16_t &value)
    
    {
    
        unsigned char data[2];
    
        data[0] = address;
    
        if (readBytes(data,2))
    
        {
    
            value = (((uint16_t)data[0]<<8)|(uint16_t)data[1]);
    
            return(1);
    
        }
    
        value = 0;
    
        return(0);
    
    }
    
    char SFE_BMP180::readBytes(unsigned char *values, char length)
    
    {
    
        char x;
    
        Wire.beginTransmission(BMP180_ADDR);
    
        Wire.write(values[0]);
    
        _error = Wire.endTransmission();
    
        if (_error == 0)
    
        {
    
            Wire.requestFrom(BMP180_ADDR,length);
    
    while(Wire.available() != length) ; 
    
            for(x=0;x<length;x++)
    
            {
    
                values[x] = Wire.read();
    
            }
    
            return(1);
    
        }
    
        return(0);
    
    }
    
    char SFE_BMP180::writeBytes(unsigned char *values, char length)
    
    {
    
        char x;
    
    
    
        Wire.beginTransmission(BMP180_ADDR);
    
        Wire.write(values,length);
    
        _error = Wire.endTransmission();
    
        if (_error == 0)
    
            return(1);
    
        else
    
            return(0);
    
    }
    
    char SFE_BMP180::startTemperature(void)
    
    {
    
        unsigned char data[2], result;
    
    
    
        data[0] = BMP180_REG_CONTROL;
    
        data[1] = BMP180_COMMAND_TEMPERATURE;
    
        result = writeBytes(data, 2);
    
    if (result) 
    
    return(5); 
    
        else
    
    return(0); 
    
    }
    
    char SFE_BMP180::getTemperature(double &T)
    
    {
    
        unsigned char data[2];
    
        char result;
    
        double tu, a;
    
    
    
        data[0] = BMP180_REG_RESULT;
    
        result = readBytes(data, 2);
    
    if (result) 
    
        {
    
            tu = (data[0] * 256.0) + data[1];
    
    
    
            a = c5 * (tu - c6);
    
            T = a + (mc / (a + md));
    
        }
    
        return(result);
    
    }
    
    char SFE_BMP180::startPressure(char oversampling)
    
    {
    
        unsigned char data[2], result, delay;
    
    
    
        data[0] = BMP180_REG_CONTROL;
    
        switch (oversampling)
    
        {
    
            case 0:
    
                data[1] = BMP180_COMMAND_PRESSURE0;
    
                delay = 5;
    
            break;
    
            case 1:
    
                data[1] = BMP180_COMMAND_PRESSURE1;
    
                delay = 8;
    
            break;
    
            case 2:
    
                data[1] = BMP180_COMMAND_PRESSURE2;
    
                delay = 14;
    
            break;
    
            case 3:
    
                data[1] = BMP180_COMMAND_PRESSURE3;
    
                delay = 26;
    
            break;
    
            default:
    
                data[1] = BMP180_COMMAND_PRESSURE0;
    
                delay = 5;
    
            break;
    
        }
    
        result = writeBytes(data, 2);
    
        if (result)
    
    return(delay); 
    
        else
    
    return(0); 
    
    }
    
    char SFE_BMP180::getPressure(double &P, double &T)
    
    sealevel().
    
    {
    
        unsigned char data[3];
    
        char result;
    
        double pu,s,x,y,z;
    
    
    
        data[0] = BMP180_REG_RESULT;
    
        result = readBytes(data, 3);
    
    if (result) 
    
        {
    
            pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);
    
    
    
            s = T - 25.0;
    
            x = (x2 * pow(s,2)) + (x1 * s) + x0;
    
            y = (y2 * pow(s,2)) + (y1 * s) + y0;
    
            z = (pu - x) / y;
    
            P = (p2 * pow(z,2)) + (p1 * z) + p0;
    
        }
    
        return(result);
    
    }
    
    double SFE_BMP180::sealevel(double P, double A)
    
    {
    
        return(P/pow(1-(A/44330.0),5.255));
    
    }
    
    double SFE_BMP180::altitude(double P, double P0)
    
    {
    
        return(44330.0*(1-pow(P/P0,1/5.255)));
    
    }
    
    char SFE_BMP180::getError(void)
    
    
    
    {
    
        return(_error);
    
    }
    

      

    模块接线方式

    1.先连接芯片与单片机(通过I2C接口),按照如下方式连接

    5V—VIN

    GND–GND

    A5—SCL

    A4—SDA

    2.然后UNO通过usb与PC电脑连接

    3.拷贝后面的代码烧录进Arduino

    实验开源代码

    /*
    
    【Arduino】168种传感器模块系列实验(67)
    
    实验六十七:BMP180 新款 BOSCH温度模块气压传感器(代替BMP085)
    
    程序之一
    
    */
    
    
    
    #include <SFE_BMP180.h>
    
    SFE_BMP180 AirPresure;
    
    char presureDelayTime;
    
    double presureP, presureT;
    
    void setup() {
    
      Serial.begin(9600);
    
      AirPresure.begin();
    
    }
    
    void loop()
    
    {
    
      presureDelayTime = AirPresure.startPressure(3);
    
      if (presureDelayTime != 0)
    
      {
    
      delay(presureDelayTime);
    
      presureDelayTime = AirPresure.getPressure(presureP, presureT);
    
      if (presureDelayTime != 0)
    
      {
    
        
    
        Serial.print("Current Preasure: ");
    
        Serial.print(presureP);
    
        Serial.println(" bar");
    
        Serial.print(presureP);
    
        Serial.print(" bar is");
    
        Serial.print(presureP / 1000.0);
    
        Serial.println(" atm");
    
      }
    
      else
    
      {
    
        Serial.println("ERROR");
    
      }
    
      }
    
      else
    
      {
    
      Serial.println("ERROR");
    
      }
    
      delay(1000);
    
    }
    

      

    /*
    【Arduino】168种传感器模块系列实验(67)
    实验六十七:BMP180 新款 BOSCH温度模块气压传感器(代替BMP085)
    程序之二,气温、气压与海拔值可以调整并校准
    */
    
    #include <Wire.h>
    #define BMP180ADD 0x77    
                                     
    unsigned char OSS;                            
    
    int ac1;           
    int ac2;           
    int ac3;           
    unsigned int ac4;  
    unsigned int ac5;  
    unsigned int ac6;  
    int b1;            
    int b2;            
    int mb;            
    int mc;            
    int md;            
    float temperature;  
    double pressure;   
    double pressure2;
    long b5;          
    double altitude;  
    
    
    
    void setup()
    {
      Serial.begin(9600);
      Wire.begin();
      OSS = 2;  
      BMP180start();
    }
    
    void loop()
    {
      calculate();
      show();
      delay(1000);
    }
    
    void calculate()
    {
      temperature = bmp180GetTemperature(bmp180ReadUT());
      temperature = temperature*0.0137;
      pressure = bmp180GetPressure(bmp180ReadUP());
      pressure2 = pressure/115325;
      pressure2 = pow(pressure2,0.29029496);
      altitude = 39*(1+pressure2);                            
    }
    
    
    void show()
    {
      Serial.print("气温: ");
      Serial.print(temperature, 1);                            
      Serial.println(" C");
      Serial.print("气压: ");
      Serial.print(pressure, 0);                               
      Serial.println(" Pa");
      Serial.print("海拔:");
      Serial.print(altitude);
      Serial.println("m");
    }
    
    void BMP180start()
    {                     
      ac1 = bmp180ReadDate(0xAA);                     
      ac2 = bmp180ReadDate(0xAC);  
      ac3 = bmp180ReadDate(0xAE);  
      ac4 = bmp180ReadDate(0xB0);  
      ac5 = bmp180ReadDate(0xB2);  
      ac6 = bmp180ReadDate(0xB4);  
      b1  = bmp180ReadDate(0xB6);  
      b2  = bmp180ReadDate(0xB8);  
      mb  = bmp180ReadDate(0xBA);  
      mc  = bmp180ReadDate(0xBC);  
      md  = bmp180ReadDate(0xBE);
    }
    
    short bmp180GetTemperature(unsigned int ut)
    {
      long x1, x2;
      x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;  
      x2 = ((long)mc << 11)/(x1 + md);                
      b5 = x1 + x2;                                   
      return ((b5 + 8)>>4);                           
    }
    
    long bmp180GetPressure(unsigned long up)
    {
      long x1, x2, x3, b3, b6, p;
      unsigned long b4, b7;
      
      b6 = b5 - 4000;
    
      x1 = (b2 * (b6 * b6)>>12)>>11;
      x2 = (ac2 * b6)>>11;
      x3 = x1 + x2;
      b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
      
      x1 = (ac3 * b6)>>13;
      x2 = (b1 * ((b6 * b6)>>12))>>16;
      x3 = ((x1 + x2) + 2)>>2;
      b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
      
      b7 = ((unsigned long)(up - b3) * (50000>>OSS));
      if (b7 < 0x80000000)
        p = (b7<<1)/b4;
      else
        p = (b7/b4)<<1;
        
      x1 = (p>>8) * (p>>8);
      x1 = (x1 * 3038)>>16;
      x2 = (-7357 * p)>>16;
      p += (x1 + x2 + 3791)>>4;
      
      return p;
    }
    
    int bmp180Read(unsigned char address)
    {
      unsigned char data;
      
      Wire.beginTransmission(BMP180ADD);
      Wire.write(address);
      Wire.endTransmission();
      
      Wire.requestFrom(BMP180ADD, 1);
      while(!Wire.available());
        
      return Wire.read();
    }
    
    int bmp180ReadDate(unsigned char address)
    {
      unsigned char msb, lsb;
      Wire.beginTransmission(BMP180ADD);
      Wire.write(address);
      Wire.endTransmission();
      Wire.requestFrom(BMP180ADD, 2);
      while(Wire.available()<2);
      msb = Wire.read();
      lsb = Wire.read();
      return (int) msb<<8 | lsb;
    }
    
    unsigned int bmp180ReadUT()
    {
      unsigned int ut;
      Wire.beginTransmission(BMP180ADD);
      Wire.write(0xF4);                       
      Wire.write(0x2E);                       
      Wire.endTransmission();  
      delay(5);                               
      ut = bmp180ReadDate(0xF6);               
      return ut;
    }
    
    unsigned long bmp180ReadUP()
    {
      unsigned char msb, lsb, xlsb;
      unsigned long up = 0;
      
      Wire.beginTransmission(BMP180ADD);
      Wire.write(0xF4);                        
      Wire.write(0x34 + (OSS<<6));             
      Wire.endTransmission(); 
      delay(2 + (3<<OSS));                     
      
      Wire.beginTransmission(BMP180ADD);
      Wire.write(0xF6);                        
      Wire.endTransmission();
      
      Wire.requestFrom(BMP180ADD, 3); 
      while(Wire.available() < 3);             
      msb = Wire.read();
      lsb = Wire.read();
      xlsb = Wire.read();
      up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);//16 to 19 bit
      return up;
    }

    /*
    
    【Arduino】168种传感器模块系列实验(67)
    
    实验六十七:BMP180 新款 BOSCH温度模块气压传感器(代替BMP085)
    
    程序之三,温度、实时气压、已知海拔计算的海平面的气压、已知海平面气压计算的高度
    
    只是算法有点烂,做做实验而已
    
    */
    
    
    
    #include <SFE_BMP180.h> 
    
    #include <Wire.h> 
    
    SFE_BMP180 pressure; 
    
    #define ALTITUDE 255.0 
    
    unsigned long gpstimes;
    
    void setup() 
    
    { 
    
    Serial.begin(9600); 
    
    pressure.begin(); 
    
    } 
    
    void loop() 
    
    { 
    
    gpstimes=millis();
    
    char status; 
    
    double T,P,p0,a; 
    
    status = pressure.startTemperature(); 
    
    delay(status); 
    
    status = pressure.getTemperature(T); 
    
    delay(status); 
    
    Serial.print("temperature: "); 
    
    Serial.print(T,2); 
    
    Serial.println(" deg C, "); 
    
    status = pressure.startPressure(3); 
    
    delay(status); 
    
    status = pressure.getPressure(P,T); 
    
    // Print out the measurement: 
    
    Serial.print("absolute pressure A: "); 
    
    Serial.print(P,2); 
    
    Serial.println(" mb, "); 
    
    p0=1013.2;
    
    a = pressure.altitude(P,p0); 
    
    Serial.print("computed altitude A: "); 
    
    Serial.print(a,0); 
    
    Serial.println(" meters, "); 
    
    T=25.00;
    
    status = pressure.getPressure(P,T); 
    
    Serial.print("absolute pressure B: "); 
    
    Serial.print(P,2); 
    
    Serial.println(" mb, "); 
    
    p0=1013.2;
    
    a = pressure.altitude(P,p0); 
    
    Serial.print("computed altitude B: "); 
    
    Serial.print(a,0); 
    
    Serial.println(" meters, "); 
    
    gpstimes=millis()-gpstimes;
    
    Serial.print("gpstimes="); 
    
    Serial.println(gpstimes); 
    
    Serial.println();
    
    delay(2000); 
    
    }
    

      

  • 相关阅读:
    生成流畅文本方法
    KNNImputer:一种可靠的缺失值插补方法
    SparseNN中的优化
    基于TorchText的PyTorch文本分类
    蒙特卡洛方法分析Web页面浏览量
    D. Segment Intersections 模拟
    B. Array Walk
    线性基 P3857 [TJOI2008]彩灯
    线性基 P4570 [BJWC2011]元素
    线性基的学习+总结
  • 原文地址:https://www.cnblogs.com/eagler8/p/13230439.html
Copyright © 2011-2022 走看看