dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.17k stars 584 forks source link

Dht22 example doesn't work #416

Closed maximpn closed 5 years ago

maximpn commented 5 years ago

I have DHT22 sensors which works normally. I checked that by the default python script from Adafriut. I made a decision to give .net core on rpi platform a try with a simple example from the examples folder. I used Dhtxx example but it doesn't work.

This is my code:

using System;
using System.Threading;
using Iot.Device.DHTxx;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello DHT!");

        using (DhtSensor dht = new DhtSensor(26, DhtType.Dht22))
        {
            while (true)
            {
                Console.WriteLine($"Temperature: {dht.Temperature.Celsius} °C, Humidity: {dht.Humidity} %");

                Thread.Sleep(2000);
            }
        }
    }
}

Project file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="IoT.Device.Bindings" Version="0.1.0-prerelease.19251.2" />
    <PackageReference Include="System.Device.Gpio" Version="0.1.0-prerelease.19251.2" />
  </ItemGroup>

</Project>

I wasn't able to install System.Device.Gpio and IoT.Device.Bindings by using commands from the main readme.md so I just used the nearest proposed version by dotnet add.

I installed .net core on the rpi by using commands:

sudo apt-get install curl libunwind8 gettext
wget https://download.visualstudio.microsoft.com/download/pr/9650e3a6-0399-4330-a363-1add761127f9/14d80726c16d0e3d36db2ee5c11928e4/dotnet-sdk-2.2.102-linux-arm.tar.gz
wget https://download.visualstudio.microsoft.com/download/pr/9d049226-1f28-4d3d-a4ff-314e56b223c5/f67ab05a3d70b2bff46ff25e2b3acd2a/aspnetcore-runtime-2.2.1-linux-arm.tar.gz
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-2.2.102-linux-arm.tar.gz -C $HOME/dotnet
export DOTNET_ROOT=$HOME/dotnet 
export PATH=$PATH:$HOME/dotnet
tar zxf aspnetcore-runtime-2.2.1-linux-arm.tar.gz -C $HOME/dotnet

On top of that I wasn't able to run it on rpi without dotnet publish -r linux-arm since I get FileNotFoundExceptions and runtime isn't able to find System.Device.Gpio.

The result of the program:

pi@raspberrypi:~/publish $ dotnet test_dht22.dll
Hello DHT!
Temperature: NaN °C, Humidity: NaN %
Temperature: NaN °C, Humidity: NaN %
Temperature: NaN °C, Humidity: NaN %

I tried other library versions and sometimes got values like 123e-308.

Do I do something wrong or the project isn't ready yet for real usage (only people with deep .net knowledge can use it)?

joperezr commented 5 years ago

Hey @katzz0 thanks a lot for your feedback. I assume that since you have some code running with python that we can disregard any problems related to bad connections. Just to double check, do you have the right pin specified? From your code above, you should be using pin 26 in the BCM numbering, not the physical layout.

Do I do something wrong or the project isn't ready yet for real usage (only people with deep .net knowledge can use it)?

From what I can tell you didn't do anything wrong, unless the gpio pin that you specified is incorrect. As for your other question, this library is definitely ready for real usage. We build two different components out of this repo, 1) the main library (System.Device.Gpio) which contains all the protocols in order to talk to individual sensors and devices, and 2) A collection of classes that wrap different sensors (we call these: device bindings) and expose an easy way to talking to them in order to get data from them. These classes internally will call System.Device.Gpio library. Most of these device bindings have been ported by the community, so we don't yet have a good story on testing on the actual hardware for some of them so we have been reviewing based on the data sheets for the components. That is the case for the DhtSensor. Are you getting any exception after the NaN or do you get any additional information when attached to the debugger?

MarkCiliaVincenti commented 5 years ago

I had the same issue. Use the TryGetTemperatureAndHumidity instead rather than what is suggested in the samples.

joperezr commented 5 years ago

@katzz0 if what @MarkCiliaVincenti suggests works, we should log an issue to fix the methods that are not working properly, and at least in the meantime switch the examples to use the API that does work.

cc @ZhangGaoxing and @Ellerbach who added/worked on this binding.

MarkCiliaVincenti commented 5 years ago

Here's my code:

            using (DHTSensor inside = new DHTSensor(InsideGpioPin, DhtType.Dht22))
            {
                if (!inside.TryGetTemperatureAndHumidity(out Temperature insideTemp, out insideHumidity))
                {
                    //Console.WriteLine(" failed obtaining inside readings");
                    return;
                }

                insideTemperature = insideTemp.Celsius + InsideTemperatureOffset;
                insideHumidity += InsideHumidityOffset;
            }

Edit: seems like my code only works on the old MyGet package. Needs reworking for the dotnetfeed blob version.

MarkCiliaVincenti commented 5 years ago

OK I can confirm. My code works with 19171.3 Couldn't get the latest prerelease packages to read from DHT22 either. The TryGetTemperatureAndHumidity method doesn't exist anymore and IsLastReadSuccessful is always false.

joperezr commented 5 years ago

mm I see, interesting, I'll take a look at this and see what changed.

ZhangGaoxing commented 5 years ago

The last change was made by me. I don't have DHT22, I just make sure that the code I committed works correctly on my DHT11 and DHT12. Interestingly, the old code always reads errors on my DHT11 (just like the two above), so when I added DHT12, I changed the original code.

According to the datasheet, the DHT series of sensors are read in the same way, which is not a problem. The code I committed was also written entirely in accordance with the datasheet. Reading errors must be timing errors. I've made several key parts loop and stopped the reading as soon as it went out of time, but krwq prevented me from doing so(https://github.com/dotnet/iot/pull/318#discussion_r266714856).

Another possible reason is the version of the sensor. There are some fake DHT sensors in the market.

Give me some time and I will try to solve this problem. I don't have any equipment on hand now. I'll start processing this weekend.

maximpn commented 5 years ago

@joperezr thanks for the detailed explanation! I see that this behaviour is a combination of a few smaller problems. I just expected to run the sample as people usually with new things to try it out and it seems I picked up the wrong sensor to start with))) I checked the BMP280 binding and it works normally through I2C but I needed to change the default address since it was 0x77 but mine was 0x76. I think it would be nice to have the collection of addresses predefined since the majority of sensors have an ability to switch to an alternative address.

Regarding debugging, I didn't try debugging since I had problems with dotnet run and there is an issue for that https://github.com/dotnet/iot/issues/345. But now I know how to handle it via dotnet publish -r linux-arm.

I have both sensors DHT11 and DHT22 (it's actually 3-wire bigger module to be mounted on a surface). I can confirm the python scripts work and values are read correctly from that sensors. I could try to play with that to figure out the problem but next two weeks I'll be out of home and won't be able to take my rpi with me. But I can test both sensors after two weeks.

That might be helpful - I found that code in the internet https://broersa.github.io/dotnetcore/2017/12/29/raspberry-pi-thermometer-using-raspbian-dotnetcore-and-dht22-sensor.html and it also doesn't work.

@ZhangGaoxing I also think that's a timing issue. I have Raspberry Pi 3 Model B but it can work differently on Rpi 2 Model B and Rpi 3 Model B+. Finally 6 combinations should be tested to be sure that DHT11 and DHT22 work on Rpi.

RobinTTY commented 5 years ago

I was able to reproduce this problem using a Dht11 both on Raspberry Pi 3 Model B and Model B+. I also tested on both Linux and Windows with the same result. I remember timing also being an issue with 1-wire on UWP.

Edit: Testing with the python library from adafruit was successful.

Ellerbach commented 5 years ago

@ZhangGaoxing I also think that's a timing issue. I have Raspberry Pi 3 Model B but it can work differently on Rpi 2 Model B and Rpi 3 Model B+. Finally 6 combinations should be tested to be sure that DHT11 and DHT22 work on Rpi.

Yes, the timing is very sensitive. As explained in the readme, this can break depending on the platform you are using. I'm far from home where I have everything to test. So won't be able to best at least for a week. My code worked with DHT11 and DHT22, I have code running for quite some time wihtout any issue in .NE Core deployed thru Azure IoT Edge but I haven't updated it with the latest .NET Core IoT bits. So in short, will test it as soon as I can.

MarkCiliaVincenti commented 5 years ago

@ZhangGaoxing I also think that's a timing issue. I have Raspberry Pi 3 Model B but it can work differently on Rpi 2 Model B and Rpi 3 Model B+. Finally 6 combinations should be tested to be sure that DHT11 and DHT22 work on Rpi.

Yes, the timing is very sensitive. As explained in the readme, this can break depending on the platform you are using. I'm far from home where I have everything to test. So won't be able to best at least for a week. My code worked with DHT11 and DHT22, I have code running for quite some time wihtout any issue in .NE Core deployed thru Azure IoT Edge but I haven't updated it with the latest .NET Core IoT bits. So in short, will test it as soon as I can.

Not sure if this is relevant, but I tested on .NET Core on Raspbian on Raspberry Pi 3 Model B+ with DHT22 from dx.com that cost me some 4 euro, so they're probably fake :)

Rickvanderwaal commented 5 years ago

I am experiencing the same issues as described above.

Running on Raspbian on Raspberry Pi 3 Model B+ with DHT22 (AM2302). Package Iot.Device.Bindings version 0.1.0-prerelease.19278.2.

Testing with the python library from adafruit was successful.

import Adafruit_DHT
sensor = Adafruit_DHT.AM2302
pin = 26 
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
print 'Temperature: {0:0.1f}*C'.format(temperature)
print 'Humidity: {0:0.1f}%'.format(humidity)

It would be nice if i could read the sensor in .NET Core. I am using the following code:

static void Main()
{
    using (DhtSensor dht = new DhtSensor(26, DhtType.Dht22))
    {
        while (true)
        {
            Console.WriteLine($"Success {dht.IsLastReadSuccessful}, Temperature: {dht.Temperature.Celsius.ToString("0.0")} °C, Humidity: { dht.Humidity.ToString("0.0")} % ");
            Thread.Sleep(1000);
        }
    }
}

Above example gives me the following output: image

None of these values are correct. Am i doing something wrong?

joperezr commented 5 years ago

cc @ZhangGaoxing do you mind taking a look to see if that's expected?

ZhangGaoxing commented 5 years ago

OK, I'll check it again.

Rickvanderwaal commented 5 years ago

I looked into the source code and found the following issue,

Reading the bytes from the DHT22 seems to be correct but translating the bytes to humidity/temperature seems to be the issue.

DhtSensor.cs line 297 results in a temperature of 1.3°.

_readBuff[2] + (_readBuff[3] & 0x7F) * 0.1

When i replace the formula with the following code, the result of the temperature is 25.9°. Which is correct.

((_readBuff[2] & 0x7F) * 256 + _readBuff[3]) * 0.1

The same issue with humidity. DhtSensor.cs line 305 results in a humidity of 9.9%.

_readBuff[0] + _readBuff[1] * 0.1

The following code gives me a humidity of 59.1% which seems correct.

(_readBuff[0] * 256 + _readBuff[1]) * 0.1

I have made a pull request: https://github.com/dotnet/iot/pull/469

maximpn commented 5 years ago

My code still doesn't work. I tried DHT11 and DHT22 (python scripts work well for both sensors) and reading isn't successful so the result is the same:

Hello DHT!
Success False, Temperature: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 °C, Humidity: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 %
Success False, Temperature: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 °C, Humidity: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 %
Success False, Temperature: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 °C, Humidity: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 %
Success False, Temperature: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 °C, Humidity: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 %
Success False, Temperature: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 °C, Humidity: 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0 %

These are my files: Program.cs

using System;
using System.Threading;
using Iot.Device.DHTxx;

namespace dht22
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Hello DHT!");

            using (DHTSensor dht = new DHTSensor(26, DhtType.Dht22))
            {
                while (true)
                {
                    Console.WriteLine($"Success {dht.IsLastReadSuccessful}, Temperature: {dht.Temperature.Celsius.ToString("0.0")} °C, Humidity: {dht.Humidity.ToString("0.0")} %");

                    Thread.Sleep(2000);
                }
            }
        }
    }
}

dht22.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="IoT.Device.Bindings" Version="0.1.0-*" />
    <PackageReference Include="System.Device.Gpio" Version="0.1.0-*" />
  </ItemGroup>

</Project>

I use dotnet publish -r linux-arm --self-contained false to create the deployable program.

maximpn commented 5 years ago

When I tried to clone Iot project through git and build the sample for DhtXX I got it working but it asked me to install .Net Core 3.0 preview and produced the build for 2.1. Below you can see the result:

DHT11_readings

IMHO it doesn't seem stable. And I'm keen on making the code in my previous message working.

Rickvanderwaal commented 5 years ago

@katzz0 Which specific version of IoT.Device.Bindings are you using because you are using a wildcard in the .csproj. Have you added the dotnet-iot package source for nuget ? (https://dotnetfeed.blob.core.windows.net/dotnet-iot/index.json)

Also try to publish your project in release mode because of better performance. dotnet publish --configuration release --runtime linux-arm

You said it worked with the latest version of the iot project. Does it work for both devices dht11 & dht22?

benbuckland commented 5 years ago

Hi, i'm facing the same issue, returns data sporadically but even when it does it appears to be wrong :( Im using 19310.5 version of packages.

joperezr commented 5 years ago

The version that @benbuckland mentions is Preview6 which was released yesterday, so this does mean that the problem repros on latest build (so I'm reopening the issue). There is a PR out by @Rickvanderwaal that will hopefully fix this issue, and should be merged pretty soon.

benbuckland commented 5 years ago

@joperezr Very happy to help out so please let me know if there is anything I can do! Im not 100% confident that the PR will solve the issue totally, think it will solve for the incorrect measurements when data is returned but cant see anything that will solve the reliability of data being returned.

joperezr commented 5 years ago

Once we merge that PR, it would be great if you can update to reference that version of the package to see if that fixes the issue for you.

Rickvanderwaal commented 5 years ago

@benbuckland you are right, i only solved the incorrect measurements for dht22 because i think that is the most important. I agree we should work om the reliability. I do have Some idea’s but those are not backwards compatible. I think the current public methods/properties of the DHTSensor class are confusing and maybe that is the problem for reliability too. Maybe we should create another issue for working on reliability?

joperezr commented 5 years ago

Maybe we should create another issue for working on reliability?

Agreed. Let's use this one to make sure that the actual device works (although not reliable) which should be fixed with @Rickvanderwaal PR. We can then log an additional one just for reliability.

MarkCiliaVincenti commented 5 years ago

OK I can confirm. My code works with 19171.3 Couldn't get the latest prerelease packages to read from DHT22 either. The TryGetTemperatureAndHumidity method doesn't exist anymore and IsLastReadSuccessful is always false.

A number of months have passed so I thought I'd give it a go seeing that this issue was closed. The result is the same.

Old code that works (19171.3):

using (DHTSensor inside = new DHTSensor(InsideGpioPin, DhtType.Dht22))
{
    if (!inside.TryGetTemperatureAndHumidity(out Temperature insideTemp, out insideHumidity) || inside.Temperature.Celsius > 60d || inside.Humidity > 100d)
    {
        Console.WriteLine(" failed obtaining inside readings");
        return;
    }

    insideTemperature = insideTemp.Celsius + InsideTemperatureOffset;
    insideHumidity += InsideHumidityOffset;
}

New code that doesn't work (IsLastReadSuccessful is permanently false), 19456.1:

using (var inside = new Dht22(InsideGpioPin))
{
    if (!inside.IsLastReadSuccessful)
    {
        Console.WriteLine(" failed obtaining inside readings");
        return;
    }

    insideTemperature = inside.Temperature.Celsius + InsideTemperatureOffset;
    insideHumidity = inside.Humidity + InsideHumidityOffset;
}

I'll have to revert back until this issue is fixed.

benbuckland commented 5 years ago

@MarkCiliaVincenti You need to call .Temperature or .Humidity first and then check IsLastReadSuccessful. I am successful about 1 in 5 times of reading the sensor, have upgraded to the RPI4 thinking that the increased processing power would help the super time sensitive reading of the sensor but alas no luck.

MarkCiliaVincenti commented 5 years ago

Thanks, I'll try that later. Strange regarding the reliability. I estimate I was getting successful readings about 11 out of 12 times from the old build.

On Sat, 7 Sep 2019, 11:43 Ben Buckland, notifications@github.com wrote:

@MarkCiliaVincenti https://github.com/MarkCiliaVincenti You need to call .Temperature or .Humidity first and then check IsLastReadSuccessful. I am successful about 1 in 5 times of reading the sensor, have upgraded to the RPI4 thinking that the increased processing power would help the super time sensitive reading of the sensor but alas no luck.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dotnet/iot/issues/416?email_source=notifications&email_token=AF7U7YGGQCEQ3YRYRXIVL53QINZSVA5CNFSM4HMIWXCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6EU2HA#issuecomment-529091868, or mute the thread https://github.com/notifications/unsubscribe-auth/AF7U7YAROY6FHRPK26VX433QINZSVANCNFSM4HMIWXCA .

MarkCiliaVincenti commented 5 years ago

I confirm. Readings are available but the reliability is considerably poorer than with the NuGet package version 19171.3. Reverting back to that version.

benbuckland commented 5 years ago

Will take a look and compare commits, see if I can identify the problem.

benbuckland commented 5 years ago

I have taken a look and cant see any change that would affect the reliability of reading. I'm going to roll back to 19171.3 and see if reliability increases for me also.

krwq commented 5 years ago

Since this is 1-wire I wouldn't expect reliability but I bet we can do slightly better results than 10%. I know linux has a way of enabling 1 wire through kernel driver which might work better here.

cc: @ZhangGaoxing in case you're interested in picking this up

MarkCiliaVincenti commented 5 years ago

It's not slightly better. It's massively better in the old build. Also in a Python library I used before it was very rare that a reading was missed.

On Mon, 9 Sep 2019, 01:32 Krzysztof Wicher, notifications@github.com wrote:

Since this is 1-wire I wouldn't expect reliability but I bet we can bet slightly better results than 10%. I know linux has a way of enabling 1 wire through kernel driver which might work better here

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dotnet/iot/issues/416?email_source=notifications&email_token=AF7U7YABNDLSXBHN6A3HVCLQIWDQPA5CNFSM4HMIWXCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6F4PSY#issuecomment-529254347, or mute the thread https://github.com/notifications/unsubscribe-auth/AF7U7YGUG3QBHLJ77H6MOZ3QIWDQPANCNFSM4HMIWXCA .