RobTillaart / DHTNew

Arduino library for DHT11 and DHT22 with automatic sensor recognition
MIT License
100 stars 15 forks source link

Strange readings #11

Closed Mr-HaleYa closed 4 years ago

Mr-HaleYa commented 4 years ago

I am using esp32 ttgo sim 800l (https://rb.gy/ogywnq) Dfrobot dht22 (https://www.dfrobot.com/product-1102.html)

my code

DHTNEW DHT(18); DHT.setWaitForReading(true);

float DHTtempBuffer[7];
float DHThumidityBuffer[7];
int DHTReadings = 7;             // number of DHT readings before choosing a median

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    DHT.read();                                     // Gets a reading from the DHT sensor
    DHThumidityBuffer[i] = DHT.getHumidity();
    DHTtempBuffer[i] = DHT.getTemperature();
  }
  sortData(DHThumidityBuffer, DHTReadings);                     //sorts array low to high
  DHThumidity = DHThumidityBuffer[(DHTReadings - 1) / 2];       //gets median of the array
  sortData(DHTtempBuffer, DHTReadings);                         //sorts array low to high
  DHTtemperature = DHTtempBuffer[(DHTReadings - 1) / 2];        //gets median of the array
}

So my problem is that even tho I use a filtering algorithm to get rid of highs and lows by taking 7 readings then choosing a median I will occasionally get some massive dips in temperature (and spikes in humidity as a result). my temperature in my room stays about 24°C and the dips are -12 and 12 °C so half the temp and half * -1. I have no clue why it is doing this... It runs every ~2 mins and when the bad readings start it does it consistently for a few runs before correcting itself.

18

Nothing moves nothing is touched nothing changes... It just goes wack... Could it be a library error? I don't see how it could be but you're a smart man @RobTillaart so you may see something I'm missing. I have also thought of the potential that its a dud sensor. I hope not bc i ordered 20 more before testing the one I'm using. I had the thought that maybe adding more reading (like 15 instead of 7) so there is more to data to filter but it looks like all the readings it's taking in those fault zones are bad...

Would appreciate any suggestion - Regards Hale

RobTillaart commented 4 years ago

The strange numbers seem to indicate that some bits are not read correctly. 12 equls 8+4 so 2 bits. Most often this is caused by the (missing) pull up resistor. So three questions: How long is the wire between ESP and DHTsensor? What is the value of the pull up resistor? What is the voltage level of the powersupply?

Mr-HaleYa commented 4 years ago

Thanks for the quick reply,

like I said initially I am using a DFrobot DHT22 19

1) How long is the wire between ESP and DHT sensor?

I am using the provided 12in cable, the wiki says the sensor is good up to 20m cable (I have my doubts on this tho)

2) What is the value of the pull-up resistor?

I found this comment about the product

The PCB has an I2C pull-up resistor and a decoupling cap

Additionally, all diagrams I have found of it wired show it without external pullups and all the docs I have read say it works with esp32. Also a direct reply from the company said that no external pull-up was needed due to the one on the PCB.

3) What is the voltage level of the power supply?

I have it connected to the 5v rail of the esp as the doc says it is 5v powered. I do have it being powered of the front ports of my desktop tho... could this all be attributed with it being supplied limited current?

RobTillaart commented 4 years ago
  1. 14 inch ~ 35 cm, normally I would add a pull up resistor 4K7 Do you have a scope to see the squareness of the signals on the line? Very useful tool when doing hardware.

  2. Strange that the documentation mentions an I2C pull up as the DHT22 is not a I2C device.

The fact that all diagrams don't show a pull up can be caused by the fact that they use short wires? Check this tutorial - https://learn.adafruit.com/dht/connecting-to-a-dhtxx-sensor it definitely uses a pull up. Also the equivalent datasheet - https://akizukidenshi.com/download/ds/aosong/AM2302.pdf promotes a pull up.

  1. The 5V should work, although it might give 5V on the ESP pins and I do not know if these can stand it for longer periods. But you have too many good readings so this is not the prime suspect.

  2. The DHT.read() function returns an error code if it detects one. 4a. You do not check on this, why not? 4b. Can you create a log file to see the error code when the dips occur. 4c. If errors are detected, adjust the code so it retries after e.g. 5 seconds.

  3. Can you try this project? it seems to be an ESP specific library. https://www.dfrobot.com/blog-910.html

Mr-HaleYa commented 4 years ago

1) Do you have a scope to see the squareness of the signals on the line?

sorry.. I do not have an o-scope since the university has closed

2) Strange that the documentation mentions an I2C pull up as the DHT22 is not an I2C device.

this was not documentation, it was a reply a user left on a purchase.

The fact that all diagrams don't show a pull up can be caused by the fact that they use short wires?

The tutorials (plural) that are on their site all show them using the same cable that is shipped with it.

Check this tutorial - https://learn.adafruit.com/dht/connecting-to-a-dhtxx-sensor it definitely uses a pull up. Also the equivalent datasheet - https://akizukidenshi.com/download/ds/aosong/AM2302.pdf promotes a pull up.

That DHT 22 is not on a PCB and is instead just the raw sensor and yes the raw sensor very much does require a pull up between VCC and data, but the DFrobot version is the raw sensor mounted to a PCB and the PCB has a 10k pull-up between VCC and data just as shown in that example.

4) The DHT.read() function returns an error code if it detects one.

Isn't it also supposes to through a crazy number at you (-999 if I remember) when it gets an error and we have none of those?

5) Can you try this project? it seems to be an ESP specific library.

that library is just a fork of the Arduino-DHT library so I didn't think it would be any different, I also wanted to use yours lol. However, It does say

none of the DHT libraries I found were written to work without errors on the ESP32. For ESP32 (a multi core/ multi processing SOC) task switching must be disabled while reading data from the sensor.

he is specifically talking about the dht22 so this might actually be legit

RobTillaart commented 4 years ago

Thanks for your replies

  1. pull up The fixed 10 K pull up on the PCB might be too high so an addition 4K7 might improve the signal quality.

    1. DHT.read() return value I used a crazy number so it would not be mistaken for an "valid temperature or humidity" -999 is crazy enough for that purpose. The return value can see if there is e.g. an CRC error and that helps to solve the issue.
  2. interrupts The DHTNEW library has a flag to disable interrupts during the time critical data extraction it is pretty new and I have only tested it on an UNO. PLease give it a try.

Add this line before DHT.read()

DHT.setDisableIRQ(true);

With my next purchase-round I'm going to add a number of ESP32 so I can do more testing.

Mr-HaleYa commented 4 years ago

so I powered up the project again to see if it would reoccur and sure enough, it did. However, I have found something interesting. When I press the reboot button my readings stay stable for quite some time before doing it ~8 passes. If I unplug the sensor and plug it back in I get 1-3 good passes then it rapidly drops to -12 after 2-5 passes it bumps to 12 and after another 2-5 int recovers. What could this mean???

Mr-HaleYa commented 4 years ago

side note: I changed it to 15 reading instead of 7 to see if it would help but no it has not

red is unplugged and replugged and yellow are just power cycles with onboard button 20

so in my debug log when I get the dips it looks like this (humid, temp°C)

40.40   25.70   //it always gives 1 good reading as far I can see
100.00  12.90
100.00  -12.90
100.00  -12.80
100.00  12.80
100.00  12.90
100.00  -12.80
100.00  -12.90
100.00  12.90
100.00  -12.90
100.00  -12.90
100.00  -12.90
100.00  -12.90
100.00  -12.90
100.00  -12.90

on a good pass, the readings look more like

40.50   25.60
41.70   25.70
40.70   25.70
40.60   25.60
40.70   25.70
40.70   25.70
40.60   25.60
40.60   25.60
40.60   25.60
40.60   25.60
40.60   25.60
40.70   25.70
40.60   25.70
40.60   25.60
40.70   25.70

In the passes right before it fails it looks like

40.60   25.60
41.60   25.70
40.50   25.60
40.50   25.60
40.60   25.70
40.70   25.80
40.60   25.70
40.50   25.60
40.60   25.70
40.50   25.60
40.60   25.70
40.60   25.70
100.00  12.80
40.60   25.70
100.00  12.80
RobTillaart commented 4 years ago

Further analysis The fact that there are so much good readings, means that the code flow is OK. Hardware issues has been discussed and you need to test and verify these.

In the software to read the DHT sensors the timing is the most critical part. For the much faster ESP32 (compared to UNO) this timing should not be a problem however the "multitasking" behavior of the ESP has been mentioned as a possible cause in this and other timing issues. However differences in hardware including differences in quality of the sensors (including fake and cheap clones) have caused many problems in the past too.

In this analysis I will prove the cause is not in the software but in the hardware, and that a work around can possibly be made in software.

Humidity Jumps to 100.0 in the code the value is constrained to the range 0..100 so the value 100 will not inform us what happend with the received bit-pattern. Come back to this later.

Temperature I see three temperature values in your log, so lets analyse the underlying bit pattern. In this analysis the MSB is most informative.

temperature = ((_bits[2] & 0x7F) * 256 + _bits[3]) * 0.1;
...
if (_bits[2] & 0x80)  // negative temperature
  {
    temperature = -temperature;
reversing these lines of code gives us Value Val * 10 bits[2] pattern bits[3] pattern
25.70 257 0000 0001 0000 0001
12.80 128 0000 0000 1000 0000
12.90 129 0000 0000 1000 0001
-12.90 -129 1000 0000 1000 0001

Notice : the Most Significant Bit has shifted 1 place to the left.

cause negative sign This means that the most right bit of bits[2] is in fact the LSB of the real humidity value. as a LSB is relative noisy this fluctuates between 0 and 1. That causes the negative sign to pop up randomly when this error occurs.

cause high humidity As the left shift moves in a bit in bi[0] which is the MSB of the humidity, it adds 6553.6 to the humidity, causing it to be >> 100 and therefor it will be constrained to 100.

AS far as I can see all wrong readings have a humidity of 100. So we might assume that when shift happens, we always shift in a HIGH bit. Where does that come from and WHY?

Cause of the shift In the code in _readsensors the bits are defined by the length of a LOW period measured in micros. These lines (around 170-180)

  loopCnt = DHTLIB_TIMEOUT;
    while(digitalRead(_pin) == HIGH)
    {
      if (--loopCnt == 0) return DHTLIB_ERROR_TIMEOUT;
    }

    if ((micros() - t) > 40)
    {
      _bits[idx] |= mask;        <<< sets HIGH bit
    }

As we get an extra HIGH bit we must conclude the time is larger than 40 us.

The number 40 is based upon the specs in the datasheet of the DHT sensors:

40 us is 42% larger than the 28us 40 us is 42% smaller than the 70us So the margin is in both directions equal in size in relative terms (harmonic average). That is the reason I choose 40. As this core code worked for years with many clients it is a good choice.

So for some reason the data pin stays HIGH too long (sometimes), or has difficulties to become LOW fast enough. An detailed analysis of the hardware is mandatory to find the cause.

CONCLUSION The root cause is not found in the code, it works too well too often. The above analysis shows that the data-pin does not goes LOW fast enough according to the specs / datasheet.

A possible solution to work around this incorrect behavior is to adjust the timing threshold value in the software, in concreto the value in line 176 from 40 to 50. This gives the signal 10 us extra time to get LOW and is still far enough from the 70 to be discriminating between 0 and 1. If the problem still occurs at 50, one could even try 60, but it must stay between 28 and 70.

Please test if this proposal solves the issue

Mr-HaleYa commented 4 years ago

You are amazing... You literally broke it down and explained it so well. How do I buy you a coffee???

Anyways, I was on board with the idea that it was a hardware issue not explicitly software related. I modified the dhtnew.cpp file and changed it to 50 and so far not a single bad reading. either your a freaking wizard and solved it or it just hasn't reoccurred yet. I have restarted, unplugged, and power cycled like 20 times, and it's going strong. all rows look like this

18.50   24.50
13.10   24.90
13.20   24.90
13.20   24.90
13.30   24.90
13.40   24.90
13.40   24.90
13.40   24.90
13.30   24.90
13.30   24.90
13.20   24.90
13.20   24.90
13.20   24.90
13.20   25.00
13.20   25.10

I will keep you informed on the status of the next 24 hours. Might I suggest that if it does not falter again meaning this minuscule increase in time was able to eliminate the problem, you should make this an update to prevent future people from suffering as I (briefly) did?

Thank you for all the time you have put into your responses - Hale

RobTillaart commented 4 years ago

Thanks for the compliments, No wizard otherwise I would focus on other things than software. It is just (hard) analytical thinking and understand the details.

I still think it is a hardware issue somehow as the timing is out of specification. Fortunately it is an problem that can be solved in software in a way it has very little chance to affect any other platform as 50 is well under the 70 uS.

I will prepare a PR with the adjusted threshold and wait for the results of your 24h test.

Mr-HaleYa commented 4 years ago

dang it...

100.00  -11.60
100.00  -11.60
100.00  -11.70
100.00  11.60
100.00  -11.60
100.00  11.70
100.00  11.70
100.00  -11.60
100.00  -11.60
100.00  -11.60
100.00  11.70
100.00  11.70
100.00  11.70
100.00  11.60
100.00  11.60

that's with 50... The lower numbers are bc its colder inside today.

100.00  11.70
100.00  11.80
100.00  11.80
100.00  11.70
100.00  11.80
100.00  11.80
100.00  11.80
100.00  -11.80
100.00  11.80
100.00  -11.80
100.00  11.80
100.00  11.80
100.00  11.80
100.00  11.80
100.00  11.80

and that's with 60....

100.00  -11.90
100.00  -421.40
100.00  -421.40
100.00  -421.40
100.00  -421.40
100.00  -421.40
100.00  421.40
100.00  421.40
100.00  421.40
100.00  -421.40
100.00  421.40
100.00  -421.40
100.00  -421.40
100.00  -421.40
100.00  -421.40

I tried 30 just for fun and got this ^^^

Mr-HaleYa commented 4 years ago

It's so weird tho... after reverting back to 40, It gives those dips then recovers and never does it again... Instead all of a sudden after running for like 8 hours the sensor shut off or something because it was a solid reading of -999 on my graph after that point. It never did recover after that until I unplugged the sensor and plugged it back in.

RobTillaart commented 4 years ago

So 40 behaves pretty good in long run, 50 is slightly better at start. 60 same. 30 is definitely too short as it adds 1 bits (numbers are larger).

It seems that the processor in the sensor got locked somehow in the end. Resetting the sensor helps. This could be done under program control by switching the powerline by means of a mosfet, Was the sensor hot?

Mr-HaleYa commented 4 years ago

no, everything was the same temperature as the box ~23°C. so all I'm needing is an internal temp and humidity sensor so we can monitor the temp to see if it gets cooked in the sun and to know if water is getting in (humidity will spike). I'm concluding these are duds so if you have any hardware change suggestions I'm up for some modding. Or do you have any suggestions on what to buy?

RobTillaart commented 4 years ago

I'll come back to it later.

RobTillaart commented 4 years ago

ALTERNATIVE SENSOR SHT31 from Sensirion would be my choice. It is an I2C sensor so you need to connect the hardware in another way. I have written a library https://github.com/RobTillaart/SHT31 which has a similar enough interface to get it up and running quick.

Accuracy is better than DHT22 although resolution is approx. same.

It has a build in heater to evaporate any condensation (e.g. if humidity goes very high) but you need to use that with care, my library supports this heater function and has some hooks to check the timing of the heater

There are three known sensors with slightly different accuracy etc. Check the datasheet https://www.mouser.com/datasheet/2/682/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital-971521.pdf

Adafruit has a breakout version of the SHT31 - https://www.adafruit.com/product/2857

DHT22 I have had the DHT22 (no breadboard version) running for many days (up to a week) without serious glitches with an UNO. So to understand the cause of the permanent failing after XX hours the hardware needs to be investigated.

One option is (again a workaround) is to power up and down the sensor from the ESP, this will cost you an extra pin and minimal code (pin HIGH wait 2 seconds, read sensor pin LOW). This will work quite well and in fact it is used in systems that are battery powered to safe energy.

RobTillaart commented 4 years ago

This question is still not answered: What value does DHT.read() return when the temperature and humidity == -999

That gives more information where in the protocol the handshake fails.

RobTillaart commented 4 years ago

The long run usage of DHT22 really depends on the individual sensor. See: https://forum.arduino.cc/index.php?topic=432544.15

If price is no issue => give the SHT31 a try (try it anyway to get some experience / reference) Or go for the switch on / off construction as that is much cheaper and will work.

RobTillaart commented 4 years ago

Studied the datasheet again, and I see this phrase "Data-bus's free status is high voltage level." but it is not specified if the host or the sensor should keep the data line HIGH . A quick look in two alternative libraries shows none pulls the line up after the sensor is read.

To test if this causes the long term failure you can add 2 lines to DHT._read() at the start (around line 86)

int DHTNEW::_read()
{
  // READ VALUES
  if (_disableIRQ) noInterrupts();
  int rv = _readSensor();
  if (_disableIRQ) interrupts();
  // put databus in HIGH state between reads.   
  pinMode(_pin, OUTPUT);        <<<<<<<< add line
  digitalWrite(_pin, HIGH);     <<<<<<<< add line
   _lastRead = millis();

Can you give this a try with a long run?

RobTillaart commented 4 years ago

FYI Made an issue - https://github.com/RobTillaart/DHTNew/issues/13 - to investigate enable/disable of the power supply in the library. Looks not difficult, but could have side effects too.

Mr-HaleYa commented 4 years ago

I think I will try the sht31, I would like to buy form DFrobot as that's where I get all my parts for this project, I just hope it actually works... I would appreciate it if you visited their site and glanced over it to see if it looks compatible and decent.

Sht31

Also, that is quite a large increase in pins going from one to three where I have almost all of my pins populated. Are all of the pins necessary? Or is there any other sensor that is a 1 pin? Of course this is just me being nitpicky

As for the checking what the error is, what code would you like me to insert together this error code? I would gladly do some error testing for you.

also with your comment saying the no breadboard version should I just desolder it from the breadboard and try it raw like you did and put my own pull up resistor and everything to see if that fixes it. Maybe it's just their combination of capacitor and resistor.

RobTillaart commented 4 years ago

DFRobotics makes quite good stuff normally and the price is a bit better than Adafruits. From the 6 pins you only need to connect VCC GND SDA and SCL, so in fact you need 1 pin more than for the DHT11.

Because I2C is a bus other devices may use the same I2C pins (e.g. LCD or OLED display, FRAM EEPROM etc)

RobTillaart commented 4 years ago

As for the checking what the error is, what code would you like me to insert together this error code? I would gladly do some error testing for you.

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    int status = DHT.read();                                     // Gets a reading from the DHT sensor
     Serial.println(status);
RobTillaart commented 4 years ago

also with your comment saying the no breadboard version should I just desolder it from the breadboard and try it raw like you did and put my own pull up resistor and everything to see if that fixes it. Maybe it's just their combination of capacitor and resistor.

Than I would just order a plain sensor. Your breadboard version works well way too often I would say.

Mr-HaleYa commented 4 years ago

Than I would just order a plain sensor. Your breadboard version works well way too often I would say.

I don't understand what you mean by this. I was asking if I should remove this image

from this

image

and try this

image

to see if it works (doesn't give false readings like it currently is)

RobTillaart commented 4 years ago

Shure you can, the idea is good to do that test but I would buy a new sensor. And then compare the results.

Mr-HaleYa commented 4 years ago

I bought seven of them and they are all doing the same thing so I don't think it's a singular sensor problem unless the entire batch was bad. I would understand one or two out of a batch but for all seven of mine to be doing the exact same thing raise some suspicions with me.

RobTillaart commented 4 years ago

all doing the same thing What do you mean by "the same thing"

  • the timing issue
  • the crash after a few hours.

All the boards use the same pull up resistor etc so in a way it is good they behave the same

RobTillaart commented 4 years ago

STILL OPEN TEST 1

Studied the datasheet again, and I see this phrase "Data-bus's free status is high voltage level." but it is not specified if the host or the sensor should keep the data line HIGH . A quick look in two alternative libraries shows none pulls the line up after the sensor is read.

To test if this causes the long term failure you can add 2 lines to DHT._read() at the start (around line 86)

int DHTNEW::_read()
{
  // READ VALUES
  if (_disableIRQ) noInterrupts();
  int rv = _readSensor();
  if (_disableIRQ) interrupts();
  // put databus in HIGH state between reads.   
  pinMode(_pin, OUTPUT);        <<<<<<<< add line
  digitalWrite(_pin, HIGH);     <<<<<<<< add line
   _lastRead = millis();

Can you give this a try with a long run?

RobTillaart commented 4 years ago

STILL OPEN TEST 2

This question is still not answered: What value does DHT.read() return when the temperature and humidity == -999

That gives more information where in the protocol the handshake fails.

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    int status = DHT.read();                                     // Gets a reading from the DHT sensor
     Serial.println(status);
RobTillaart commented 4 years ago

Merged the PR for the thresshold timing as it improves the behavior on the ESP and makes it easier to adjust this setting.

Mr-HaleYa commented 4 years ago

all doing the same thing What do you mean by "the same thing"

  • the timing issue
  • the crash after a few hours.

All the boards use the same pull up resistor etc so in a way it is good they behave the same

Both, all of them give me the -12, 12 then correct readings and after a couple hours they -999

After leaving one of them crashed for overnight when I came back he actually does recover from the crash after about 2 hours then ran 8 hours and crashed again then recovered after about 2 and is still running, however immediately after recovering from the crash it does the timing air and gives me -12, 12 and then recovers to actual readings

Mr-HaleYa commented 4 years ago

STILL OPEN TEST 2

This question is still not answered: What value does DHT.read() return when the temperature and humidity == -999

That gives more information where in the protocol the handshake fails.

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    int status = DHT.read();                                     // Gets a reading from the DHT sensor
     Serial.println(status);

It is 3 a.m. here but yes once I am awake in the morning and functional I will put this code in and let you know what happens when it gives me the false readings and what happens when it crashes.

Mr-HaleYa commented 4 years ago

STILL OPEN TEST 1

Studied the datasheet again, and I see this phrase "Data-bus's free status is high voltage level." but it is not specified if the host or the sensor should keep the data line HIGH . A quick look in two alternative libraries shows none pulls the line up after the sensor is read.

To test if this causes the long term failure you can add 2 lines to DHT._read() at the start (around line 86)

int DHTNEW::_read()
{
  // READ VALUES
  if (_disableIRQ) noInterrupts();
  int rv = _readSensor();
  if (_disableIRQ) interrupts();
  // put databus in HIGH state between reads.   
  pinMode(_pin, OUTPUT);        <<<<<<<< add line
  digitalWrite(_pin, HIGH);     <<<<<<<< add line
   _lastRead = millis();

Can you give this a try with a long run?

I will do this test after I have finished test 2

RobTillaart commented 4 years ago

Thanks, and you better get some sleep :)

I will have a quick check if I can catch the bit shift in the library. Will make a separate branch for that called testing.


Tested the code impact

Added these lines to the end of the .cpp file in _readSensor()

  // CATCH RIGHTSHIFT BUG ESP (only 1 single bit)
  // humidity is max 1000 = 03 E8 for DHT22   
  // 64 for DHT11 so most significant bit may not be set.
  if (_bits[0] & 0x80)
  {
    Serial.println(F("catch"));
    // shift 40 bytes one position to the left. (last bit will be missed...)
    for (uint8_t i = 0; i < 5; i++)
    {
      if (i && (_bits[i] & 0x80)) _bits[i-1]++;
      _bits[i] <<= 1;
    }
  }

  return DHTLIB_OK;
}

// -- END OF FILE --

This fix adds 98 bytes to runtime size of the lib (UNO) which is quite a lot, while it is used "seldom".

What I could implement in the library is just the detection :

  // CATCH RIGHTSHIFT BUG ESP (only 1 single bit)
  // humidity is max 1000 = 03 E8 for DHT22   
  // 64 for DHT11 so most significant bit may not be set.
  if (_bits[0] & 0x80) return DHTLIB_ERROR_BITSHIFT;

adds 14 bytes to the library (UNO)

user code should be something like (as you should always check the return value)

while dht.read()  != DHTLIB_OK;;

this adds another 4 bytes so in total there is a workaround for 18 bytes, where the user may choose or not to reread the sensor.

Mr-HaleYa commented 4 years ago

Apologies for my absence of replies, I have started the Test 2 with this code

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    int status = DHT.read();                                     // Gets a reading from the DHT sensor
    Serial.print(status); Serial.print("\t");                    // Prints return code
    DHThumidityBuffer[i] = DHT.getHumidity();
    DHTtempBuffer[i] = DHT.getTemperature();
    Serial.print(DHThumidityBuffer[i]); Serial.print("\t"); Serial.println(DHTtempBuffer[i]);
    delay(1000);
  }
}

and when I get the -12 or 12 it is showing error -1 which is #define DHTLIB_ERROR_CHECKSUM -1

I have not had a -999 reading yet (literally just started the test and those usually take 7+ hours to show up)

a good pass

0   41.00   25.00
0   40.90   24.80
0   40.90   24.90
0   40.90   24.90
0   41.00   25.00
0   40.90   24.90
0   41.00   25.00
0   41.00   25.00
0   41.00   25.00
0   41.00   24.90
0   41.00   25.00
0   40.90   24.80
0   41.00   24.90
0   41.00   25.00
0   40.90   24.80

a bad pass

0   39.50   24.80
-1  100.00  -12.50
-1  100.00  12.40
-1  100.00  -12.50
-1  100.00  12.50
-1  100.00  12.40
-1  100.00  12.50
-1  100.00  12.40
-1  100.00  12.40
-1  100.00  12.40
-1  100.00  12.40
-1  100.00  -12.40
-1  100.00  12.40
-1  100.00  -12.50
-1  100.00  12.40

ok we got some weird stuff going on....... if I comment out

  Serial.print("\n");
  Serial.print(celsius); Serial.println(" °C out");
  Serial.print(fahrenheit); Serial.println(" °F out");
  Serial.print(distance); Serial.println(" mm");
  Serial.print(DHTtemperature); Serial.println(" °C in");
  Serial.print(DHThumidity); Serial.println("% RH in");

from my loop (it just shows data after the loop has ran) it gives no errors......... and what looks like different data. (the humidity is way different)

0   18.50   24.80
0   18.20   24.70
0   17.90   24.70
0   17.60   24.60
0   17.40   24.70
0   17.20   24.70
0   17.10   24.80
0   16.80   24.70
0   16.70   24.70
0   16.60   24.70
0   16.50   24.70
0   16.40   24.70
0   16.30   24.70
0   16.30   24.80
0   16.20   24.70

like I said with humidity it is usually showing in the 40s and hardly ever changes even if I breathe on it... Except now when I breathe on it the temp drops to 1 °C

0   19.20   25.20
0   26.10   1.40
0   26.10   1.70
0   26.10   1.80
0   26.10   1.60
0   26.10   1.70
0   26.10   1.50
0   26.10   1.60
0   26.10   1.50
0   26.10   1.50
0   26.10   1.40
0   26.10   1.20
0   26.10   1.00
0   26.10   25.50
0   26.10   25.40
0   26.10   25.40

This is bizarre...

RobTillaart commented 4 years ago

Thanks for the update. The CRC error was expected, when the bits shift also the bits in the CRC are shifted so they do not add up. This confirms the bit shift diagnosis.

The new readings I cannot explain and as it is almost 23:00 (11pm) I won't dive into it right away.

I would expect that if the temp drops to 1C suddenly there would be a CRC error too.

Also strange humidity jump from 19.2 to 26.1 and stays exactly constant, no fluctuation whatever. Magnitude point of view, it is way too low not a factor 2 so no shift error. It misses this bitpattern 160= A0 = 1010.0000 Adding this bit pattern would give ~42 humidity

The temp looks also like it looses 4 high bits, 24C = 240 = F0 = 1111.0000

is that threshold still 50? Or higher?

Tomorrow I'll order the ESP32 so i hope to be able to test in parallel later this week.

To be continued

Mr-HaleYa commented 4 years ago

ok... now I'm pretty sure its something in my code... I rewrote the TEST example so it had the same function as my sketch and I haven't had a single error... I switch back to mine and ERROR.

The script I'm running is

#include <dhtnew.h>
DHTNEW mySensor(18);

void setup()
{
  mySensor.setWaitForReading (true);
  Serial.begin(9600);

  Serial.println("\n1. Type detection test, first run might take longer to determine type");
  Serial.println("STAT\tHUMI\tTEMP\tTIME\tTYPE");
}

void loop()
{
  getDHT();
  Serial.println();
}

float DHTtempBuffer[15];
float DHThumidityBuffer[15];
int DHTReadings = 15;                              // number of DHT readings before choosing a median

void getDHT(){
  for (int i = 0 ; i < DHTReadings; i++) {
    Serial.print(mySensor.getType()); Serial.print("\t");
    int status = mySensor.read();                                     // Gets a reading from the DHT sensor
    Serial.print(status); Serial.print("\t");
    DHThumidityBuffer[i] = mySensor.getHumidity();
    DHTtempBuffer[i] = mySensor.getTemperature();
    Serial.print(DHThumidityBuffer[i]); Serial.print("\t"); Serial.println(DHTtempBuffer[i]);
  }
}

ESP32_TTGOSIM800L.zip

This is a copy of what I am running that is giving all the errors. A lot of it does nothing right now since I have all functions commented except getDHT so I could test it.


also, I added a check for sensor type and when it gives me the 1°C readings it shows its a DHT11...

0   11  0   14.80   1.60    //reading #, type, Return code, humid, temp
1   11  0   14.60   1.40
2   11  0   14.60   1.40
3   11  0   14.50   1.30
4   11  0   14.50   1.30
5   11  0   14.50   1.40
6   11  0   14.60   1.40
7   11  0   14.50   1.30
8   11  0   14.50   1.40
9   11  0   14.60   1.50
10  11  0   14.60   1.50
11  11  0   14.50   1.30
12  11  0   14.50   1.40
13  11  0   14.50   1.40
14  11  0   14.60   1.40
Mr-HaleYa commented 4 years ago

I may have figured it out,

So I am using an esp32 ttgo sim800l so I can have a cellular connection to send my data to my website when out of wifi range. When I was first developing my code I naturally went to there examples and copied and pasted to get me up and running. Well, they have a power chip on the board than can act as a boost converter to keep the power active when using a battery down to 4V which is nice. The way you activate this feature is

#define I2C_SDA              21
#define I2C_SCL              22

#define IP5306_ADDR          0x75
#define IP5306_REG_SYS_CTL0  0x00

void setup()
{
  Wire.begin(I2C_SDA, I2C_SCL);
  bool   isOk = setPowerBoostKeepOn(1);
  Serial.println(String("IP5306 KeepOn ") + (isOk ? "PASS" : "FAIL"));
}

bool setPowerBoostKeepOn(int en) {
  Wire.beginTransmission(IP5306_ADDR);
  Wire.write(IP5306_REG_SYS_CTL0);
  if (en) {
    Wire.write(0x37); // Set bit1: 1 enable 0 disable boost keep on
  } else {
    Wire.write(0x35); // 0x37 is default reg value
  }
  return Wire.endTransmission() == 0;
}

I was slowly adding things to scratch sketch to see if i could catch the error code in the act and it was only after I added this that it started misbehaving. I ran each sketch 5 times for 5 mins to give it adequate time to act up and not a single one did until this was active and now every run it has the bad reading. as soon as I comment it out it fixes it. (I still get the -12, 12 every now and then but just 1 or 2 per pass instead of 50 in a row)

Also when It is active it identifies my sensor type as a DHT11 (This is new) and when its removed it shows correctly DHT22.

I'm not going to even pretend I know why this is happening (I assume overlapping bits?) but what I do know is the KeepActive state is usual 0 and the doc says that code sets the bit to 1. There comment in the code is "Set bit1: 1 enable 0 disable boost keep on"

I did not think I would need this feature since I have a battery boost converter built into my solar manager that supplies a constant 5v, but even when plugged into my Pc getting power-off USB if this is not enabled the whole board just shuts off after a couple of minutes.

I would love to hear your comments about this, until then I will have this running to see if it is truly error-free Thank you for all help so far. - Hale

RobTillaart commented 4 years ago

Good morning,

Bit Shift Error FYI, merged the bit shift error detection into the master.

Auto Detection working Identifying the wrong sensortype is new to me too. The auto detect code is straightforward, the DHT22 which has the fastest wake up is tried first,

#define DHTLIB_DHT11_WAKEUP        18
#define DHTLIB_DHT_WAKEUP          1

The difference is not small, it is an order of magnitude. The assumption of the auto detect is that if the sensor can be read after a wake up of only 1 millisecond it is a DHT22 or compatible. If due to the "power code", the sensor does not get enough power at a certain moment it might be possible that it reacts too late. This results in a failure of the correct detection.

Currently the library has no way to force the type of sensor, or to force a re detection after it has made up his mind. A minimal function

void  setType(uint8_t type = 0) { _type = type; };

could do the job, by default setting it to undetected. Will make a PR for that.

Power control If power is LOW it could affect the reading of individual bits although these are timing based, if the data line goes LOW too early it can be misinterpreted.

Solving this should be done at application level. You know when the "power code" is active and you can see if a read (both T & H ) is correct from the status of the read() which should be DHTLIB_OK or as simple as comparing it to the previous measurement, which should be close enough. OK, the latter is an heuristic and depends on what you define to be the largest drop acceptable.

Mr-HaleYa commented 4 years ago

removing the power boost code did not fix it... it still goes -999 after 8-10 hours (I forgot to log so I don't know the return value) then -12, 12 once recovered from -999...

RobTillaart commented 4 years ago

I got my ESP today so i hope to get them up and running by the weekend.

RobTillaart commented 4 years ago

Strange that the sensor resumes with a bit shift. Do you still use the 50 milliseconds timing? (it is now in the master)

What is the voltage over the VCC - GND pins? before and after crash?

Mr-HaleYa commented 4 years ago

Yes, I am using the current master code, I even check, and yes its at 50. For outside we use the Solar Power Management board that has a 5V boost converter that is very stable. Indoors I have used dedicated power supply (very heavy duty PS) and USB (3A USB PS and PC USB) all were set at 5V. Probing with a multimeter I see no fluctuation in voltage on pins.

Mr-HaleYa commented 4 years ago

I have swapped out my indoor test station with a DHT11 running the exact same code that I was using for the 22 (literally unplugged and plugged in new sensor) and for the last 4.5 hours, It hasn't given a single error...

RobTillaart commented 4 years ago

from: https://forum.arduino.cc/index.php?topic=432544.msg4605910#msg4605910

P.S. And, yep, looks like reading it faster than datasheet states makes it halt.

but the code does wait for more than 2 seconds. ... so no cause either.

BTW I merged 2 minor PR's into master.

RobTillaart commented 4 years ago

from dht22 datasheet

6. Operating specifications: (1) Power and Pins Power's voltage should be 3.3-6V DC. When power is supplied to sensor, don't send any instruction to the sensor within one second to pass unstable status. One capacitor valued 100nF can be added between VDD and GND for wave filtering.

Can you check if such a capacitor is on the Dfrobot board ?

RobTillaart commented 4 years ago

I created a pull request to force the data pin to HIGH between reads. It is stated in the datasheet and although the library works for hours without, I added it as a "floating" data line might be more vulnerable for noise.

It is in the develop branch, so if you have any chance to test please do.

Mr-HaleYa commented 4 years ago

What all is different in the dev branch? Also, where you able to replicate my conditions/results?

RobTillaart commented 4 years ago

Changes in dev https://github.com/RobTillaart/DHTNew/pull/19/files

I have had no time yet to solder the ESP32 and recreate stuff.
Saturday I will have more time as I have a bizz to run too :)