-
-
Notifications
You must be signed in to change notification settings - Fork 109
/
Copy pathSht4X.cs
136 lines (122 loc) · 4.72 KB
/
Sht4X.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Device.I2c;
using System.Threading;
using UnitsNet;
namespace Iot.Device.Sht4x
{
/// <summary>
/// Humidity and Temperature Sensor Sht4X.
/// </summary>
public class Sht4X : IDisposable
{
/// <summary>
/// Default I2C address of the Sht4x sensor.
/// </summary>
public const byte I2cDefaultAddress = 0x44;
/// <summary>
/// Represents an I2C device used for communication with the Sht4X sensor.
/// </summary>
private I2cDevice _i2CDevice;
/// <summary>
/// Initializes a new instance of the <see cref="Sht4X" /> class.
/// </summary>
/// <param name="i2CDevice">The I2C device used for communication.</param>
public Sht4X(I2cDevice i2CDevice)
{
_i2CDevice = i2CDevice ?? throw new ArgumentNullException();
}
/// <inheritdoc/>
public void Dispose()
{
_i2CDevice?.Dispose();
_i2CDevice = null;
}
/// <summary>
/// Reads the temperature and humidity data from the sensor.
/// </summary>
/// <param name="precision">The measurement mode to use.</param>
/// <returns>The sensor data.</returns>
/// <exception cref="Exception">Thrown if there is an error in the I2C communication.</exception>
/// <exception cref="InvalidCrcException">Thrown if invalid data is returned from device.</exception>
public Sht4XSensorData ReadData(MeasurementMode precision)
{
var dataToWrite = (byte)precision;
var delay = GetDelay(precision);
var result = _i2CDevice.WriteByte(dataToWrite);
if (result.Status != I2cTransferStatus.FullTransfer)
{
throw new Exception();
}
Thread.Sleep(delay);
var readBuffer = new byte[6];
_i2CDevice.Read(readBuffer);
if (result.Status != I2cTransferStatus.FullTransfer)
{
throw new Exception();
}
// Humidity and temperature data will always be transmitted the following way: First temperature signal (2 * 8-bit data + 8-
// bit CRC), second humidity signal(2 * 8 - bit data + 8 - bit CRC). The serial number is transmitted as two 16 - bit words.
ValidateCrc8(new[] { readBuffer[0], readBuffer[1] }, readBuffer[2]);
ValidateCrc8(new[] { readBuffer[3], readBuffer[4] }, readBuffer[5]);
var temperatureTicks = (readBuffer[0] * 256) + readBuffer[1];
var humidityTicks = (readBuffer[3] * 256) + readBuffer[4];
var temperature = -45 + (175 * temperatureTicks / 65535.0f);
var humidity = -6 + (125 * humidityTicks / 65535.0f);
return new Sht4XSensorData(
Temperature.FromDegreesCelsius(temperature),
RelativeHumidity.FromPercent(humidity));
}
private static void ValidateCrc8(byte[] buffer, byte dataCrc)
{
byte crc = 0xFF;
foreach (byte b in buffer)
{
crc ^= b;
for (int i = 0; i < 8; i++)
{
if ((crc & 0x80) != 0)
{
crc = (byte)((crc << 1) ^ 0x31);
}
else
{
crc <<= 1;
}
}
}
var resultCrc = (byte)(crc & 0xFF);
if (dataCrc != resultCrc)
{
throw new InvalidCrcException();
}
}
private static ushort GetDelay(MeasurementMode precision)
{
switch (precision)
{
case MeasurementMode.NoHeaterHighPrecision:
return 10;
case MeasurementMode.NoHeaterMediumPrecision:
return 5;
case MeasurementMode.NoHeaterLowPrecision:
return 2;
case MeasurementMode.HighHeat1S1:
return 1100;
case MeasurementMode.HighHeat100Ms:
return 100;
case MeasurementMode.MediumHeat1S1:
return 1100;
case MeasurementMode.MediumHeat100Ms:
return 100;
case MeasurementMode.LowHeat1S1:
return 1100;
case MeasurementMode.LowHeat100Ms:
return 100;
default:
throw new ArgumentException();
}
}
}
}