Skip to content
This repository was archived by the owner on Apr 10, 2020. It is now read-only.

Commit e90ec57

Browse files
authored
Merge pull request #1 from JTrotta/HTU21DF-Driver
HTU21DF driver
2 parents 2aa9e70 + 6eb0a0f commit e90ec57

File tree

12 files changed

+392
-59
lines changed

12 files changed

+392
-59
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ TestResults
1414
**.suo
1515
**.sdf
1616
*.sln.docstates
17+
.vs/*
1718

1819
# resharper
1920
/_[Rr]e[Ss]harper.*

Raspberry.IO.Components/Sensors/Temperature/Dht/InvalidChecksumException.cs renamed to Raspberry.IO.Components/InvalidChecksumException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Globalization;
33

4-
namespace Raspberry.IO.Components.Sensors.Temperature.Dht
4+
namespace Raspberry.IO.Components
55
{
66
public class InvalidChecksumException : Exception
77
{

Raspberry.IO.Components/Raspberry.IO.Components.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,15 @@
144144
<Compile Include="Properties\AssemblyInfo.cs" />
145145
<Compile Include="Sensors\Distance\HcSr04\HcSr04Connection.cs" />
146146
<Compile Include="Sensors\Distance\HcSr04\Units.cs" />
147+
<Compile Include="Sensors\Humidity\Htu21df\Htu21dfConnection.cs" />
147148
<Compile Include="Sensors\Pressure\Bmp085\Bmp085Data.cs" />
148149
<Compile Include="Sensors\Pressure\Bmp085\Bmp085I2cConnectionExtensionMethods.cs" />
149150
<Compile Include="Sensors\Pressure\Bmp085\Bmp085Precision.cs" />
150151
<Compile Include="Sensors\Temperature\Dht\Dht11Connection.cs" />
151152
<Compile Include="Sensors\Temperature\Dht\Dht22Connection.cs" />
152153
<Compile Include="Sensors\Temperature\Dht\DhtConnection.cs" />
153154
<Compile Include="Sensors\Temperature\Dht\DhtData.cs" />
154-
<Compile Include="Sensors\Temperature\Dht\InvalidChecksumException.cs" />
155+
<Compile Include="InvalidChecksumException.cs" />
155156
<Compile Include="Sensors\Temperature\Ds18b20\Ds18b20Connection.cs" />
156157
<Compile Include="Sensors\VariableResistiveDividerConnection.cs" />
157158
<Compile Include="Sensors\Temperature\Tmp36\Tmp36Connection.cs" />
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System;
2+
using System.Threading;
3+
using Raspberry.IO.Components.Sensors.Temperature.Dht;
4+
using Raspberry.IO.InterIntegratedCircuit;
5+
6+
namespace Raspberry.IO.Components.Sensors.Humidity.Htu21df
7+
{
8+
/// <summary>
9+
/// Connection to the HTU21D-F Adafruit humidity and temperature breakout board.
10+
/// </summary>
11+
/// <remarks>See <see cref="https://www.adafruit.com/datasheets/1899_HTU21D.pdf"/> for more information.</remarks>///
12+
public class Htu21dfConnection
13+
{
14+
#region Helpers
15+
16+
public enum I2cDefs : byte
17+
{
18+
HTU21DF_I2CADDR = 0x40,
19+
HTU21DF_READTEMP = 0xE3,
20+
HTU21DF_READHUM = 0xE5,
21+
HTU21DF_READTEMP_NOHOLDMASTER = 0xF3,
22+
HTU21DF_READHUM_NOHOLDMASTER = 0xF5,
23+
HTU21DF_WRITEREG = 0xE6,
24+
HTU21DF_READREG = 0xE7,
25+
HTU21DF_RESET = 0xFE,
26+
}
27+
28+
public enum I2cReadMode
29+
{
30+
/// <summary>
31+
/// Default. In this mode, the SCK line is blocked during the measurement process. When measurement is complete
32+
/// the sensor indicates by releasing SCK and the read can continue.
33+
/// </summary>
34+
HoldMaster,
35+
36+
/// <summary>
37+
/// The sensor does not hold SCK so other I2C comms can take place on the bus. The MCU (R-Pi) has to then
38+
/// poll for the data. NOT CURRENTLY SUPPORTED.
39+
/// </summary>
40+
NoHoldMaster,
41+
}
42+
43+
#endregion
44+
45+
#region Fields
46+
47+
private readonly I2cDeviceConnection connection;
48+
49+
#endregion
50+
51+
#region Instance Management
52+
53+
/// <summary>
54+
/// Initializes a new instance of the <see cref="Htu21dfConnection"/> class.
55+
/// </summary>
56+
/// <param name="connection">The connection.</param>
57+
public Htu21dfConnection( I2cDeviceConnection connection )
58+
{
59+
this.connection = connection;
60+
ReadMode = I2cReadMode.HoldMaster;
61+
}
62+
63+
#endregion
64+
65+
#region Methods
66+
67+
public I2cReadMode ReadMode { get; set; }
68+
69+
/// <summary>
70+
/// Init's the sensor and checks its status is OK.
71+
/// </summary>
72+
public void Begin()
73+
{
74+
Reset();
75+
76+
connection.WriteByte( (byte) I2cDefs.HTU21DF_READREG );
77+
var status = connection.ReadByte();
78+
if ( status != 0x02 )
79+
{
80+
throw new Exception( $"Status following reset should be 0x02. Have {status}" );
81+
}
82+
}
83+
84+
/// <summary>
85+
/// Resets the sensor by power cycling. Takes about 15ms.
86+
/// </summary>
87+
private void Reset()
88+
{
89+
connection.WriteByte((byte)I2cDefs.HTU21DF_RESET);
90+
Thread.Sleep(15);
91+
}
92+
93+
/// <summary>
94+
/// Reads the temperature value from the sensor.
95+
/// </summary>
96+
/// <returns>Temperature in degrees Centigrade.</returns>
97+
public double ReadTemperature()
98+
{
99+
if ( ReadMode == I2cReadMode.NoHoldMaster )
100+
{
101+
throw new NotSupportedException( "No-Hold-Master read mode not supported." );
102+
}
103+
104+
connection.WriteByte( (byte) I2cDefs.HTU21DF_READTEMP );
105+
106+
// Add delay between request and actual read
107+
Thread.Sleep( 50 );
108+
109+
// Read 3 bytes; 2 bytes temp data and one byte checksum.
110+
var readBytes = connection.Read( 3 );
111+
CheckCrc( readBytes );
112+
113+
// Get data value from bytes 0 and 1.
114+
var tVal = ( readBytes[0] << 8 ) + readBytes[1];
115+
116+
// Compute temp using formula from datasheet.
117+
return ( ( tVal * 175.72 ) / 65536 ) - 46.85;
118+
}
119+
120+
/// <summary>
121+
/// Reads the humidity value from the sensor.
122+
/// </summary>
123+
/// <returns>The relative humidity value as a percentage.</returns>
124+
public double ReadHumidity()
125+
{
126+
if (ReadMode == I2cReadMode.NoHoldMaster)
127+
{
128+
throw new NotSupportedException("No-Hold-Master read mode not supported.");
129+
}
130+
131+
connection.WriteByte((byte)I2cDefs.HTU21DF_READHUM);
132+
133+
// Add delay between request and actual read
134+
Thread.Sleep( 50 );
135+
136+
// Read 3 bytes; 2 bytes temp data and one byte checksum.
137+
var readBytes = connection.Read( 3 );
138+
CheckCrc( readBytes );
139+
140+
// Get data value from bytes 0 and 1.
141+
var hVal = ( readBytes[0] << 8 ) + readBytes[1];
142+
143+
// Compute temp using formula from datasheet.
144+
return ( ( (double)hVal * 125 ) / 65536 ) - 6;
145+
}
146+
147+
/// <summary>
148+
/// Calculate the CRC checksum. The result should be zero.
149+
/// Thanks to the IoT-Playground - https://github.com/iot-playground.
150+
/// </summary>
151+
public static void CheckCrc(byte[] readData)
152+
{
153+
// Test cases from datasheet:
154+
// sensor value = 0xDC, checkvalue is 0x79. readData = 0x00DC79.
155+
// message = 0x683A, checkvalue is 0x7C. readData = 0x683A7C
156+
// message = 0x4E85, checkvalue is 0x6B. readData = 0x45856B
157+
158+
// Create a 32-bit value with bytes of {0, val-msb, val-lsb, checksum}
159+
var remainder = (uint) ( ( readData[0] << 16 ) + ( readData[1] << 8 ) + readData[2] );
160+
161+
// This is the x^8 + x^5 + x^4 + 1 polynomial (100110001), but shifted up to start at the left-hand
162+
// side of the 24-bit value.
163+
uint divisor = 0x988000;
164+
165+
for ( var i = 0; i < 16; i++ )
166+
{
167+
if ( (remainder & (1<<(23-i))) != 0 )
168+
{
169+
remainder ^= divisor;
170+
}
171+
172+
divisor >>= 1;
173+
}
174+
175+
if ( remainder != 0 )
176+
{
177+
throw new InvalidChecksumException( 0x00, remainder );
178+
}
179+
}
180+
181+
#endregion
182+
}
183+
}

Raspberry.IO.InterIntegratedCircuit/I2cDriver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,10 @@ private static uint GetProcessorBscAddress(Processor processor)
491491
switch (processor)
492492
{
493493
case Processor.Bcm2708:
494+
case Processor.BCM2835: // <- added this one JJ FIX per RB3
494495
return Interop.BCM2835_BSC1_BASE;
495496

496497
case Processor.Bcm2709:
497-
case Processor.BCM2835: // <- added this one JJ FIX per RB3
498498
return Interop.BCM2836_BSC1_BASE;
499499

500500
default:
@@ -507,10 +507,10 @@ private static uint GetProcessorGpioAddress(Processor processor)
507507
switch (processor)
508508
{
509509
case Processor.Bcm2708:
510+
case Processor.BCM2835: // <- added this one JJ FIX per RB3
510511
return Interop.BCM2835_GPIO_BASE;
511512

512513
case Processor.Bcm2709:
513-
case Processor.BCM2835: // <- added this one JJ FIX per RB3
514514
return Interop.BCM2836_GPIO_BASE;
515515

516516
default:

RaspberrySharp.IO.sln

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 2012
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27004.2006
5+
MinimumVisualStudioVersion = 10.0.40219.1
46
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Raspberry.IO.GeneralPurpose", "Raspberry.IO.GeneralPurpose\Raspberry.IO.GeneralPurpose.csproj", "{281C71ED-C36D-408E-8BAA-75C381DC17E7}"
57
EndProject
68
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{93E87796-2109-444A-8852-7174C93E6F45}"
@@ -66,6 +68,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Gpio.Ds1307", "Tests\T
6668
EndProject
6769
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.I2C.LTC2943", "Tests\Test.I2C.LTC2943\Test.I2C.LTC2943.csproj", "{6A8D4696-3291-492C-B301-AB0AFECC9440}"
6870
EndProject
71+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.Gpio.Htu21df", "Tests\Test.Gpio.Htu21df\Test.Gpio.Htu21df.csproj", "{04E66E09-8128-4122-BBF3-17220BC75ADA}"
72+
EndProject
6973
Global
7074
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7175
Debug|Any CPU = Debug|Any CPU
@@ -176,13 +180,16 @@ Global
176180
{6A8D4696-3291-492C-B301-AB0AFECC9440}.Debug|Any CPU.Build.0 = Debug|Any CPU
177181
{6A8D4696-3291-492C-B301-AB0AFECC9440}.Release|Any CPU.ActiveCfg = Release|Any CPU
178182
{6A8D4696-3291-492C-B301-AB0AFECC9440}.Release|Any CPU.Build.0 = Release|Any CPU
183+
{04E66E09-8128-4122-BBF3-17220BC75ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
184+
{04E66E09-8128-4122-BBF3-17220BC75ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU
185+
{04E66E09-8128-4122-BBF3-17220BC75ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU
186+
{04E66E09-8128-4122-BBF3-17220BC75ADA}.Release|Any CPU.Build.0 = Release|Any CPU
179187
EndGlobalSection
180188
GlobalSection(SolutionProperties) = preSolution
181189
HideSolutionNode = FALSE
182190
EndGlobalSection
183191
GlobalSection(NestedProjects) = preSolution
184192
{15ECD485-B3FD-4B6F-8491-7489DFFC89BC} = {93E87796-2109-444A-8852-7174C93E6F45}
185-
{C39D0CC3-C0F2-4B58-8779-2CCB5B52534C} = {93E87796-2109-444A-8852-7174C93E6F45}
186193
{B28253A7-BB93-40F7-B41C-B4AE369174ED} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
187194
{54075457-7C1D-4C8F-BE7D-CFCA34F11228} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
188195
{6B5D38D3-7642-4DF9-A9AA-3AF7D00890BC} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
@@ -197,12 +204,17 @@ Global
197204
{D4B87926-598E-4EAB-BA75-CD9FB253D450} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
198205
{CAD5F2DD-AB2D-4145-9850-8101343E2AF5} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
199206
{E401FE2A-7F73-41E7-9347-B51FEDAE71B9} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
200-
{E9412139-F9EA-4E39-AB7C-CE775ED06C82} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
201-
{6A8D4696-3291-492C-B301-AB0AFECC9440} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
207+
{C39D0CC3-C0F2-4B58-8779-2CCB5B52534C} = {93E87796-2109-444A-8852-7174C93E6F45}
202208
{17A2A965-36FA-4CDB-B2D6-AC69C9E9857F} = {C39D0CC3-C0F2-4B58-8779-2CCB5B52534C}
203209
{0BB6C3CE-422E-49F2-9165-DEC06AFE1B1A} = {C39D0CC3-C0F2-4B58-8779-2CCB5B52534C}
204210
{99EB3D1A-F0B7-454E-BB50-9B2F5349BC5B} = {C39D0CC3-C0F2-4B58-8779-2CCB5B52534C}
205211
{CAF876A0-0FCB-44F7-96F1-53704CB6015F} = {C39D0CC3-C0F2-4B58-8779-2CCB5B52534C}
212+
{E9412139-F9EA-4E39-AB7C-CE775ED06C82} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
213+
{6A8D4696-3291-492C-B301-AB0AFECC9440} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
214+
{04E66E09-8128-4122-BBF3-17220BC75ADA} = {15ECD485-B3FD-4B6F-8491-7489DFFC89BC}
215+
EndGlobalSection
216+
GlobalSection(ExtensibilityGlobals) = postSolution
217+
SolutionGuid = {7B21C3A9-4153-4372-8A05-012F51A2E4E9}
206218
EndGlobalSection
207219
GlobalSection(MonoDevelopProperties) = preSolution
208220
Policies = $0

Tests/Test.Gpio.Htu21df/App.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
5+
</startup>
6+
</configuration>

Tests/Test.Gpio.Htu21df/Program.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Threading;
3+
using Raspberry.IO.Components.Sensors.Humidity.Htu21df;
4+
using Raspberry.IO.GeneralPurpose;
5+
using Raspberry.IO.InterIntegratedCircuit;
6+
7+
8+
namespace Test.Gpio.Htu21df
9+
{
10+
class Program
11+
{
12+
static void Main()
13+
{
14+
const ConnectorPin sdaPin = ConnectorPin.P1Pin03;
15+
const ConnectorPin sclPin = ConnectorPin.P1Pin05;
16+
17+
Console.WriteLine( "HTU21DF Sample: Read humidity and temperature" );
18+
Console.WriteLine();
19+
Console.WriteLine( "\tSDA: {0}", sdaPin );
20+
Console.WriteLine( "\tSCL: {0}", sclPin );
21+
Console.WriteLine();
22+
23+
using ( var driver = new I2cDriver( sdaPin.ToProcessor(), sclPin.ToProcessor() ) )
24+
{
25+
var deviceConnection = new Htu21dfConnection( driver.Connect( 0x40 ) );
26+
deviceConnection.Begin();
27+
28+
while ( !Console.KeyAvailable )
29+
{
30+
var temp = deviceConnection.ReadTemperature();
31+
var humidity = deviceConnection.ReadHumidity();
32+
Console.WriteLine( $"Temp is: {temp:F1}C. RH is {humidity:F1}%" );
33+
Thread.Sleep( 2000 );
34+
}
35+
}
36+
}
37+
}
38+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("Test.Gpio.Htu21df")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("Test.Gpio.Htu21df")]
13+
[assembly: AssemblyCopyright("Copyright © 2017")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("04e66e09-8128-4122-bbf3-17220bc75ada")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

0 commit comments

Comments
 (0)