Skip to content

Commit

Permalink
Add new functionality to Bme680 binding (#482)
Browse files Browse the repository at this point in the history
* Add driver

* Add samples

* Add Readme

* Add missing reference

* Remove unreachable code, remove TODOs

* Update I2C address in samples

* Modify csproj to only compile default sample

* Bit manipulation and documentation updates, small bugfix

* sample update

* remove outdated binding

* Fix temperature compensating formula

* Add remaining registers

* Add data masks

* Add HeaterProfile enum

* Add status properties + current heater profile

* Update csproj

* Add filtering mode for Bme680

* Add remaining calibration registers

* Simplify methods, add setFilterMode

* Add HeaterProfileConfig class

* Add gas measurement functionality

* Add gas measurement functionality for real...

* Use methods where appropriate, update sample

* Update Bme280 sample

* Add default configuration

* Reset device upon initial config, update samples

* Add license notice

* Set defaults through constructor, update sample

* Cache values instead of repeated reading from device

* Improve caching behavior, update samples

* Update Bmp280 sample

* Add missing headers

* fix typo

* Add missing xml documentation, argument check

* Update sample

* Add missing caching of values

* move fields to top of file

* Rename CurrentHeaterProfile

* Update sample

* fix CI

* Use stackalloc, make appropriate variables static

* Update read methods to work synchronous

* Remove async signature from samples

* Update methods to burst read registers if possible

* fix xml documentation

* Change Read methods to TryRead

* Align behavior with Bmx280 bindings

* fix method call

* update xml documentation

* Update doc, remove Todo, adhere to naming guideline

* Update README.md

* Add missing xml docs

* Load calibration and default config in base

* Remove redundant import

* minor update to readme
  • Loading branch information
RobinTTY authored and joperezr committed Sep 11, 2019
1 parent 711f3bc commit 9813c3a
Show file tree
Hide file tree
Showing 23 changed files with 1,044 additions and 413 deletions.
104 changes: 61 additions & 43 deletions src/devices/Bmxx80/Bme280.cs
Expand Up @@ -2,18 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Device.I2c;
using System.Threading.Tasks;
using Iot.Device.Bmxx80.CalibrationData;
using Iot.Device.Bmxx80.PowerMode;
using Iot.Device.Bmxx80.Register;

namespace Iot.Device.Bmxx80
{
/// <summary>
/// Represents a BME280 temperature, barometric pressure and humidity sensor.
/// </summary>
public class Bme280 : Bmx280Base
public sealed class Bme280 : Bmx280Base
{
/// <summary>
/// The expected chip ID of the BME280.
Expand All @@ -23,7 +22,9 @@ public class Bme280 : Bmx280Base
/// <summary>
/// Calibration data for the <see cref="Bme680"/>.
/// </summary>
private readonly Bme280CalibrationData _bme280Calibration;
private Bme280CalibrationData _bme280Calibration;

private Sampling _humiditySampling;

/// <summary>
/// Initializes a new instance of the <see cref="Bme280"/> class.
Expand All @@ -32,62 +33,79 @@ public class Bme280 : Bmx280Base
public Bme280(I2cDevice i2cDevice)
: base(DeviceId, i2cDevice)
{
var bme280CalibrationData = new Bme280CalibrationData();
bme280CalibrationData.ReadFromDevice(this);
_bme280Calibration = bme280CalibrationData;
_calibrationData = bme280CalibrationData;

_bme280Calibration = (Bme280CalibrationData)_calibrationData;
_communicationProtocol = CommunicationProtocol.I2c;
}

/// <summary>
/// Get the current sample rate for humidity measurements.
/// Gets or sets the humidity sampling.
/// </summary>
/// <returns>The humidity <see cref="Sampling"/>.</returns>
public Sampling ReadHumiditySampling()
/// <exception cref="ArgumentOutOfRangeException">Thrown when the <see cref="Sampling"/> is set to an undefined mode.</exception>
public Sampling HumiditySampling
{
byte status = Read8BitsFromRegister((byte)Bme280Register.CTRL_HUM);
status = (byte)(status & 0b_0000_0111);
return ByteToSampling(status);
get => _humiditySampling;
set
{
if (!Enum.IsDefined(typeof(Sampling), value))
throw new ArgumentOutOfRangeException();

byte status = Read8BitsFromRegister((byte)Bme280Register.CTRL_HUM);
status = (byte)(status & 0b_1111_1000);
status = (byte)(status | (byte)value);

Span<byte> command = stackalloc[] {(byte)Bme280Register.CTRL_HUM, status};
_i2cDevice.Write(command);

// Changes to the above register only become effective after a write operation to "CTRL_MEAS".
byte measureState = Read8BitsFromRegister((byte)Bmx280Register.CTRL_MEAS);

command = stackalloc[] {(byte)Bmx280Register.CTRL_MEAS, measureState};
_i2cDevice.Write(command);
_humiditySampling = value;
}
}

/// <summary>
/// Sets the humidity sampling to the given value.
/// Reads the humidity. A return value indicates whether the reading succeeded.
/// </summary>
/// <param name="sampling">The <see cref="Sampling"/> to set.</param>
public void SetHumiditySampling(Sampling sampling)
/// <param name="humidity">
/// Contains the measured humidity as %rH if the <see cref="HumiditySampling"/> was not set to <see cref="Sampling.Skipped"/>.
/// Contains <see cref="double.NaN"/> otherwise.
/// </param>
/// <returns><code>true</code> if measurement was not skipped, otherwise <code>false</code>.</returns>
public bool TryReadHumidity(out double humidity)
{
byte status = Read8BitsFromRegister((byte)Bme280Register.CTRL_HUM);
status = (byte)(status & 0b_1111_1000);
status = (byte)(status | (byte)sampling);
_i2cDevice.Write(new[] { (byte)Bme280Register.CTRL_HUM, status });

// Changes to the above register only become effective after a write operation to "CTRL_MEAS".
byte measureState = Read8BitsFromRegister((byte)Bmx280Register.CTRL_MEAS);
_i2cDevice.Write(new[] { (byte)Bmx280Register.CTRL_MEAS, measureState });
if (HumiditySampling == Sampling.Skipped)
{
humidity = double.NaN;
return false;
}

// Read the temperature first to load the t_fine value for compensation.
TryReadTemperature(out _);

var hum = Read16BitsFromRegister((byte)Bme280Register.HUMIDDATA, Endianness.BigEndian);

humidity = CompensateHumidity(hum);
return true;
}

/// <summary>
/// Reads the Humidity from the sensor as %rH.
/// Gets the required time in ms to perform a measurement with the current sampling modes.
/// </summary>
/// <returns>Returns a percentage from 0 to 100.</returns>
public async Task<double> ReadHumidityAsync()
/// <returns>The time it takes for the chip to read data in milliseconds rounded up.</returns>
public override int GetMeasurementDuration()
{
if (ReadPowerMode() == Bmx280PowerMode.Forced)
{
await Task.Delay(GetMeasurementTimeForForcedMode(ReadHumiditySampling()));
}

// Read the temperature first to load the t_fine value for compensation.
await ReadTemperatureAsync();

byte msb = Read8BitsFromRegister((byte)Bme280Register.HUMIDDATA_MSB);
byte lsb = Read8BitsFromRegister((byte)Bme280Register.HUMIDDATA_LSB);

// Combine the values into a 32-bit integer.
int t = (msb << 8) | lsb;
return s_osToMeasCycles[(int)PressureSampling] + s_osToMeasCycles[(int)TemperatureSampling] + s_osToMeasCycles[(int)HumiditySampling];
}

return CompensateHumidity(t);
/// <summary>
/// Sets the default configuration for the sensor.
/// </summary>
protected override void SetDefaultConfiguration()
{
base.SetDefaultConfiguration();
HumiditySampling = Sampling.UltraLowPower;
}

/// <summary>
Expand Down

0 comments on commit 9813c3a

Please sign in to comment.