Skip to content

Instantly share code, notes, and snippets.

@kokeiro001
Created February 13, 2019 07:02
Show Gist options
  • Save kokeiro001/1e3b9946fe113976904d0286db1c1969 to your computer and use it in GitHub Desktop.
Save kokeiro001/1e3b9946fe113976904d0286db1c1969 to your computer and use it in GitHub Desktop.
DHT11からデータ取得するスクリプトの一部。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Unosquare.RaspberryIO.Gpio;
namespace KokeiroPi.ConsoleApp.Devices
{
enum DHTReadErrorState
{
None,
MissingData,
CRC,
}
class DHT11ReadResult
{
public DHTReadErrorState Error { get; set; }
public int Temperature { get; set; }
public int Humidity { get; set; }
public string ErrorMessage { get; set; }
}
class DHT11
{
private readonly GpioPin pin;
public DHT11(GpioPin pin)
{
this.pin = pin;
}
public async Task<DHT11ReadResult> Read()
{
pin.PinMode = GpioPinDriveMode.Output;
await pin.WriteAsync(GpioPinValue.High);
await Task.Delay(TimeSpan.FromMilliseconds(25));
await pin.WriteAsync(GpioPinValue.Low);
await Task.Delay(TimeSpan.FromMilliseconds(11));
pin.PinMode = GpioPinDriveMode.Input;
pin.InputPullMode = GpioPinResistorPullMode.PullUp;
var data = CollectInput();
var pullUpLengths = ParseDataPullUpLengths(data);
if (pullUpLengths.Length != 40)
{
return new DHT11ReadResult
{
Error = DHTReadErrorState.MissingData,
ErrorMessage = $"data.Length={data.Length}, pullUpLengths.Length={pullUpLengths.Length}",
};
}
var bits = CalculateBits(pullUpLengths);
var result = BitsToBytes(bits);
var checksum = CalculateChecksum(result);
if (result[4] != checksum)
{
return new DHT11ReadResult
{
Error = DHTReadErrorState.CRC
};
}
return new DHT11ReadResult
{
Temperature = result[2],
Humidity = result[0],
Error = DHTReadErrorState.None
};
}
private GpioPinValue[] CollectInput()
{
var unchangedCount = 0;
var maxUnchangedCount = 1000;
var last = default(GpioPinValue?);
var data = new List<GpioPinValue>(maxUnchangedCount * 2);
while (true)
{
var current = pin.ReadValue();
data.Add(current);
if (last != current)
{
unchangedCount = 0;
last = current;
}
else
{
unchangedCount++;
if (unchangedCount > maxUnchangedCount)
{
break;
}
}
}
return data.ToArray();
}
private int[] ParseDataPullUpLengths(GpioPinValue[] data)
{
var state = State.InitPullDown;
var lengths = new List<int>(data.Length);
var currentLength = 0;
for (int i = 0; i < data.Length; i++)
{
var current = data[i];
currentLength++;
switch (state)
{
case State.InitPullDown:
if (current == GpioPinValue.Low)
{
state = State.InitPullUp;
}
break;
case State.InitPullUp:
if (current == GpioPinValue.High)
{
state = State.DataFirstPullDown;
}
break;
case State.DataFirstPullDown:
if (current == GpioPinValue.Low)
{
currentLength = 0;
state = State.DataPullUp;
}
break;
case State.DataPullUp:
if (current == GpioPinValue.High)
{
currentLength = 0;
state = State.DataPullDown;
}
break;
case State.DataPullDown:
if (current == GpioPinValue.Low)
{
lengths.Add(currentLength);
state = State.DataPullUp;
}
break;
default:
throw new InvalidOperationException(nameof(state));
}
}
return lengths.ToArray();
}
private bool[] CalculateBits(int[] pullUpLengths)
{
var shortestPullUp = pullUpLengths.Min();
var longestPullUp = pullUpLengths.Max();
var halfway = shortestPullUp + (longestPullUp - shortestPullUp) / 2;
var bits = new bool[pullUpLengths.Length];
for (int i = 0; i < pullUpLengths.Length; i++)
{
bits[i] = pullUpLengths[i] > halfway;
}
return bits;
}
private byte[] BitsToBytes(bool[] bits)
{
if (bits.Length % 8 != 0)
{
throw new ArgumentException(nameof(bits));
}
if (BitConverter.IsLittleEndian)
{
bits = bits.Reverse().ToArray();
}
var bitArray = new BitArray(bits);
var byteArray = new byte[bits.Length / 8];
bitArray.CopyTo(byteArray, 0);
if (BitConverter.IsLittleEndian)
{
byteArray = byteArray.Reverse().ToArray();
}
return byteArray;
}
private byte CalculateChecksum(byte[] theBytes)
{
return (byte)(theBytes[0] + theBytes[1] + theBytes[2] + (byte)(theBytes[3] & (byte)255));
}
private enum State
{
InitPullDown,
InitPullUp,
DataFirstPullDown,
DataPullUp,
DataPullDown,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment