123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- /*
- BMP280.cpp
-
- Bosch BMP280 pressure sensor library for the Arduino microcontroller.
- This library uses I2C connection.
- Uses floating-point equations from BMP280 datasheet.
- modified by mhafuzul islam
- version 1.01 16/9/2014 initial version
-
- Our example code uses the "pizza-eating" license. You can do anything
- you like with this code. No really, anything. If you find it useful,
- buy me italian pizza someday.
- */
- #include "BMP280.h"
- #include <Wire.h>
- #include <stdio.h>
- #include <math.h>
- BMP280::BMP280()
- {
- //do nothing
- }
- /*
- * Initialize library and coefficient for measurements
- */
- char BMP280::begin(int sdaPin, int sclPin)
- {
- Wire.begin(sdaPin,sclPin);
- return (readCalibration());
- }
- char BMP280::begin()
- {
-
- // Start up the Arduino's "wire" (I2C) library:
- Wire.begin();
- return (readCalibration());
- }
- // The BMP280 includes factory calibration data stored on the device.
- // Each device has different numbers, these must be retrieved and
- // used in the calculations when taking measurements.
- // Retrieve calibration data from device:
- char BMP280::readCalibration() {
-
- if (
- readUInt(0x88, dig_T1) &&
- readInt(0x8A, dig_T2) &&
- readInt(0x8C, dig_T3) &&
- readUInt(0x8E, dig_P1) &&
- readInt(0x90, dig_P2) &&
- readInt(0x92, dig_P3) &&
- readInt(0x94, dig_P4) &&
- readInt(0x96, dig_P5) &&
- readInt(0x98, dig_P6) &&
- readInt(0x9A, dig_P7) &&
- readInt(0x9C, dig_P8) &&
- readInt(0x9E, dig_P9)){
- #ifdef _debugSerial
- Serial.print("dig_T1="); Serial.println(dig_T1,2);
- Serial.print("dig_T2="); Serial.println(dig_T2,2);
- Serial.print("dig_T3="); Serial.println(dig_T3,2);
- Serial.print("dig_P1="); Serial.println(dig_P1,2);
- Serial.print("dig_P2="); Serial.println(dig_P2,2);
- Serial.print("dig_P3="); Serial.println(dig_P3,2);
- Serial.print("dig_P4="); Serial.println(dig_P4,2);
- Serial.print("dig_P5="); Serial.println(dig_P5,2);
- Serial.print("dig_P6="); Serial.println(dig_P6,2);
- Serial.print("dig_P7="); Serial.println(dig_P7,2);
- Serial.print("dig_P8="); Serial.println(dig_P8,2);
- Serial.print("dig_P9="); Serial.println(dig_P9,2);
- #endif
- #ifdef _debugTestData
- dig_T1 = 27504.0;
- dig_T2 = 26435.0;
- dig_T3 = -1000.0;
- dig_P1 = 36477.0;
- dig_P2 = -10685.0;
- dig_P3 = 3024.0;
- dig_P4 = 2855.0;
- dig_P5 = 140.0;
- dig_P6 = -7.0;
- dig_P7 = 15500.0;
- dig_P8 = -14600.0;
- dig_P9 = 6000.0;
- Serial.print("dig_T1="); Serial.println(dig_T1,2);
- Serial.print("dig_T2="); Serial.println(dig_T2,2);
- Serial.print("dig_T3="); Serial.println(dig_T3,2);
- Serial.print("dig_P1="); Serial.println(dig_P1,2);
- Serial.print("dig_P2="); Serial.println(dig_P2,2);
- Serial.print("dig_P3="); Serial.println(dig_P3,2);
- Serial.print("dig_P4="); Serial.println(dig_P4,2);
- Serial.print("dig_P5="); Serial.println(dig_P5,2);
- Serial.print("dig_P6="); Serial.println(dig_P6,2);
- Serial.print("dig_P7="); Serial.println(dig_P7,2);
- Serial.print("dig_P8="); Serial.println(dig_P8,2);
- Serial.print("dig_P9="); Serial.println(dig_P9,2);
- #endif
- return (1);
- }
- else
- return (0);
- }
- /*
- ** Read a signed integer (two bytes) from device
- ** @param : address = register to start reading (plus subsequent register)
- ** @param : value = external variable to store data (function modifies value)
- */
- char BMP280::readInt(char address, double &value)
- {
- unsigned char data[2]; //char is 4bit,1byte
- data[0] = address;
- if (readBytes(data,2))
- {
- value = (double)(int16_t)(((unsigned int)data[1]<<8)|(unsigned int)data[0]); //
- return(1);
- }
- value = 0;
- return(0);
- }
- /*
- ** Read an unsigned integer (two bytes) from device
- ** @param : address = register to start reading (plus subsequent register)
- ** @param : value = external variable to store data (function modifies value)
- */
- char BMP280::readUInt(char address, double &value)
- {
- unsigned char data[2]; //4bit
- data[0] = address;
- if (readBytes(data,2))
- {
- value = (double)(unsigned int)(((unsigned int)data[1]<<8)|(unsigned int)data[0]);
- return(1);
- }
- value = 0;
- return(0);
- }
- /*
- ** Read an array of bytes from device
- ** @param : value = external array to hold data. Put starting register in values[0].
- ** @param : length = number of bytes to read
- */
- char BMP280::readBytes(unsigned char *values, char length)
- {
- char x;
- Wire.beginTransmission(BMP280_ADDR);
- Wire.write(values[0]);
- error = Wire.endTransmission();
- if (error == 0)
- {
- Wire.requestFrom(BMP280_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);
- }
- /*
- ** Write an array of bytes to device
- ** @param : values = external array of data to write. Put starting register in values[0].
- ** @param : length = number of bytes to write
- */
- char BMP280::writeBytes(unsigned char *values, char length)
- {
- Wire.beginTransmission(BMP280_ADDR);
- Wire.write(values,length);
- error = Wire.endTransmission();
- if (error == 0)
- return(1);
- else
- return(0);
- }
- short BMP280::getOversampling(void)
- {
- return oversampling;
- }
- char BMP280::setOversampling(short oss)
- {
- oversampling = oss;
- return (1);
- }
- /*
- ** Begin a measurement cycle.
- ** Oversampling: 0 to 4, higher numbers are slower, higher-res outputs.
- ** @returns : delay in ms to wait, or 0 if I2C error.
- */
- char BMP280::startMeasurment(void)
- {
- unsigned char data[2], result, delay;
-
- data[0] = BMP280_REG_CONTROL;
- switch (oversampling)
- {
- case 0:
- data[1] = BMP280_COMMAND_PRESSURE0;
- oversampling_t = 1;
- delay = 8;
- break;
- case 1:
- data[1] = BMP280_COMMAND_PRESSURE1;
- oversampling_t = 1;
- delay = 10;
- break;
- case 2:
- data[1] = BMP280_COMMAND_PRESSURE2;
- oversampling_t = 1;
- delay = 15;
- break;
- case 3:
- data[1] = BMP280_COMMAND_PRESSURE3;
- oversampling_t = 1;
- delay = 24;
- break;
- case 4:
- data[1] = BMP280_COMMAND_PRESSURE4;
- oversampling_t = 1;
- delay = 45;
- break;
- case 16:
- data[1] = BMP280_COMMAND_OVERSAMPLING_MAX;
- oversampling_t = 1;
- delay = 80; //I cannot find any data about timings in datasheet for x16 pressure and x16 temeprature oversampling
- break; //I guess this is enough time (maybe it can be even smaller ~60ms)
- default:
- data[1] = BMP280_COMMAND_PRESSURE0;
- delay = 9;
- 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
- }
- /*
- ** Get the uncalibrated pressure and temperature value.
- ** @param : uP = stores the uncalibrated pressure value.(20bit)
- ** @param : uT = stores the uncalibrated temperature value.(20bit)
- */
- char BMP280::getUnPT(double &uP, double &uT)
- {
- unsigned char data[6];
- char result;
-
- data[0] = BMP280_REG_RESULT_PRESSURE; //0xF7
- result = readBytes(data, 6); // 0xF7; xF8, 0xF9, 0xFA, 0xFB, 0xFC
- if (result) // good read
- {
- double factor = pow(2, 4);
- uP = (double)(data[0] *4096 + data[1]*16 + data[2]/16) ; //20bit UP
- uT = (double)(data[3]*4096 + data[4]*16 + data[5]/16) ; //20bit UT
- #ifdef _debugSerial
- Serial.print(uT);
- Serial.print(" ");
- Serial.println(uP);
- #endif
- #ifdef _debugTestData
- uT = 519888.0;
- uP = 415148.0;
- Serial.print(uT);
- Serial.print(" ");
- Serial.println(uP);
- #endif
- }
- return(result);
- }
- /*
- ** Retrieve temperature and pressure.
- ** @param : T = stores the temperature value in degC.
- ** @param : P = stores the pressure value in mBar.
- */
- char BMP280::getTemperatureAndPressure(double &T,double &P)
- {
- double uT ;
- double uP;
- char result = getUnPT(uP,uT);
- if(result!=0){
- // calculate the temperature
- result = calcTemperature(T,uT);
- if(result){
- // calculate the pressure
- result = calcPressure(P,uP);
- if(result)return (1);
- else error = 3 ; // pressure error ;
- return (9);
- }else
- error = 2; // temperature error ;
- }
- else
- error = 1;
-
- return (9);
- }
- /*
- ** temperature calculation
- ** @param : T = stores the temperature value after calculation.
- ** @param : uT = the uncalibrated temperature value.
- */
- char BMP280::calcTemperature(double &T, double &adc_T)
- //
- {
- //Serial.print("adc_T = "); Serial.println(adc_T,DEC);
-
- double var1 = (adc_T/16384.0 - dig_T1/1024.0)*dig_T2;
- double var2 = ((adc_T/131072.0 - dig_T1/8192.0)*(adc_T/131072.0 - dig_T1/8192.0))*dig_T3;
- t_fine = var1+var2;
- T = (var1+var2)/5120.0;
- #ifdef _debugSerial
- Serial.print(var1);
- Serial.print(" ");
- Serial.print(var2);
- Serial.print(" ");
- Serial.print(t_fine);
- Serial.print(" ");
- Serial.println(T);
- #endif
-
- if(T>100 || T <-100)return 0;
-
- return (1);
- }
- /*
- ** Pressure calculation from uncalibrated pressure value.
- ** @param : P = stores the pressure value.
- ** @param : uP = uncalibrated pressure value.
- */
- char BMP280::calcPressure(double &P,double uP)
- {
- //char result;
- double var1 , var2 ;
-
- var1 = (t_fine/2.0) - 64000.0;
- #ifdef _debugSerial
- Serial.print("var1 = ");Serial.println(var1,2);
- #endif
- var2 = var1 * (var1 * dig_P6/32768.0); //not overflow
- #ifdef _debugSerial
- Serial.print("var2 = ");Serial.println(var2,2);
- #endif
- var2 = var2 + (var1 * dig_P5 * 2.0); //overflow
- #ifdef _debugSerial
- Serial.print("var2 = ");Serial.println(var2,2);
- #endif
-
- var2 = (var2/4.0)+((dig_P4)*65536.0);
- #ifdef _debugSerial
- Serial.print("var2 = ");Serial.println(var2,2);
- #endif
-
- var1 = (dig_P3 * var1 * var1/524288.0 + dig_P2 * var1) / 524288.0;
- #ifdef _debugSerial
- Serial.print("var1 = ");Serial.println(var1,2);
- #endif
- var1 = (1.0 + var1/32768.0) * dig_P1;
- #ifdef _debugSerial
- Serial.print("var1 = ");Serial.println(var1,2);
- #endif
-
- P = 1048576.0- uP;
- #ifdef _debugSerial
- Serial.print("p = ");Serial.println(p,2);
- #endif
-
- P = (P-(var2/4096.0))*6250.0/var1 ; //overflow
- #ifdef _debugSerial
- Serial.print("p = ");Serial.println(p,2);
- #endif
-
- var1 = dig_P9*P*P/2147483648.0; //overflow
- #ifdef _debugSerial
- Serial.print("var1 = ");Serial.println(var1,2);
- #endif
- var2 = P*dig_P8/32768.0;
- #ifdef _debugSerial
- Serial.print("var2 = ");Serial.println(var2,2);
- #endif
- P = P + (var1+var2+dig_P7)/16.0;
- #ifdef _debugSerial
- Serial.print("p = ");Serial.println(p,2);
- #endif
-
- P = P/100.0 ;
-
- if(P>1200.0 || P < 800.0)return (0);
- return (1);
- }
- double BMP280::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 BMP280::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 BMP280::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);
- }
|