DexterInd / DexterInd/GrovePi

Add support for: Grove - Temp&Humi&Barometer Sensor (BME280)

Open
#343 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
494
Forks
472
PR merge metrics
No merged PRs in 30d

Description

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";
        } 

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No project files, tests, or entry points are named. Start by inspecting existing Grove sensor integrations in the repository and compare their public API and I2C handling with the supplied SensorBME280 code; done means the BME280 is integrated into the library with temperature, pressure, humidity, altitude, and display functionality available.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, raspberry-pi
Domain
embedded-iot
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.