极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12319|回复: 8

菜鸟看 BMP180

[复制链接]
发表于 2014-9-24 21:35:09 | 显示全部楼层 |阅读模式
本帖最后由 hi55234 于 2014-9-24 21:55 编辑

库文件
https://github.com/sparkfun/BMP1 ... ibraries/SFE_BMP180

  1. #include <SFE_BMP180.h>
  2. #include <Wire.h>

  3. SFE_BMP180 pressure; //引用库?定义库?

  4. //本地海拔,很无聊的东西,除非你要通过本地气压计算海平面的气压
  5. #define ALTITUDE 255.0

  6. unsigned long gpstimes;

  7. void setup()
  8. {
  9. Serial.begin(9600);

  10. pressure.begin(); //初始化BMP180?

  11. }

  12. void loop()
  13. {
  14. gpstimes=millis();

  15. char status; //纯延时用的,因为如果不延迟,则读数不正确
  16. double T,P,p0,a; //温度、实时气压、已知海拔计算的海平面的气压、已知海平面气压计算的高度

  17. //目测实在看不惯status,则可以去掉,指定延时时间
  18. //可以计算温度,不过对比酒精温度计有2度的误差,感觉比较废
  19. //但是,若海平面取1013.2,以此偏差温度所计算的海拔(气压)倒是比较正确的
  20. //相反实际温度计算的海拔误差反而较大
  21. //坑爹啊

  22. status = pressure.startTemperature();
  23. delay(status);
  24. status = pressure.getTemperature(T);
  25. delay(status);

  26. Serial.print("temperature: ");
  27. Serial.print(T,2);
  28. Serial.println(" deg C, ");



  29. status = pressure.startPressure(3);
  30. delay(status);

  31. status = pressure.getPressure(P,T);

  32. // Print out the measurement:
  33. Serial.print("absolute pressure A: ");
  34. Serial.print(P,2);
  35. Serial.println(" mb, ");


  36. //百度百科
  37. //海平面气压(sea level pressure) 温度15摄氏度(59华氏度)条件下,29.92”英寸汞柱(1013.2hPa)
  38. p0=1013.2;
  39.                   
  40.                                     
  41. a = pressure.altitude(P,p0);
  42. Serial.print("computed altitude A: ");
  43. Serial.print(a,0);
  44. Serial.println(" meters, ");


  45. ////////////////////////////////////////////
  46. T=25.00;
  47. status = pressure.getPressure(P,T);

  48. // Print out the measurement:
  49. Serial.print("absolute pressure B: ");
  50. Serial.print(P,2);
  51. Serial.println(" mb, ");


  52. //百度百科
  53. //海平面气压(sea level pressure) 温度15摄氏度(59华氏度)条件下,29.92”英寸汞柱(1013.2hPa)
  54. p0=1013.2;
  55.                   
  56.                                     
  57. a = pressure.altitude(P,p0);
  58. Serial.print("computed altitude B: ");
  59. Serial.print(a,0);
  60. Serial.println(" meters, ");

  61. gpstimes=millis()-gpstimes;
  62. Serial.print("gpstimes=");
  63. Serial.println(gpstimes);
  64. Serial.println();

  65. }
复制代码
回复

使用道具 举报

 楼主| 发表于 2014-9-24 21:51:41 | 显示全部楼层
本帖最后由 hi55234 于 2014-9-24 21:53 编辑

就应用来说:
pressure.getPressure(P,T);
pressure.altitude(P,p0);

用得最多,前者是绝对压力,后者专门计算四轴啥的相对垂直位移

  1. #include <SFE_BMP180.h>
  2. #include <Wire.h>

  3. SFE_BMP180 pressure; //引用库?定义库?

  4. //本地海拔,很无聊的东西,除非你要通过本地气压计算海平面的气压
  5. #define ALTITUDE 255.0

  6. char status; //纯延时用的,因为如果不延迟,则读数不正确
  7. double T,P,p0,a; //温度、实时气压、已知海拔计算的海平面的气压、已知海平面气压计算的高度

  8. unsigned long gpstimes;

  9. void setup()
  10. {
  11. Serial.begin(9600);

  12. pressure.begin(); //初始化BMP180?

  13. }

  14. void loop()
  15. {
  16. gpstimes=millis();




  17. //计算P

  18. status = pressure.startTemperature();
  19. delay(status);
  20. status = pressure.getTemperature(T);
  21. delay(status);

  22. status = pressure.startPressure(3);
  23. delay(status);

  24. status = pressure.getPressure(P,T);

  25. //计算垂直位置的移动数
  26. a = pressure.altitude(P,p0);
  27. Serial.print("computed altitude A: ");
  28. Serial.print(a,3);
  29. Serial.println(" meters, ");

  30. p0=P;//给p0赋值




  31.                                     

  32. gpstimes=millis()-gpstimes;
  33. Serial.print("gpstimes=");
  34. Serial.println(gpstimes);
  35. Serial.println();
  36. delay(2000);

  37. }
复制代码



以此程序就能知道,其极限分辨率,以及需要滤波的部分··········
分辨率为0.06hPa(0.5米)
回复 支持 反对

使用道具 举报

发表于 2014-9-24 23:41:15 | 显示全部楼层
本帖最后由 topdog 于 2014-9-24 23:44 编辑

SFE_BMP180.cpp

#include <SFE_BMP180.h>
#include <Wire.h>
#include <stdio.h>
#include <math.h>


SFE_BMP180::SFE_BMP180()
// Base library type
{
}


char SFE_BMP180::begin()
// Initialize library for subsequent pressure measurements
{
        double c3,c4,b1;
       
        // Start up the Arduino's "wire" (I2C) library:
       
        Wire.begin();

        // The BMP180 includes factory calibration data stored on the device.
        // Each device has different numbers, these must be retrieved and
        // used in the calculations when taking pressure measurements.

        // Retrieve calibration data from device:
       
        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))
        {

                // All reads completed successfully!

                // If you need to check your math using known numbers,
                // you can uncomment one of these examples.
                // (The correct results are commented in the below functions.)

                // Example from Bosch datasheet
                // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
                // B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;

                // Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
                // AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
                // VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;

                /*
                Serial.print("AC1: "); Serial.println(AC1);
                Serial.print("AC2: "); Serial.println(AC2);
                Serial.print("AC3: "); Serial.println(AC3);
                Serial.print("AC4: "); Serial.println(AC4);
                Serial.print("AC5: "); Serial.println(AC5);
                Serial.print("AC6: "); Serial.println(AC6);
                Serial.print("VB1: "); Serial.println(VB1);
                Serial.print("VB2: "); Serial.println(VB2);
                Serial.print("MB: "); Serial.println(MB);
                Serial.print("MC: "); Serial.println(MC);
                Serial.print("MD: "); Serial.println(MD);
                */
               
                // Compute floating-point polynominals:

                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);

                /*
                Serial.println();
                Serial.print("c3: "); Serial.println(c3);
                Serial.print("c4: "); Serial.println(c4);
                Serial.print("c5: "); Serial.println(c5);
                Serial.print("c6: "); Serial.println(c6);
                Serial.print("b1: "); Serial.println(b1);
                Serial.print("mc: "); Serial.println(mc);
                Serial.print("md: "); Serial.println(md);
                Serial.print("x0: "); Serial.println(x0);
                Serial.print("x1: "); Serial.println(x1);
                Serial.print("x2: "); Serial.println(x2);
                Serial.print("y0: "); Serial.println(y0);
                Serial.print("y1: "); Serial.println(y1);
                Serial.print("y2: "); Serial.println(y2);
                Serial.print("p0: "); Serial.println(p0);
                Serial.print("p1: "); Serial.println(p1);
                Serial.print("p2: "); Serial.println(p2);
                */
               
                // Success!
                return(1);
        }
        else
        {
                // Error reading calibration data; bad component or connection?
                return(0);
        }
}


char SFE_BMP180::readInt(char address, int &value)
// Read a signed integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
        unsigned char data[2];

        data[0] = address;
        if (readBytes(data,2))
        {
                value = (((int)data[0]<<8)|(int)data[1]);
                //if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
                return(1);
        }
        value = 0;
        return(0);
}


char SFE_BMP180::readUInt(char address, unsigned int &value)
// Read an unsigned integer (two bytes) from device
// address: register to start reading (plus subsequent register)
// value: external variable to store data (function modifies value)
{
        unsigned char data[2];

        data[0] = address;
        if (readBytes(data,2))
        {
                value = (((unsigned int)data[0]<<8)|(unsigned int)data[1]);
                return(1);
        }
        value = 0;
        return(0);
}


char SFE_BMP180::readBytes(unsigned char *values, char length)
// Read an array of bytes from device
// values: external array to hold data. Put starting register in values[0].
// length: number of bytes to read
{
        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) ; // wait until bytes are ready
                for(x=0;x<length;x++)
                {
                        values[x] = Wire.read();
                }
                return(1);
        }
        return(0);
}


char SFE_BMP180::writeBytes(unsigned char *values, char length)
// Write an array of bytes to device
// values: external array of data to write. Put starting register in values[0].
// length: number of bytes to write
{
        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)
// Begin a temperature reading.
// Will return delay in ms to wait, or 0 if I2C error
{
        unsigned char data[2], result;
       
        data[0] = BMP180_REG_CONTROL;
        data[1] = BMP180_COMMAND_TEMPERATURE;
        result = writeBytes(data, 2);
        if (result) // good write?
                return(5); // return the delay in ms (rounded up) to wait before retrieving data
        else
                return(0); // or return 0 if there was a problem communicating with the BMP
}


char SFE_BMP180::getTemperature(double &T)
// Retrieve a previously-started temperature reading.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startTemperature() to have been called prior and sufficient time elapsed.
// T: external variable to hold result.
// Returns 1 if successful, 0 if I2C error.
{
        unsigned char data[2];
        char result;
        double tu, a;
       
        data[0] = BMP180_REG_RESULT;

        result = readBytes(data, 2);
        if (result) // good read, calculate temperature
        {
                tu = (data[0] * 256.0) + data[1];

                //example from Bosch datasheet
                //tu = 27898;

                //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
                //tu = 0x69EC;
               
                a = c5 * (tu - c6);
                T = a + (mc / (a + md));

                /*               
                Serial.println();
                Serial.print("tu: "); Serial.println(tu);
                Serial.print("a: "); Serial.println(a);
                Serial.print("T: "); Serial.println(*T);
                */
        }
        return(result);
}


char SFE_BMP180::startPressure(char oversampling)
// Begin a pressure reading.
// Oversampling: 0 to 3, higher numbers are slower, higher-res outputs.
// Will return delay in ms to wait, or 0 if I2C error.
{
        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) // good write?
                return(delay); // return the delay in ms (rounded up) to wait before retrieving data
        else
                return(0); // or return 0 if there was a problem communicating with the BMP
}


char SFE_BMP180::getPressure(double &P, double &T)
// Retrieve a previously started pressure reading, calculate abolute pressure in mbars.
// Requires begin() to be called once prior to retrieve calibration parameters.
// Requires startPressure() to have been called prior and sufficient time elapsed.
// Requires recent temperature reading to accurately calculate pressure.

// P: external variable to hold pressure.
// T: previously-calculated temperature.
// Returns 1 for success, 0 for I2C error.

// Note that calculated pressure value is absolute mbars, to compensate for altitude call sealevel().
{
        unsigned char data[3];
        char result;
        double pu,s,x,y,z;
       
        data[0] = BMP180_REG_RESULT;

        result = readBytes(data, 3);
        if (result) // good read, calculate pressure
        {
                pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);

                //example from Bosch datasheet
                //pu = 23843;

                //example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;       
                //pu = (0x98 * 256.0) + 0x2F + (0xC0/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;

                /*
                Serial.println();
                Serial.print("pu: "); Serial.println(pu);
                Serial.print("T: "); Serial.println(*T);
                Serial.print("s: "); Serial.println(s);
                Serial.print("x: "); Serial.println(x);
                Serial.print("y: "); Serial.println(y);
                Serial.print("z: "); Serial.println(z);
                Serial.print("P: "); Serial.println(*P);
                */
        }
        return(result);
}


double SFE_BMP180::sealevel(double P, double A)
// Given a pressure P (mb) taken at a specific altitude (meters),
// return the equivalent pressure (mb) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
        return(P/pow(1-(A/44330.0),5.255));
}


double SFE_BMP180::altitude(double P, double P0)
// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
// return altitude (meters) above baseline.
{
        return(44330.0*(1-pow(P/P0,1/5.255)));
}


char SFE_BMP180::getError(void)
        // If any library command fails, you can retrieve an extended
        // error code using this command. Errors are from the wire library:
        // 0 = Success
        // 1 = Data too long to fit in transmit buffer
        // 2 = Received NACK on transmit of address
        // 3 = Received NACK on transmit of data
        // 4 = Other error
{
        return(_error);
}


回复 支持 反对

使用道具 举报

发表于 2014-9-24 23:46:50 | 显示全部楼层
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(); // base type

                char begin();
                        // call pressure.begin() to initialize BMP180 before use
                        // returns 1 if success, 0 if failure (bad component or I2C bus shorted?)
               
                char startTemperature(void);
                        // command BMP180 to start a temperature measurement
                        // returns (number of ms to wait) for success, 0 for fail

                char getTemperature(double &T);
                        // return temperature measurement from previous startTemperature command
                        // places returned value in T variable (deg C)
                        // returns 1 for success, 0 for fail

                char startPressure(char oversampling);
                        // command BMP180 to start a pressure measurement
                        // oversampling: 0 - 3 for oversampling value
                        // returns (number of ms to wait) for success, 0 for fail

                char getPressure(double &P, double &T);
                        // return absolute pressure measurement from previous startPressure command
                        // note: requires previous temperature measurement in variable T
                        // places returned value in P variable (mbar)
                        // returns 1 for success, 0 for fail

                double sealevel(double P, double A);
                        // convert absolute pressure to sea-level pressure (as used in weather data)
                        // P: absolute pressure (mbar)
                        // A: current altitude (meters)
                        // returns sealevel pressure in mbar

                double altitude(double P, double P0);
                        // convert absolute pressure to altitude (given baseline pressure; sea-level, runway, etc.)
                        // P: absolute pressure (mbar)
                        // P0: fixed baseline pressure (mbar)
                        // returns signed altitude in meters

                char getError(void);
                        // If any library command fails, you can retrieve an extended
                        // error code using this command. Errors are from the wire library:
                        // 0 = Success
                        // 1 = Data too long to fit in transmit buffer
                        // 2 = Received NACK on transmit of address
                        // 3 = Received NACK on transmit of data
                        // 4 = Other error

        private:
       
                char readInt(char address, int &value);
                        // read an signed int (16 bits) from a BMP180 register
                        // address: BMP180 register address
                        // value: external signed int for returned value (16 bits)
                        // returns 1 for success, 0 for fail, with result in value

                char readUInt(char address, unsigned int &value);
                        // read an unsigned int (16 bits) from a BMP180 register
                        // address: BMP180 register address
                        // value: external unsigned int for returned value (16 bits)
                        // returns 1 for success, 0 for fail, with result in value

                char readBytes(unsigned char *values, char length);
                        // read a number of bytes from a BMP180 register
                        // values: array of char with register address in first location [0]
                        // length: number of bytes to read back
                        // returns 1 for success, 0 for fail, with read bytes in values[] array
                       
                char writeBytes(unsigned char *values, char length);
                        // write a number of bytes to a BMP180 register (and consecutive subsequent registers)
                        // values: array of char with register address in first location [0]
                        // length: number of bytes to write
                        // returns 1 for success, 0 for fail
                       
                int AC1,AC2,AC3,VB1,VB2,MB,MC,MD;
                unsigned int AC4,AC5,AC6;
                double c5,c6,mc,md,x0,x1,x2,y0,y1,y2,p0,p1,p2;
                char _error;
};

#define BMP180_ADDR 0x77 // 7-bit address

#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

#endif
回复 支持 反对

使用道具 举报

发表于 2014-9-25 22:51:50 | 显示全部楼层
#######################################
# Syntax Coloring Map for SFE_BMP180
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

SFE_BMP180        KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

begin        KEYWORD2
startTemperature        KEYWORD2
getTemperature        KEYWORD2
startPressure        KEYWORD2
getPressure        KEYWORD2
sealevel        KEYWORD2
altitude        KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################

BMP180_ADDR        LITERAL1
回复 支持 反对

使用道具 举报

发表于 2014-10-3 20:48:41 | 显示全部楼层
感谢大神,正需要这个
回复 支持 反对

使用道具 举报

发表于 2015-1-30 23:00:39 | 显示全部楼层
下载来的SFE_BMP180.h里面怎么都是html代码啊?
回复 支持 反对

使用道具 举报

发表于 2015-3-9 14:21:51 | 显示全部楼层
测试下来Latitude怎么一直都是负值呀?难道在海平面以下?不可能吧!
回复 支持 反对

使用道具 举报

发表于 2015-7-30 16:54:18 | 显示全部楼层
能不能改接线不用A4 A5 ?
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-17 20:58 , Processed in 0.076492 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表