2016年4月13日 星期三

MS5611 arduino code



#define MS5611_ADDRESS (0x77)

#define MS5611_CMD_ADC_READ (0x00)
#define MS5611_CMD_RESET (0x1E)
#define MS5611_CMD_CONV_D1 (0x40)
#define MS5611_CMD_CONV_D2 (0x50)
#define MS5611_CMD_READ_PROM (0xA2)

typedef enum
{
MS5611_ULTRA_HIGH_RES = 0x08,
MS5611_HIGH_RES = 0x06,
MS5611_STANDARD = 0x04,
MS5611_LOW_POWER = 0x02,
MS5611_ULTRA_LOW_POWER = 0x00
} ms5611_osr_t;
class MS5611
{
public:
bool begin(ms5611_osr_t osr = MS5611_HIGH_RES);
uint32_t readRawTemperature(void);
uint32_t readRawPressure(void);
double readTemperature(bool compensation = false);
int32_t readPressure(bool compensation = false);
double getAltitude(double pressure, double seaLevelPressure = 101325);
double getSeaLevel(double pressure, double altitude);
void setOversampling(ms5611_osr_t osr);
ms5611_osr_t getOversampling(void);
private:
uint16_t fc[6];
uint8_t ct;
uint8_t uosr;
int32_t TEMP2;
int64_t OFF2, SENS2;
void reset(void);
void readPROM(void);
uint16_t readRegister16(uint8_t reg);
uint32_t readRegister24(uint8_t reg);
};

#include <Wire.h>
#include <math.h>
#include <MS5611.h>
bool MS5611::begin(ms5611_osr_t osr)
{
Wire.begin();
reset();
setOversampling(osr);
delay(100);
readPROM();
return true;
}
// Set oversampling value
void MS5611::setOversampling(ms5611_osr_t osr)
{
switch (osr)
{
case MS5611_ULTRA_LOW_POWER:
ct = 1;
break;
case MS5611_LOW_POWER:
ct = 2;
break;
case MS5611_STANDARD:
ct = 3;
break;
case MS5611_HIGH_RES:
ct = 5;
break;
case MS5611_ULTRA_HIGH_RES:
ct = 10;
break;
}
uosr = osr;
}
// Get oversampling value
ms5611_osr_t MS5611::getOversampling(void)
{
return (ms5611_osr_t)uosr;
}
void MS5611::reset(void)
{
Wire.beginTransmission(MS5611_ADDRESS);
#if ARDUINO >= 100
Wire.write(MS5611_CMD_RESET);
#else
Wire.send(MS5611_CMD_RESET);
#endif
Wire.endTransmission();
}
void MS5611::readPROM(void)
{
for (uint8_t offset = 0; offset < 6; offset++)
{
fc[offset] = readRegister16(MS5611_CMD_READ_PROM + (offset * 2));
}
}
uint32_t MS5611::readRawTemperature(void)
{
Wire.beginTransmission(MS5611_ADDRESS);
#if ARDUINO >= 100
Wire.write(MS5611_CMD_CONV_D2 + uosr);
#else
Wire.send(MS5611_CMD_CONV_D2 + uosr);
#endif
Wire.endTransmission();
delay(ct);
return readRegister24(MS5611_CMD_ADC_READ);
}
uint32_t MS5611::readRawPressure(void)
{
Wire.beginTransmission(MS5611_ADDRESS);
#if ARDUINO >= 100
Wire.write(MS5611_CMD_CONV_D1 + uosr);
#else
Wire.send(MS5611_CMD_CONV_D1 + uosr);
#endif
Wire.endTransmission();
delay(ct);
return readRegister24(MS5611_CMD_ADC_READ);
}
int32_t MS5611::readPressure(bool compensation)
{
uint32_t D1 = readRawPressure();
uint32_t D2 = readRawTemperature();
int32_t dT = D2 - (uint32_t)fc[4] * 256;
int64_t OFF = (int64_t)fc[1] * 65536 + (int64_t)fc[3] * dT / 128;
int64_t SENS = (int64_t)fc[0] * 32768 + (int64_t)fc[2] * dT / 256;
if (compensation)
{
int32_t TEMP = 2000 + ((int64_t) dT * fc[5]) / 8388608;
OFF2 = 0;
SENS2 = 0;
if (TEMP < 2000)
{
OFF2 = 5 * ((TEMP - 2000) * (TEMP - 2000)) / 2;
SENS2 = 5 * ((TEMP - 2000) * (TEMP - 2000)) / 4;
}
if (TEMP < -1500)
{
OFF2 = OFF2 + 7 * ((TEMP + 1500) * (TEMP + 1500));
SENS2 = SENS2 + 11 * ((TEMP + 1500) * (TEMP + 1500)) / 2;
}
OFF = OFF - OFF2;
SENS = SENS - SENS2;
}
uint32_t P = (D1 * SENS / 2097152 - OFF) / 32768;
return P;
}
double MS5611::readTemperature(bool compensation)
{
uint32_t D2 = readRawTemperature();
int32_t dT = D2 - (uint32_t)fc[4] * 256;
int32_t TEMP = 2000 + ((int64_t) dT * fc[5]) / 8388608;
TEMP2 = 0;
if (compensation)
{
if (TEMP < 2000)
{
TEMP2 = (dT * dT) / (2 << 30);
}
}
TEMP = TEMP - TEMP2;
return ((double)TEMP/100);
}
// Calculate altitude from Pressure & Sea level pressure
double MS5611::getAltitude(double pressure, double seaLevelPressure)
{
return (44330.0f * (1.0f - pow((double)pressure / (double)seaLevelPressure, 0.1902949f)));
}
// Calculate sea level from Pressure given on specific altitude
double MS5611::getSeaLevel(double pressure, double altitude)
{
return ((double)pressure / pow(1.0f - ((double)altitude / 44330.0f), 5.255f));
}
// Read 16-bit from register (oops MSB, LSB)
uint16_t MS5611::readRegister16(uint8_t reg)
{
uint16_t value;
Wire.beginTransmission(MS5611_ADDRESS);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.beginTransmission(MS5611_ADDRESS);
Wire.requestFrom(MS5611_ADDRESS, 2);
while(!Wire.available()) {};
#if ARDUINO >= 100
uint8_t vha = Wire.read();
uint8_t vla = Wire.read();
#else
uint8_t vha = Wire.receive();
uint8_t vla = Wire.receive();
#endif;
Wire.endTransmission();
value = vha << 8 | vla;
return value;
}
// Read 24-bit from register (oops XSB, MSB, LSB)
uint32_t MS5611::readRegister24(uint8_t reg)
{
uint32_t value;
Wire.beginTransmission(MS5611_ADDRESS);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.beginTransmission(MS5611_ADDRESS);
Wire.requestFrom(MS5611_ADDRESS, 3);
while(!Wire.available()) {};
#if ARDUINO >= 100
uint8_t vxa = Wire.read();
uint8_t vha = Wire.read();
uint8_t vla = Wire.read();
#else
uint8_t vxa = Wire.receive();
uint8_t vha = Wire.receive();
uint8_t vla = Wire.receive();
#endif;
Wire.endTransmission();
value = ((int32_t)vxa << 16) | ((int32_t)vha << 8) | vla;
return value;
}

Reference : https://github.com/jarzebski/Arduino-MS5611

沒有留言:

張貼留言