esp32-ogn-tracker/main/bmp180.h

152 wiersze
5.8 KiB
C++

#ifndef __BMP180_H__
#define __BMP180_H__
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "hal.h"
class BMP180
{ private:
public:
static const uint8_t ADDR = 0x77; // BMP180 I2C address
private:
static const uint8_t REG_CALIB = 0xAA; // calibration register: 11x16bit (MSB first)
static const uint8_t REG_ID = 0xD0; // ID register: always reads 0x55
static const uint8_t REG_RESET = 0xE0; // write 0xB6 to perform soft-reset
static const uint8_t REG_MEAS = 0xF4; // measurement control: SSCMMMMM SS=oversampling, C=conversion, MMMMM=mode
static const uint8_t MEAS_TEMP = 0x2E; // measure temperature
static const uint8_t MEAS_PRESS = 0x34; // measure pressure
static const uint8_t MEAS_BUSY = 0x20; // measurement-busy flag
static const uint8_t REG_ADC = 0xF6; // ADC result: 2 or 3 bytes
static const uint8_t REG_ADC_MSB = 0xF6; // ADC result: MSB
static const uint8_t REG_ADC_LSB = 0xF7; // ADC result: LSB
static const uint8_t REG_ADC_XLSB = 0xF8; // ADC result: more LSB
static const uint8_t MEAS_OSS = 0x03; // oversampling factor: 0=single, 1=two, 2=four, 3=eight samples
public:
uint8_t Bus; // which I2C bus
private:
union
{ int16_t Calib[11];
struct
{ int16_t AC1, AC2, AC3; // 11 calibration values from EEPROM
uint16_t AC4, AC5, AC6;
int16_t B1, B2;
int16_t MB, MC, MD;
} ;
} ;
int32_t B5; // temperature compensation for pressure ?
public:
uint8_t Error; // error on the I2C bus (0=no error)
uint16_t RawTemp; // raw temperature - to be processed
int16_t Temperature; // [0.1 degC] after processing
uint32_t RawPress; // raw pressure - to be processed
uint32_t Pressure; // [ Pa ] after processing
private:
static uint16_t SwapBytes(uint16_t Word) { return (Word>>8) | (Word<<8); }
static uint16_t SwapBytes( int16_t Word) { return SwapBytes((uint16_t)Word); }
static void SwapBytes(uint16_t *Word, uint8_t Bytes)
{ uint8_t Words=Bytes>>1;
for(uint8_t Idx=0; Idx<Words; Idx++)
Word[Idx]=SwapBytes(Word[Idx]);
}
public:
void DefaultCalib(void) // set default calibration constants
{ AC1 = 408;
AC2 = -72;
AC3 = -14383;
AC4 = 32741;
AC5 = 32757;
AC6 = 23153;
B1 = 6190;
B2 = 4;
MB = -32768;
MC = -8711;
MD = 2868; }
uint8_t CheckID(void) // check ID, to make sure the BMP180 is connected and works correctly
{ uint8_t ID;
Error=I2C_Read(Bus, ADDR, REG_ID, ID); if(Error) return Error;
return ID!=0x55; } // 0 => no error and correct ID
uint8_t ReadCalib(void) // read the calibration constants from the EEPROM
{ Error=I2C_Read(Bus, ADDR, REG_CALIB, (uint8_t *)Calib, 2*11); if(Error) return Error;
SwapBytes((uint16_t *)Calib, 2*11 ); return Error; }
uint8_t ReadReady(void) // check if temperature or pressure conversion is done
{ uint8_t MeasCtrl;
Error=I2C_Read(Bus, ADDR, REG_MEAS, MeasCtrl); if(Error) return Error;
return (MeasCtrl&MEAS_BUSY)==0; } // 0 = busy, 1 => ready
uint8_t WaitReady(uint8_t Timeout=4, uint8_t Wait=4) // wait for the conversion to be ready
{ vTaskDelay(Wait);
for(; Timeout; Timeout--)
{ uint8_t Err=ReadReady(); if(Err>1) return Err;
if(Err==1) return 0;
vTaskDelay(1); }
return 0xFF; }
uint8_t TriggRawTemperature(void) // start a temperature measurement
{ uint8_t Ctrl=MEAS_TEMP;
Error=I2C_Write(Bus, ADDR, REG_MEAS, Ctrl); return Error; }
uint8_t ReadRawTemperature(void)
{ Error=I2C_Read(Bus, ADDR, REG_ADC, RawTemp); if(Error) return Error;
RawTemp=SwapBytes(RawTemp); return 0; }
uint8_t AcquireRawTemperature(void) //
{ uint8_t Err=TriggRawTemperature(); if(Err) return Err;
Err=WaitReady(4, 4); if(Err) return Err;
return ReadRawTemperature(); }
uint8_t TrigRawPressure(void) // start a pressure measurement
{ uint8_t Ctrl=(MEAS_OSS<<6) | MEAS_PRESS;
Error=I2C_Write(Bus, ADDR, REG_MEAS, Ctrl); return Error; }
uint8_t ReadRawPressure(void)
{ RawPress=0;
Error=I2C_Read(Bus, ADDR, REG_ADC, (uint8_t *)(&RawPress), 3); if(Error) return Error;
RawPress = ((RawPress<<16)&0xFF0000) | (RawPress&0x00FF00) | ((RawPress>>16)&0x0000FF);
RawPress>>=(8-MEAS_OSS);
return 0; }
uint8_t AcquireRawPressure(void)
{ uint8_t Err=TrigRawPressure(); if(Err) return Err;
uint8_t Timeout = (((uint8_t)1<<MEAS_OSS)+2)<<1;
Err=WaitReady(Timeout, Timeout); if(Err) return Err;
return ReadRawPressure(); }
// temperature and pressure calculation routines takes from the datasheet
void CalcTemperature(void) // calculate the temperature from raw readout and calibration values
{ int32_t X1 = ( (( (int32_t)RawTemp - (int32_t)AC6 )*(int32_t)AC5) )>>15;
int32_t X2 = ((int32_t)MC<<11)/(X1+(int32_t)MD);
B5 = X1+X2;
Temperature = (B5+8)>>4; }
void CalcPressure(void) // calculate the pressure - must calculate the temperature first !
{ int32_t B6 = B5-4000;
int32_t X1 = ((int32_t)B2*((B6*B6)>>12))>>11;
int32_t X2 = ((int32_t)AC2*B6)>>11;
int32_t X3 = X1+X2;
int32_t B3 = (((((int32_t)AC1<<2)+X3)<<MEAS_OSS)+2)>>2;
X1 = ((int32_t)AC3*B6)>>13;
X2 = ((int32_t)B1*((B6*B6)>>12))>>16;
X3 = ((X1+X2)+2)>>2;
uint32_t B4 = ((uint32_t)AC4*(uint32_t)(X3+32768))>>15;
uint32_t B7 = (RawPress-B3)*((uint32_t)50000>>MEAS_OSS);
if(B7&0x8000000) { Pressure = (B7/B4)<<1; }
else { Pressure = (B7<<1)/B4; }
X1 = (Pressure>>8)*(Pressure>>8);
X1 = (X1*3038)>>16;
X2 = (-7357*(int32_t)Pressure)>>16;
Pressure += (X1+X2+3791)>>4; }
} ;
#endif // __BMP180_H__