Skip to content

Commit ff9624e

Browse files
committed
Try adding support for InOut pins and DHT sensor
1 parent a650afc commit ff9624e

12 files changed

+238
-16
lines changed

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

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
<Compile Include="Properties\AssemblyInfo.cs" />
102102
<Compile Include="Sensors\Distance\HcSr04\HcSr04Connection.cs" />
103103
<Compile Include="Sensors\Distance\HcSr04\Units.cs" />
104+
<Compile Include="Sensors\Temperature\Dht\DhtConnection.cs" />
105+
<Compile Include="Sensors\Temperature\Dht\DhtData.cs" />
104106
<Compile Include="Sensors\VariableResistiveDividerConnection.cs" />
105107
<Compile Include="Sensors\Temperature\Tmp36\Tmp36Connection.cs" />
106108
<Compile Include="Sensors\ResistiveDivider.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using Raspberry.Timers;
3+
4+
namespace Raspberry.IO.Components.Sensors.Temperature.Dht
5+
{
6+
/// <summary>
7+
/// Represents a connection to a DHT-11 or DHT-22 humidity / temperature sensor.
8+
/// </summary>
9+
/// <remarks>This is preliminary work and is not working.</remarks>
10+
public class DhtConnection : IDisposable
11+
{
12+
private readonly IInputOutputBinaryPin pin;
13+
14+
public DhtConnection(IInputOutputBinaryPin pin)
15+
{
16+
this.pin = pin;
17+
18+
pin.Write(true);
19+
Timer.Sleep(100);
20+
}
21+
22+
public void Dispose()
23+
{
24+
Close();
25+
}
26+
27+
public DhtData GetData()
28+
{
29+
// pull pin down for 18ms
30+
pin.Write(false);
31+
Timer.Sleep(18m);
32+
33+
// pull pin up for 40µs
34+
pin.Write(true);
35+
Timer.Sleep(40m / 1000m);
36+
37+
pin.Wait(true, 40m / 1000m);
38+
39+
// Wait for pin to be down (at most 80µs)
40+
pin.Wait(false, 80m / 1000m);
41+
42+
// Wait for pin to be up (at most 80µs)
43+
pin.Wait(true, 80m / 1000m);
44+
45+
var data = new byte[]{0,0,0,0,0};
46+
for (var i = 0; i < 5; i++)
47+
for (var j = 0; j < 8; j++)
48+
{
49+
pin.Wait(false, 50m / 1000m);
50+
51+
var start = DateTime.UtcNow;
52+
pin.Wait(true, 100m / 1000m);
53+
54+
// bit "0" has 26-28us high-voltage length, bit "1" has 70us high-voltage length
55+
var value = (DateTime.UtcNow - start).TotalMilliseconds > 40.0/1000 ? 1 : 0;
56+
57+
data[i] = (byte) (data[i] << 1 + value);
58+
}
59+
60+
Console.WriteLine(
61+
"{0:X2} {1:X2} {2:X2} {3:X2} {4:X2}",
62+
data[0],
63+
data[1],
64+
data[2],
65+
data[3],
66+
data[4]);
67+
68+
var checkSum = data[0] + data[1] + data[2] + data[3];
69+
if ((checkSum & 0xff) != data[4])
70+
throw new InvalidOperationException("Checksum is not valid");
71+
72+
pin.Write(true);
73+
74+
return new DhtData
75+
{
76+
Humidity = (data[0] << 8 + data[1])/10.0m,
77+
Temperature = ((data[2] & 0x80) == 0 ? 1 : -1)*((data[2] & 0x7F) << 8 + data[3])/10.0m
78+
};
79+
}
80+
81+
public void Close()
82+
{
83+
pin.Dispose();
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Raspberry.IO.Components.Sensors.Temperature.Dht
2+
{
3+
public class DhtData
4+
{
5+
public decimal Temperature;
6+
public decimal Humidity;
7+
}
8+
}

Raspberry.IO.GeneralPurpose/GpioBinaryPinExtensionMethods.cs

+28
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,34 @@ public static GpioInputBinaryPin In(this IGpioConnectionDriver driver, Processor
5757
return new GpioInputBinaryPin(driver, pin, resistor);
5858
}
5959

60+
/// <summary>
61+
/// Gets a bidirectional pin on the current driver.
62+
/// </summary>
63+
/// <param name="driver">The driver.</param>
64+
/// <param name="pin">The pin.</param>
65+
/// <param name="resistor">The resistor.</param>
66+
/// <returns>
67+
/// The GPIO input binary pin.
68+
/// </returns>
69+
public static GpioInputOutputBinaryPin InOut(this IGpioConnectionDriver driver, ConnectorPin pin, PinResistor resistor = PinResistor.None)
70+
{
71+
return driver.InOut(pin.ToProcessor(), resistor);
72+
}
73+
74+
/// <summary>
75+
/// Gets a bidirectional pin on the current driver.
76+
/// </summary>
77+
/// <param name="driver">The driver.</param>
78+
/// <param name="pin">The pin.</param>
79+
/// <param name="resistor">The resistor.</param>
80+
/// <returns>
81+
/// The GPIO input binary pin.
82+
/// </returns>
83+
public static GpioInputOutputBinaryPin InOut(this IGpioConnectionDriver driver, ProcessorPin pin, PinResistor resistor = PinResistor.None)
84+
{
85+
return new GpioInputOutputBinaryPin(driver, pin, resistor);
86+
}
87+
6088
#endregion
6189
}
6290
}

Raspberry.IO.GeneralPurpose/GpioConnectionDriver.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Runtime.InteropServices;
88
using Raspberry.IO.Interop;
9+
using Raspberry.Timers;
910

1011
#endregion
1112

@@ -135,9 +136,9 @@ public void SetPinResistor(ProcessorPin pin, PinResistor resistor)
135136
}
136137

137138
WriteResistor(pud);
138-
Timers.Timer.Sleep(1);
139+
HighResolutionTimer.Sleep(0.005m);
139140
SetPinResistorClock(pin, true);
140-
Timers.Timer.Sleep(1);
141+
HighResolutionTimer.Sleep(0.005m);
141142
WriteResistor(Interop.BCM2835_GPIO_PUD_OFF);
142143
SetPinResistorClock(pin, false);
143144
}
@@ -253,7 +254,7 @@ public ProcessorPins Read(ProcessorPins pins)
253254

254255
private static int GetActualTimeout(decimal timeout)
255256
{
256-
if (timeout > 1)
257+
if (timeout > 0)
257258
return (int)timeout;
258259

259260
if (timeout > 0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
namespace Raspberry.IO.GeneralPurpose
2+
{
3+
/// <summary>
4+
/// Represents a bidirectional pin on GPIO interface.
5+
/// </summary>
6+
public class GpioInputOutputBinaryPin : IInputOutputBinaryPin
7+
{
8+
private readonly IGpioConnectionDriver driver;
9+
private readonly ProcessorPin pin;
10+
private readonly PinResistor resistor;
11+
private PinDirection? direction;
12+
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="GpioInputOutputBinaryPin"/> class.
15+
/// </summary>
16+
/// <param name="driver">The driver.</param>
17+
/// <param name="pin">The pin.</param>
18+
/// <param name="resistor">The resistor.</param>
19+
public GpioInputOutputBinaryPin(IGpioConnectionDriver driver, ProcessorPin pin, PinResistor resistor = PinResistor.None)
20+
{
21+
this.driver = driver;
22+
this.pin = pin;
23+
this.resistor = resistor;
24+
}
25+
26+
/// <summary>
27+
/// Releases unmanaged and - optionally - managed resources.
28+
/// </summary>
29+
public void Dispose()
30+
{
31+
if (direction.HasValue)
32+
driver.Release(pin);
33+
}
34+
35+
/// <summary>
36+
/// Reads this instance.
37+
/// </summary>
38+
/// <returns>The value.</returns>
39+
public bool Read()
40+
{
41+
SetDirection(PinDirection.Input);
42+
return driver.Read(pin);
43+
}
44+
45+
/// <summary>
46+
/// Waits the specified wait for up.
47+
/// </summary>
48+
/// <param name="waitForUp">if set to <c>true</c> [wait for up].</param>
49+
/// <param name="timeout">The timeout.</param>
50+
public void Wait(bool waitForUp = true, decimal timeout = 0)
51+
{
52+
SetDirection(PinDirection.Input);
53+
driver.Wait(pin, waitForUp, timeout);
54+
}
55+
56+
/// <summary>
57+
/// Writes the specified state.
58+
/// </summary>
59+
/// <param name="state">the state.</param>
60+
public void Write(bool state)
61+
{
62+
SetDirection(PinDirection.Output);
63+
driver.Write(pin, state);
64+
}
65+
66+
private void SetDirection(PinDirection newDirection)
67+
{
68+
if (direction == newDirection)
69+
return;
70+
71+
if (direction.HasValue)
72+
driver.Release(pin);
73+
74+
driver.Allocate(pin, newDirection);
75+
if (newDirection == PinDirection.Input && resistor != PinResistor.None)
76+
driver.SetPinResistor(pin, resistor);
77+
78+
direction = newDirection;
79+
}
80+
81+
}
82+
}

Raspberry.IO.GeneralPurpose/GpioOutputBinaryPin.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace Raspberry.IO.GeneralPurpose
22
{
33
/// <summary>
4-
/// Represents an output pin on GPIO interface
4+
/// Represents an output pin on GPIO interface.
55
/// </summary>
66
public class GpioOutputBinaryPin : IOutputBinaryPin
77
{

Raspberry.IO.GeneralPurpose/MemoryGpioConnectionDriver.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Globalization;
55
using System.Runtime.InteropServices;
66
using Raspberry.IO.Interop;
7+
using Raspberry.Timers;
78

89
#endregion
910

@@ -108,9 +109,9 @@ public void SetPinResistor(ProcessorPin pin, PinResistor resistor)
108109
}
109110

110111
WriteResistor(pud);
111-
Timers.Timer.Sleep(1);
112+
HighResolutionTimer.Sleep(0.005m);
112113
SetPinResistorClock(pin, true);
113-
Timers.Timer.Sleep(1);
114+
HighResolutionTimer.Sleep(0.005m);
114115
WriteResistor(Interop.BCM2835_GPIO_PUD_OFF);
115116
SetPinResistorClock(pin, false);
116117
}

Raspberry.IO.GeneralPurpose/Raspberry.IO.GeneralPurpose.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
<Compile Include="GpioConnectionDriverExtensionMethods.cs" />
6363
<Compile Include="GpioConnectionSettings.cs" />
6464
<Compile Include="GpioInputBinaryPin.cs" />
65+
<Compile Include="GpioInputOutputBinaryPin.cs" />
6566
<Compile Include="GpioOutputBinaryPin.cs" />
6667
<Compile Include="Interop.cs" />
6768
<Compile Include="PinDetectedEdges.cs" />

Raspberry.IO/IInputOutputBinaryPin.cs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Raspberry.IO
2+
{
3+
/// <summary>
4+
/// Provides an interface for bidirectional binary pins.
5+
/// </summary>
6+
public interface IInputOutputBinaryPin : IInputBinaryPin, IOutputBinaryPin {}
7+
}

Raspberry.IO/Raspberry.IO.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<Compile Include="ByteExtensionMethods.cs" />
4646
<Compile Include="IInputAnalogPin.cs" />
4747
<Compile Include="IInputBinaryPin.cs" />
48+
<Compile Include="IInputOutputBinaryPin.cs" />
4849
<Compile Include="IOutputAnalogPin.cs" />
4950
<Compile Include="IOutputBinaryPin.cs" />
5051
<Compile Include="Properties\AssemblyInfo.cs" />

Tests/Test.Gpio.MCP3008/Program.cs

+15-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Threading;
55
using Raspberry.IO.Components.Converters.Mcp3008;
66
using Raspberry.IO.Components.Sensors;
7+
using Raspberry.IO.Components.Sensors.Temperature.Dht;
78
using Raspberry.IO.Components.Sensors.Temperature.Tmp36;
89
using Raspberry.IO.GeneralPurpose;
910

@@ -34,16 +35,19 @@ static void Main()
3435

3536
const decimal voltage = 3.3m;
3637

37-
var driver = GpioConnectionSettings.DefaultDriver;
38+
var driver = new MemoryGpioConnectionDriver(); //GpioConnectionSettings.DefaultDriver;
3839

39-
using (var clockPin = driver.Out(adcClock))
40-
using (var csPin = driver.Out(adcCs))
41-
using (var misoPin = driver.In(adcMiso))
42-
using (var mosiPin = driver.Out(adcMosi))
43-
using (var adcConnection = new Mcp3008SpiConnection(clockPin, csPin, misoPin, mosiPin))
44-
45-
using (var temperatureConnection = new Tmp36Connection(adcConnection.In(Mcp3008Channel.Channel0), voltage))
46-
using(var lightConnection = new VariableResistiveDividerConnection(adcConnection.In(Mcp3008Channel.Channel1), ResistiveDivider.ForLowerResistor(10000)))
40+
using (var adcConnection = new Mcp3008SpiConnection(
41+
driver.Out(adcClock),
42+
driver.Out(adcCs),
43+
driver.In(adcMiso),
44+
driver.Out(adcMosi)))
45+
using (var temperatureConnection = new Tmp36Connection(
46+
adcConnection.In(Mcp3008Channel.Channel0),
47+
voltage))
48+
using (var lightConnection = new VariableResistiveDividerConnection(
49+
adcConnection.In(Mcp3008Channel.Channel1),
50+
ResistiveDivider.ForLowerResistor(10000)))
4751
{
4852
Console.CursorVisible = false;
4953

@@ -53,7 +57,8 @@ static void Main()
5357
decimal resistor = lightConnection.GetResistor();
5458
var lux = resistor.ToLux();
5559

56-
Console.WriteLine("Temperature = {0,5:0.0} °C\tLight = {1,5:0.0} Lux ({2} ohms)", temperature, lux, (int)resistor);
60+
Console.WriteLine("Temperature = {0,5:0.0} °C\tLight = {1,5:0.0} Lux ({2} ohms)", temperature, lux, (int) resistor);
61+
5762
Console.CursorTop--;
5863

5964
Thread.Sleep(1000);

0 commit comments

Comments
 (0)