GrovePi
GrovePi copied to clipboard
Add support for: Grove - Temp&Humi&Barometer Sensor (BME280)
Here's the code for the sensor, if you want to integrate into your library. For the C# Win 10 IoT
All features of the sensor work as expected.
class SensorBME280
{
private I2cDevice SensorBme280;
private byte SensorAddress = 0x76;
// BME280 Calibration variables
private UInt16 T1;
private Int16 T2;
private Int16 T3;
private UInt16 P1;
private Int16 P2;
private Int16 P3;
private Int16 P4;
private Int16 P5;
private Int16 P6;
private Int16 P7;
private Int16 P8;
private Int16 P9;
private byte H1;
private Int16 H2;
private byte H3;
private Int16 H4;
private Int16 H5;
private Int16 H6;
// BME280 Data register addresses
private byte HumLsbAddr = 0xfe;
private byte HumMsbAddr = 0xfd;
private byte TmpXlsbAddr = 0xfc;
private byte TmpLsbAddr = 0xfb;
private byte TmpMsbAddr = 0xfa;
private byte PreXlsbAddr = 0xf9;
private byte PreLsbAddr = 0xf8;
private byte PreMsbAddr = 0xf7;
// BME280 Variable data calibration
private Int32 t_fine = Int32.MinValue;
// BME280 Calibration data address
enum Register : byte
{
Dig_T1 = 0x88,
Dig_T2 = 0x8a,
Dig_T3 = 0x8c,
Dig_P1 = 0x8e,
Dig_P2 = 0x90,
Dig_P3 = 0x92,
Dig_P4 = 0x94,
Dig_P5 = 0x96,
Dig_P6 = 0x98,
Dig_P7 = 0x9a,
Dig_P8 = 0x9c,
Dig_P9 = 0x9e,
Dig_H1 = 0xa1,
Dig_H2 = 0xe1,
Dig_H3 = 0xe3,
Dig_H4 = 0xe4,
Dig_H5 = 0xe5,
Dig_H6 = 0xe7,
}
// BME280 measurement data acquisition register address
enum Command : byte
{
ReadTemperature = 0xfa,
ReadPressure = 0xf7,
ReadHumidity = 0xfd,
}
public async void InitializeSensor()
{
I2cController I2c = await I2cController.GetDefaultAsync();
SensorBme280 = I2c.GetDevice(new I2cConnectionSettings(SensorAddress));
// Sensor initialization
uint osrs_t = 3;
uint osrs_p = 3;
uint osrs_h = 3;
uint mode = 3;
uint t_sb = 5;
uint filter = 0;
uint spi3w_en = 0;
uint ctrlMeasReg = (osrs_t << 5) | (osrs_p << 2) | mode;
uint configReg = (t_sb << 5) | (filter << 2) | spi3w_en;
uint ctrlHumReg = osrs_h;
SensorBme280.Write(new byte[] { 0xf2, (byte)ctrlHumReg });
SensorBme280.Write(new byte[] { 0xf4, (byte)ctrlMeasReg });
SensorBme280.Write(new byte[] { 0xf5, (byte)configReg });
await Task.Delay(10);
// Load calibration data
// Temperature
T1 = ReadUInt16((byte)Register.Dig_T1);
T2 = (Int16)ReadUInt16((byte)Register.Dig_T2);
T3 = (Int16)ReadUInt16((byte)Register.Dig_T3);
// Barometric pressure
P1 = ReadUInt16((byte)Register.Dig_P1);
P2 = (Int16)ReadUInt16((byte)Register.Dig_P2);
P3 = (Int16)ReadUInt16((byte)Register.Dig_P3);
P4 = (Int16)ReadUInt16((byte)Register.Dig_P4);
P5 = (Int16)ReadUInt16((byte)Register.Dig_P5);
P6 = (Int16)ReadUInt16((byte)Register.Dig_P6);
P7 = (Int16)ReadUInt16((byte)Register.Dig_P7);
P8 = (Int16)ReadUInt16((byte)Register.Dig_P8);
P9 = (Int16)ReadUInt16((byte)Register.Dig_P9);
// Humidity
H1 = ReadByte((byte)Register.Dig_H1);
H2 = (Int16)ReadUInt16((byte)Register.Dig_H2);
H3 = ReadByte((byte)Register.Dig_H3);
H4 = (short)(ReadByte((byte)Register.Dig_H4) << 4 | ReadByte((byte)Register.Dig_H4 + 1) & 0xf);
H5 = (short)(ReadByte((byte)Register.Dig_H5 + 1) << 4 | ReadByte((byte)Register.Dig_H5) >> 4);
H6 = (sbyte)ReadByte((byte)Register.Dig_H6);
}
/// <summary>
/// Temperature data acquisition (Celsius)
/// </summary>
/// <returns></returns>
public async Task<double> ReadTemperature()
{
byte tmsb = ReadByte(TmpMsbAddr);
byte tlsb = ReadByte(TmpLsbAddr);
byte txlsb = ReadByte(TmpXlsbAddr);
Int32 tmpRaw = (tmsb << 12) | (tlsb << 4) | (txlsb >> 4);
double var1, var2, T;
var1 = ((tmpRaw / 16384.0) - (T1 / 1024.0)) * T2;
var2 = ((tmpRaw / 131072.0) - (T1 / 8192.0)) * T3;
t_fine = (Int32)(var1 + var2);
T = (var1 + var2) / 5120.0;
await Task.Delay(1);
return T;
}
/// <summary>
/// Pressure data acquisition (Hectopascal)
/// </summary>
/// <returns></returns>
public async Task<double> ReadPressure()
{
byte pmsb = ReadByte(PreMsbAddr);
byte plsb = ReadByte(PreLsbAddr);
byte pxlsb = ReadByte(PreXlsbAddr);
Int32 preRaw = (pmsb << 12) | (plsb << 4) | (pxlsb >> 4);
Int64 var1, var2, P;
var1 = t_fine - 128000;
var2 = var1 * var1 * (Int64)P6;
var2 = var2 + ((var1 * (Int64)P5) << 17);
var2 = var2 + ((Int64)P4 << 35);
var1 = ((var1 * var1 * (Int64)P3) >> 8) + ((var1 * (Int64)P2) << 12);
var1 = (((((Int64)1 << 47) + var1)) * (Int64)P1) >> 33;
if (var1 == 0)
{
return 0;
}
P = 1048576 - preRaw;
P = (((P << 31) - var2) * 3125) / var1;
var1 = ((Int64)P9 * (P >> 13)) >> 25;
var2 = ((Int64)P8 * P) >> 19;
P = ((P + var1 + var2) >> 8) + ((Int64)P7 << 4);
await Task.Delay(1);
return (double)(P / 256 / 100);
}
/// <summary>
/// Humidity data acquisition (Relative Humidity)
/// </summary>
/// <returns></returns>
public async Task<double> ReadHumidity()
{
byte hmsb = ReadByte(HumMsbAddr);
byte hlsb = ReadByte(HumLsbAddr);
int humRaw = (hmsb << 8) | hlsb;
Int32 H;
H = t_fine - 76800;
H = (((((humRaw << 14) - (((Int32)H4) << 20) - ((Int32)H5 * H)) + ((Int32)16384)) >> 15) * (((((((H * ((Int32)H6)) >> 10) * (((H * ((Int32)H3)) >> 11) + ((Int32)32768))) >> 10) + ((Int32)2097152)) * ((Int32)H2) + 8192) >> 14));
H = (H - (((((H >> 15) * (H >> 15)) >> 7) * ((Int32)H1)) >> 4));
H = (H < 0 ? 0 : H);
H = (H > 419430400 ? 419430400 : H);
await Task.Delay(1);
return (UInt32)((H >> 12) / 1000);
}
public double ReadAltitude(double pressure, bool useInternationalFormula = true)
{
if (useInternationalFormula)
{
// International Barometric Formula
return 44330.0f * (1.0f - (float)Math.Pow((pressure / 1013), 0.1903f));
}
else
{
// Seeedstudio Grove BME280 formula
double a = pressure / 101325;
double b = 1 / 5.25588;
double c = Math.Pow(a, b);
c = 1.0 - c;
c = c / 0.0000225577;
c = c / 100;
return c;
}
}
/// <summary>
/// Double-byte data readout
/// </summary>
/// <param name="register"></param>
/// <returns></returns>
private UInt16 ReadUInt16(byte register)
{
byte[] writeBuf = new byte[] { 0x00 };
byte[] readBuf = new byte[] { 0x00, 0x00 };
writeBuf[0] = register;
SensorBme280.WriteRead(writeBuf, readBuf);
int h = readBuf[1] << 8;
int l = readBuf[0];
return (UInt16)(h + l);
}
/// <summary>
/// Read byte
/// </summary>
/// <param name="register"></param>
/// <returns></returns>
private byte ReadByte(byte register)
{
byte[] writeBuf = new byte[] { 0x00 };
byte[] readBuf = new byte[] { 0x00 };
writeBuf[0] = register;
SensorBme280.WriteRead(writeBuf, readBuf);
return readBuf[0];
}
/// <summary>
/// Display temperature (°C)
/// </summary>
/// <returns></returns>
public string DisplayTemperature(double temperature)
{
return $"{Math.Round(temperature, 0)} °C";
}
/// <summary>
/// Display pressure (hPa)
/// </summary>
/// <returns></returns>
public string DisplayPressure(double pressure)
{
return $"{Math.Round(pressure, 1)} hPa";
}
/// <summary>
/// Display humidity (%rh)
/// </summary>
/// <returns></returns>
public string DisplayHumidity(double humidity)
{
return $"{Math.Round(humidity, 0)}% rh";
}
/// <summary>
/// Display altitude (m)
/// </summary>
/// <returns></returns>
public string DisplayAltitude(double altitude)
{
return $"{Math.Round(altitude, 0)} m";
}