提交 fada3a8d 编写于 作者: Z Zhang Yuexin 提交者: Krzysztof Wicher

Refactoring DHT & Re-adding DHT12 & Adding DHT10 Binding (#518)

* resolve conflict

* remove redundant xml comment
上级 bbe0f6b8
// Licensed to the .NET Foundation under one or more agreements.
// 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;
using System.Device.I2c;
using Iot.Units;
namespace Iot.Device.DHTxx
{
/// <summary>
/// Temperature and Humidity Sensor DHT10
/// </summary>
public class Dht10 : DhtBase
{
/// <summary>
/// DHT10 Default I2C Address
/// </summary>
public const byte DefaultI2cAddress = 0x38;
// state, humi[20-13], humi[12-5], humi[4-1]temp[20-17], temp[16-9], temp[8-1]
private byte[] _dht10ReadBuff = new byte[6];
private const byte DHT10_CMD_INIT = 0b_1110_0001;
private const byte DHT10_CMD_START = 0b_1010_1100;
private const byte DHT10_CMD_SOFTRESET = 0b_1011_1010;
/// <summary>
/// Get the last read of relative humidity in percentage
/// </summary>
/// <remarks>
/// If last read was not successfull, it returns double.NaN
/// </remarks>
public override double Humidity
{
get
{
ReadData();
return GetHumidity(_dht10ReadBuff);
}
}
/// <summary>
/// Get the last read temperature
/// </summary>
/// <remarks>
/// If last read was not successfull, it returns double.NaN
/// </remarks>
public override Temperature Temperature
{
get
{
ReadData();
return GetTemperature(_dht10ReadBuff);
}
}
/// <summary>
/// Create a DHT10 sensor through I2C
/// </summary>
/// <param name="i2cDevice">I2C Device</param>
public Dht10(I2cDevice i2cDevice)
: base(i2cDevice)
{
_i2cDevice.WriteByte(DHT10_CMD_SOFTRESET);
// make sure DHT10 stable (in the datasheet P7)
DelayHelper.DelayMilliseconds(20, true);
_i2cDevice.WriteByte(DHT10_CMD_INIT);
}
internal override void ReadThroughI2c()
{
// DHT10 has no calibration bits
IsLastReadSuccessful = true;
_i2cDevice.WriteByte(DHT10_CMD_START);
// make sure DHT10 ends measurement (in the datasheet P7)
DelayHelper.DelayMilliseconds(75, true);
_i2cDevice.Read(_dht10ReadBuff);
}
internal override double GetHumidity(byte[] readBuff)
{
int raw = (((readBuff[1] << 8) | readBuff[2]) << 4) | readBuff[3] >> 4;
return raw / Math.Pow(2, 20) * 100;
}
internal override Temperature GetTemperature(byte[] readBuff)
{
int raw = ((((readBuff[3] & 0b_0000_1111) << 8) | readBuff[4]) << 8) | readBuff[5];
return Temperature.FromCelsius(raw / Math.Pow(2, 20) * 200 - 50);
}
}
}
......@@ -2,18 +2,31 @@
// 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.Device.Gpio;
using Iot.Units;
namespace Dhtxx.Devices
namespace Iot.Device.DHTxx
{
internal class Dht11Device : IDhtDevice
/// <summary>
/// Temperature and Humidity Sensor DHT11
/// </summary>
public class Dht11 : DhtBase
{
public double GetHumidity(byte[] readBuff)
/// <summary>
/// Create a DHT11 sensor
/// </summary>
/// <param name="pin">The pin number (GPIO number)</param>
/// <param name="pinNumberingScheme">The GPIO pin numbering scheme</param>
public Dht11(int pin, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
: base(pin, pinNumberingScheme)
{ }
internal override double GetHumidity(byte[] readBuff)
{
return readBuff[0] + readBuff[1] * 0.1;
}
public Temperature GetTemperature(byte[] readBuff)
internal override Temperature GetTemperature(byte[] readBuff)
{
var temp = readBuff[2] + readBuff[3] * 0.1;
return Temperature.FromCelsius(temp);
......
// Licensed to the .NET Foundation under one or more agreements.
// 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.Device.Gpio;
using System.Device.I2c;
using Iot.Units;
namespace Iot.Device.DHTxx
{
/// <summary>
/// Temperature and Humidity Sensor DHT12
/// </summary>
public class Dht12 : DhtBase
{
/// <summary>
/// DHT12 Default I2C Address
/// </summary>
public const byte DefaultI2cAddress = 0x5C;
/// <summary>
/// Create a DHT12 sensor
/// </summary>
/// <param name="pin">The pin number (GPIO number)</param>
/// <param name="pinNumberingScheme">The GPIO pin numbering scheme</param>
public Dht12(int pin, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
: base(pin, pinNumberingScheme)
{ }
/// <summary>
/// Create a DHT12 sensor through I2C
/// </summary>
/// <param name="i2cDevice">I2C Device</param>
public Dht12(I2cDevice i2cDevice)
: base(i2cDevice)
{ }
internal override double GetHumidity(byte[] readBuff)
{
return readBuff[0] + readBuff[1] * 0.1;
}
internal override Temperature GetTemperature(byte[] readBuff)
{
var temp = readBuff[2] + (readBuff[3] & 0x7F) * 0.1;
// if MSB = 1 we have negative temperature
temp = (readBuff[3] & 0x80) == 0 ? temp : -temp;
return Temperature.FromCelsius(temp);
}
}
}
......@@ -2,18 +2,31 @@
// 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.Device.Gpio;
using Iot.Units;
namespace Dhtxx.Devices
namespace Iot.Device.DHTxx
{
internal class Dht22Device : IDhtDevice
/// <summary>
/// Temperature and Humidity Sensor DHT21
/// </summary>
public class Dht21 : DhtBase
{
public double GetHumidity(byte[] readBuff)
/// <summary>
/// Create a DHT22 sensor
/// </summary>
/// <param name="pin">The pin number (GPIO number)</param>
/// <param name="pinNumberingScheme">The GPIO pin numbering scheme</param>
public Dht21(int pin, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
: base(pin, pinNumberingScheme)
{ }
internal override double GetHumidity(byte[] readBuff)
{
return (readBuff[0] << 8 | readBuff[1]) * 0.1;
}
public Temperature GetTemperature(byte[] readBuff)
internal override Temperature GetTemperature(byte[] readBuff)
{
var temp = (readBuff[2] & 0x7F) + readBuff[3] * 0.1;
// if MSB = 1 we have negative temperature
......
// Licensed to the .NET Foundation under one or more agreements.
// 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.Device.Gpio;
using Iot.Units;
namespace Iot.Device.DHTxx
{
/// <summary>
/// Temperature and Humidity Sensor DHT22
/// </summary>
public class Dht22 : DhtBase
{
/// <summary>
/// Create a DHT22 sensor
/// </summary>
/// <param name="pin">The pin number (GPIO number)</param>
/// <param name="pinNumberingScheme">The GPIO pin numbering scheme</param>
public Dht22(int pin, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
: base(pin, pinNumberingScheme)
{ }
internal override double GetHumidity(byte[] readBuff)
{
return (readBuff[0] << 8 | readBuff[1]) * 0.1;
}
internal override Temperature GetTemperature(byte[] readBuff)
{
var temp = (readBuff[2] & 0x7F) + readBuff[3] * 0.1;
// if MSB = 1 we have negative temperature
temp = ((readBuff[2] & 0x80) == 0 ? temp : -temp);
return Temperature.FromCelsius(temp);
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Iot.Units;
namespace Dhtxx.Devices
{
public interface IDhtDevice
{
double GetHumidity(byte[] readBuff);
Temperature GetTemperature(byte[] readBuff);
}
}
......@@ -8,7 +8,6 @@ using System.Device.Gpio;
using System.Device.I2c;
using System.Diagnostics;
using System.Threading;
using Dhtxx.Devices;
using Iot.Units;
namespace Iot.Device.DHTxx
......@@ -16,28 +15,24 @@ namespace Iot.Device.DHTxx
/// <summary>
/// Temperature and Humidity Sensor DHTxx
/// </summary>
public class DhtSensor : IDisposable
public abstract class DhtBase : IDisposable
{
/// <summary>
/// DHT12 Default I2C Address
/// </summary>
public const byte Dht12DefaultI2cAddress = 0x5C;
protected byte[] _readBuff = new byte[5];
private readonly CommunicationProtocol _protocol;
protected readonly int _pin;
protected readonly I2cDevice _i2cDevice;
protected readonly GpioController _controller;
// wait about 1 ms
private readonly uint _loopCount = 10000;
private readonly byte[] _readBuff = new byte[5];
private readonly CommunicationProtocol _protocol;
private readonly int _pin;
private readonly I2cDevice _i2cDevice;
private readonly GpioController _controller;
private readonly Stopwatch _stopwatch = new Stopwatch();
private int _lastMeasurement = 0;
private IDhtDevice _device;
/// <summary>
/// How last read went, <c>true</c> for success, <c>false</c> for failure
/// </summary>
public bool IsLastReadSuccessful { get; private set; }
public bool IsLastReadSuccessful { get; internal set; }
/// <summary>
/// Get the last read temperature
......@@ -45,12 +40,12 @@ namespace Iot.Device.DHTxx
/// <remarks>
/// If last read was not successfull, it returns double.NaN
/// </remarks>
public Temperature Temperature
public virtual Temperature Temperature
{
get
{
ReadData();
return IsLastReadSuccessful ? _device.GetTemperature(_readBuff) : Temperature.FromCelsius(double.NaN);
return IsLastReadSuccessful ? GetTemperature(_readBuff) : Temperature.FromCelsius(double.NaN);
}
}
......@@ -60,12 +55,12 @@ namespace Iot.Device.DHTxx
/// <remarks>
/// If last read was not successfull, it returns double.NaN
/// </remarks>
public double Humidity
public virtual double Humidity
{
get
{
ReadData();
return IsLastReadSuccessful ? _device.GetHumidity(_readBuff) : double.NaN;
return IsLastReadSuccessful ? GetHumidity(_readBuff) : double.NaN;
}
}
......@@ -73,14 +68,12 @@ namespace Iot.Device.DHTxx
/// Create a DHT sensor
/// </summary>
/// <param name="pin">The pin number (GPIO number)</param>
/// <param name="dhtType">The DHT Type, either Dht11 or Dht22</param>
/// <param name="pinNumberingScheme">The GPIO pin numbering scheme</param>
public DhtSensor(int pin, DhtType dhtType, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
public DhtBase(int pin, PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical)
{
_protocol = CommunicationProtocol.OneWire;
_controller = new GpioController(pinNumberingScheme);
_pin = pin;
SetDevice(dhtType);
_controller.OpenPin(_pin);
// delay 1s to make sure DHT stable
......@@ -91,44 +84,31 @@ namespace Iot.Device.DHTxx
/// Create a DHT sensor through I2C (Only DHT12)
/// </summary>
/// <param name="i2cDevice">The I2C device used for communication.</param>
public DhtSensor(I2cDevice i2cDevice)
public DhtBase(I2cDevice i2cDevice)
{
_protocol = CommunicationProtocol.I2C;
_i2cDevice = i2cDevice;
SetDevice(DhtType.Dht12);
}
/// <summary>
/// Start a reading
/// </summary>
/// <returns>
/// <c>true</c> if read is successfull, otherwise <c>false</c>.
/// </returns>
private void ReadData()
internal virtual void ReadData()
{
// The time of two measurements should be more than 1s.
if (Environment.TickCount - _lastMeasurement < 1000)
{
return;
}
if (_protocol == CommunicationProtocol.OneWire)
{
ReadThroughOneWire();
}
else
{
ReadThroughI2c();
}
}
/// <summary>
/// Read through One-Wire
/// </summary>
/// <returns>
/// <c>true</c> if read is successfull, otherwise <c>false</c>.
/// </returns>
private bool ReadThroughOneWire()
internal virtual void ReadThroughOneWire()
{
byte readVal = 0;
uint count;
......@@ -158,7 +138,7 @@ namespace Iot.Device.DHTxx
if (count-- == 0)
{
IsLastReadSuccessful = false;
return IsLastReadSuccessful;
return;
}
}
......@@ -169,7 +149,7 @@ namespace Iot.Device.DHTxx
if (count-- == 0)
{
IsLastReadSuccessful = false;
return IsLastReadSuccessful;
return;
}
}
......@@ -183,7 +163,7 @@ namespace Iot.Device.DHTxx
if (count-- == 0)
{
IsLastReadSuccessful = false;
return IsLastReadSuccessful;
return;
}
}
......@@ -196,7 +176,7 @@ namespace Iot.Device.DHTxx
if (count-- == 0)
{
IsLastReadSuccessful = false;
return IsLastReadSuccessful;
return;
}
}
_stopwatch.Stop();
......@@ -226,17 +206,12 @@ namespace Iot.Device.DHTxx
{
IsLastReadSuccessful = false;
}
return IsLastReadSuccessful;
}
/// <summary>
/// Read through I2C
/// </summary>
/// <returns>
/// <c>true</c> if read is successfull, otherwise <c>false</c>.
/// </returns>
private bool ReadThroughI2c()
internal virtual void ReadThroughI2c()
{
// DHT12 Humidity Register
_i2cDevice.WriteByte(0x00);
......@@ -253,27 +228,21 @@ namespace Iot.Device.DHTxx
{
IsLastReadSuccessful = false;
}
return IsLastReadSuccessful;
}
/// <summary>
/// Initialise the sensor instance with the corresponding device based on DhtType.
/// Converting data to humidity
/// </summary>
private void SetDevice(DhtType type)
{
switch (type)
{
case DhtType.Dht11:
_device = new Dht11Device();
break;
case DhtType.Dht12:
case DhtType.Dht21:
case DhtType.Dht22:
_device = new Dht22Device();
break;
}
}
/// <param name="readBuff">Data</param>
/// <returns>Humidity</returns>
internal abstract double GetHumidity(byte[] readBuff);
/// <summary>
/// Converting data to Temperature
/// </summary>
/// <param name="readBuff">Data</param>
/// <returns>Temperature</returns>
internal abstract Temperature GetTemperature(byte[] readBuff);
/// <summary>
/// Cleanup
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Iot.Device.DHTxx
{
/// <summary>
/// The type of DHT sensor used
/// </summary>
public enum DhtType
{
Dht11,
Dht12,
/// <summary>
/// AM2301
/// </summary>
Dht21,
/// <summary>
/// AM2302
/// </summary>
Dht22
}
}
......@@ -8,11 +8,12 @@
<ItemGroup>
<Compile Include="CommunicationProtocol.cs" />
<Compile Include="Devices\Dht11Device.cs" />
<Compile Include="Devices\Dht22Device.cs" />
<Compile Include="Devices\IDhtDevice.cs" />
<Compile Include="DhtType.cs" />
<Compile Include="DhtSensor.cs" />
<Compile Include="Devices\Dht10.cs" />
<Compile Include="Devices\Dht11.cs" />
<Compile Include="Devices\Dht12.cs" />
<Compile Include="Devices\Dht21.cs" />
<Compile Include="Devices\Dht22.cs" />
<Compile Include="DhtBase.cs" />
<Compile Include="..\Common\System\Device\DelayHelper.cs" />
</ItemGroup>
......
# DHTxx - Digital-Output Relative Humidity & Temperature Sensor Module
The DHT temperature and humidity sensors are very popular. This projects support DHT11, DHT12, DHT21(AM2301), DHT22(AM2302).
The DHT temperature and humidity sensors are very popular. This projects support DHT10, DHT11, DHT12, DHT21(AM2301), DHT22(AM2302).
## Comparison
| | DHT10 | DHT11 | DHT12 | DHT21 | DHT22 |
| :------: | :------: | :------: | :------: | :------: | :------: |
| Image | <img src="imgs/dht10.jpg" height="60"/> | <img src="imgs/dht11.jpg" height="60"/> | <img src="imgs/dht12.jpg" height="60"/> | <img src="imgs/dht21.jpg" height="60"/> | <img src="imgs/dht22.jpg" height="60"/> |
| Temperature Range | -40 ~ 80 ℃ | -20 ~ 60 ℃ | -20 ~ 60 ℃ | -40 ~ 80 ℃ | -40 ~ 80 ℃ |
| Humidity Range | 0 ~ 99.9 % | 5 ~ 95 % | 20 ~ 95 % | 0 ~ 99.9 % | 0 ~ 99.9 % |
| Temperature Accuracy | ±0.5 ℃ | ±2 ℃ | ±0.5 ℃ | ±0.5 ℃ | ±0.5 ℃ |
| Humidity Accuracy | ±3 % | ±5 % | ±4 % | ±3 % | ±2 % |
| Protocol | I2C | 1-Wire | I2C, 1-Wire | 1-Wire | 1-Wire |
## Usage
### 1-Wire Protocol
```csharp
// GPIO Pin, DHT Type
using (DhtSensor dht = new DhtSensor(26, DhtType.DHT22))
// GPIO Pin
using (Dht11 dht = new Dht11(26))
{
Temperature temperature = dht.Temperature;
double humidity = dht.Humidity;
......@@ -23,7 +34,7 @@ Only DHT12 can use I2C protocol.
I2cConnectionSettings settings = new I2cConnectionSettings(1, DhtSensor.DefaultI2cAddressDht12);
I2cDevice device = I2cDevice.Create(settings);
using (DhtSensor dht = new DhtSensor(device))
using (Dht12 dht = new Dht12(device))
{
Temperature temperature = dht.Temperature;
double humidity = dht.Humidity;
......@@ -32,6 +43,7 @@ using (DhtSensor dht = new DhtSensor(device))
## References
* **DHT10** [datasheet (Currently only Chinese)](http://www.aosong.com/userfiles/files/media/DHT10%E8%A7%84%E6%A0%BC%E4%B9%A6.pdf)
* **DHT11** [datasheet](https://cdn.datasheetspdf.com/pdf-down/D/H/T/DHT11-Aosong.pdf)
* **DHT12** [datasheet](https://cdn.datasheetspdf.com/pdf-down/D/H/T/DHT12-Aosong.pdf)
* **DHT21** [datasheet](https://cdn.datasheetspdf.com/pdf-down/A/M/2/AM2301-Aosong.pdf)
......
......@@ -3,22 +3,21 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Device.I2c;
using System.Threading;
using Iot.Device.DHTxx;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello DHT!");
// Init DHT12 through I2C
//I2cConnectionSettings settings = new I2cConnectionSettings(1, DhtSensor.Dht12DefaultI2cAddress);
//I2cDevice device = I2cDevice.Create(settings);
//DhtSensor dht = new DhtSensor(device);
// Init DHT10 through I2C
I2cConnectionSettings settings = new I2cConnectionSettings(1, Dht10.DefaultI2cAddress);
I2cDevice device = I2cDevice.Create(settings);
using (DhtSensor dht = new DhtSensor(4, DhtType.Dht11))
using (Dht10 dht = new Dht10(device))
{
while (true)
{
......
......@@ -2,7 +2,7 @@
## Hardware Required
* DHT11/DHT12/DHT21/DHT22
* DHT10/DHT11/DHT12/DHT21/DHT22
* Male/Female Jumper Wires
## Circuit
......@@ -27,7 +27,7 @@ Some sensors are already sold with the 10K resistor. Connect the GPIO26 to the *
## Code
```csharp
using (DhtSensor dht = new DhtSensor(26, DhtType.DHT22))
using (Dht11 dht = new Dht11(26))
{
while (true)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册