Arduino

Arduino --- BMP180大气压强传感器的使用

2017-11-01  本文已影响81人  梦沧海

前言

大气压强传感器,故名思议,是一款检测气压的传感器,其使用代码如下:

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

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

SFE_BMP180.h

/*
    SFE_BMP180.h
    Bosch BMP180 pressure sensor library for the Arduino microcontroller
    Mike Grusin, SparkFun Electronics

    Uses floating-point equations from the Weather Station Data Logger project
    http://wmrx00.sourceforge.net/
    http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf

    Forked from BMP085 library by M.Grusin

    version 1.0 2013/09/20 initial version
    Verison 1.1.2 - Updated for Arduino 1.6.4 5/2015
    
    Our example code uses the "beerware" license. You can do anything
    you like with this code. No really, anything. If you find it useful,
    buy me a (root) beer someday.
*/

#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, int16_t &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, uint16_t &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
            
        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 // 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

SFE_BMP180.cp

/*
    SFE_BMP180.cpp
    Bosch BMP180 pressure sensor library for the Arduino microcontroller
    Mike Grusin, SparkFun Electronics

    Uses floating-point equations from the Weather Station Data Logger project
    http://wmrx00.sourceforge.net/
    http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf

    Forked from BMP085 library by M.Grusin

    version 1.0 2013/09/20 initial version
    Verison 1.1.2 - Updated for Arduino 1.6.4 5/2015

    Our example code uses the "beerware" license. You can do anything
    you like with this code. No really, anything. If you find it useful,
    buy me a (root) beer someday.
*/

#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, int16_t &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 = (int16_t)((data[0]<<8)|data[1]);
        //if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
        return(1);
    }
    value = 0;
    return(0);
}


char SFE_BMP180::readUInt(char address, uint16_t &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 = (((uint16_t)data[0]<<8)|(uint16_t)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);
}
上一篇下一篇

猜你喜欢

热点阅读