DHT22 stability; unstable implementation.

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, 

 

I have made my own implementation for reading the DHT22;

I have used it successfully now for some time, however now I have made some

changes to Hw, and the reading is now unstable, sometimes it is successfull, often

it is successfull during an initial period from power-on, the suddenly misses out, more and more.

 

Hw changes include all components new, processor, lead to DHT, board (which is

now PCB (own design) instead of the old veroboard)

 

Before digging into the issue more Has anyone any knowns to tell for this kind of appearence, intermittent  

(like differencies in DHT items (unfortunately this time (first) I have soldered the DHT to the new wires, reluctant to chip away)

 

I have a list of possibles, however there might be experience with you out there:

changed clock, freq.(not using crystal, but internal on this version, though having possiblity to mount), some powering disturbancies (the 5V to DHT) (using a 10k pullup on signal), bit-distortion on the wire....(now approx 70cm, against before 10cm), fault in DHT itself, ....

Last Edited: Sun. Nov 5, 2017 - 07:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Will need a little more info.

 

Can you post a schematic of your circuit?

 

Can you post your code, using the code tags, (<> icon)?

 

Can you explain exactly what is and is not doing?

 

Can you put the 70 cm wire to the sensor back on the micro on the Veroboard, and another pin if one is still attached to that micro, and test that setup?

 

You mentioned not using a crystal.

A quick look at the data sheets show uSec timing pulses, and 40 bits in a row to read.

If your clock is not self -resynching, being even a little bit out of spec can be a lot out of spec by the time your read 40 bits...

Perhaps adding an external crystal, and changing the Fuses to use that, would be helpful.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ill be back with some more, unfortunately I have two places where I work, and of cause have the vero variant on the other site.

Also the designs are on another machine. So Ill be back. 

However, there is a "behavioural clue"; it seems that it is temperature sensitive, just now it gives the right readings all the time,

and then it has been left overnight in a room that has cooled, it is situated under the air-heat-pump flow, and it might be that

when temperature gets high, it stops giving the right decoding of bits. The error I get is a decoding error, during decoding,

the initial starting pulses are ok received.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gechxx wrote:
 Hw changes include all components new, processor, lead to DHT, board (which is

now PCB (own design) instead of the old veroboard)

So that sounds like you've changed pretty much everything?!

 

Before digging into the issue more Has anyone any knowns to tell for this kind of appearence, intermittent  

Did you build just one of the Veroboard models? And how many of the new board?

 

DocJC wrote:
Will need a little more info.

Indeed!

Can you post a schematic of your circuit?

 

Can you post your code, using the code tags, (<> icon)?

Instructions for posting both code & images: http://www.avrfreaks.net/comment...

 

Photographs - of both the Veroboard and new PCB - would also be helpful.

 

Can you explain exactly what is and is not doing?

+1

 

And what testing have you done?

 

Do you have an oscilloscope and/or logic analyser?

 

gechxx wrote:
Before digging into the issue more Has anyone any knowns to tell for this kind of appearence, intermittent 

 

DocJC wrote:
You mentioned not using a crystal.

Yes, that would be one of the fist things to check!

 

Hence my initial question of whether there was just one Veroboard model - it is quite possible that you just "got lucky" with that one ...

 

Also, have you carefully checked that all other parameters are, by design, solidly within specified operating limits under all conditions ... ?

 

EDIT

 

quote

Last Edited: Mon. Nov 6, 2017 - 12:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"changed everything"; well all Hw, Sw same, Hw design same (except for layout)

"more info": yes, sorry will be back

"oscilloscope": yes, but no; an old type without time-sequence recording, only steady state signals

 

New finding:  when I move the DHT22 up towards a lamp, temperature reading increases, and then suddenly the "bit-read" error from my code comes

and when I return the DHT to a cooler place the readings comes back displayed.

 

Could the DHT be faulty, from possible heating when soldering (have used sockets before), I really should do the cross testing with other DHT, and this DHT

on old board (but as said, then I will have to delay several days to retreive that).

 

Realize I should do more testing before troubling you folks, sorry. 

Thanks for support. will retreive the code and post in afternoon.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course, it's always possible that the DHT22 - or any other component(s) - could be faulty.

 

But I strongly suspect that a "marginal" design is far more likely - and, as Doc suggested, the RC oscillator would be a prime suspect

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good that I designed the into PCB place/possibilities to mount crystal then :)

And yes, could well be a margin design, its kind of ad-hoc.

 

For what it is worth, here comes the code, it's kind of talky commenting, I leave it in.

the main idea is to pick up the timing from counting on the known time period made

by DHT answering in the beginning. (sorry for the io.h, its a relic and same as avr/)

It is Error 3 that exits when seemingly gets too hot.

//#define __AVR_ATmega8__

#define F_CPU 8000000UL
#include "io.h"
#include <avr/delay.h>
#include <avr/interrupt.h>
#define TempBit  PB1
#define DHT_PORT PORTB
#define DHT_PIN  PINB
#define DHT_DDR  DDRB

uint16_t DHT(int* Out_Humid, int* Out_Temp)
{
/* routine to read the DHT temperature and humitidy */

   uint16_t  maxcount,count,mean,ccount1,ccount2;
   uint8_t  bit_no;
   uint8_t  byteno,setbit;
   unsigned char nbr_str[6];
   uint16_t err;
   uint8_t  bitfield[40];
   uint16_t interv[40];

   uint16_t Humid,Temp;
   uint8_t  sum,sum1,sum2,sum3,sum4,chk;

   DHT_DDR   |= (1<<TempBit) ;       // set port bit to output

   DHT_PORT |= (1<<TempBit) ;       // set high
   _delay_ms(200);                // initial stablizing wait, changed from 20 to 100

   DHT_PORT &= ~(1<<TempBit) ;       // set low for minimum 1ms according spec changed from 2 to 18 (now 50)
   _delay_ms(18);

   cli();                        // time critical starts here, turn off interrups

   DHT_PORT |= (1<<TempBit) ;       // set high for last trigger round
   _delay_us(40);                // 

   //--- change to listen 

   DHT_DDR &= ~(1<<TempBit);        // change port pin to input, now it should follow 80us low then 80us high

   DHT_PORT |= (1<<TempBit) ;       // set (input !) high which enables pull-up ??? removed possibly too strong ?
                                 // how relate to external pullup resistor,turn this off, well nothing works

   //count = 40;                   // rough assumption; loop below takes 3 clock cycles,
    count = 320;                  // for 8Mhz that would be 8 times 40 then
                                 // 1MHz clock would make loop could
                                 // up to 80us before expire waiting
   maxcount=count;

   while (  !( DHT_PIN & (1<<TempBit)) )  if(! --count)goto expire1 ;  // wait 80us for low to high, zero is false
   ccount1 = maxcount-count;                                        // the counted away is now measure for our 80us
                                                                    // as it takes for the while and if clause to exec
                                                                    // at this expire it NEVER goes HIGH

   count = maxcount;
   while (  ( DHT_PIN & (1<<TempBit)) ) if(! --count)goto expire2 ;    // wait 80us to go from high to low
                                                                    // at this expire it NEVER goes LOW again

   ccount2 = maxcount-count;                                   

   // should be low now, and go high after 50us for first dig

   for (bit_no=0 ; bit_no < 40 ; bit_no++)   //   40 bits; ie 5 x 8bit bytes are to arrive

      {
      // each bit starts with 50us low, then followed by short or long bit high puls; 

      count = ccount2;                  // approx 80, should give margine for 50

      while ( ! ( DHT_PIN & (1<<TempBit)) ) if(! --count)goto expire3 ;    // wait the 50us to go to high

      mean = ccount2-count;   // we think we now have a measure for count loop for the 50us lead time,
                              // following high less (26us) would then be a zero, and more should be a one (70us)
                              // note that this assignment steals time in itself

      interv[bit_no] = mean;  // note that now were stealing more time for the bit, moving the mean further
                              // this is just for verification testing

      count=ccount2;
      while (  ( DHT_PIN & (1<<TempBit)) ) if(! --count)goto expire4 ;    // wait max 70us to go from high to low

      count = ccount2 - count;  // added ..... is that ok... no; well yes should be
      // take care of received bit

       if (count < mean ) bitfield[bit_no] = 0; else bitfield[bit_no] = 1;    // give som extra for inserted code (10 removed)

       // the line should now be at low after the bit, starting new bit      

     }  // bit pickup loop

     /* all steps ok */

      sei();

     //---------- decimal not DHT11, but DHT22---------
     // transfer bits from bitfield

     Humid=0;
     for(setbit=0; setbit<16;setbit++)
         if ( bitfield[15-setbit]==1 ) Humid |= (1<<setbit) ;

    // temp
     Temp=0;
     for(setbit=0; setbit<16;setbit++)
         if ( bitfield[31-setbit]==1 )  Temp |= (1<<setbit) ;

     chk=0;sum=0;sum1=0;sum2=0;sum3=0;sum4=0;
     for(setbit=0; setbit<8; setbit++) {
         if ( bitfield[39-setbit]  == 1 )   chk |= (1<<setbit) ;
         if ( bitfield[7-setbit]   == 1 )  sum1 |= (1<<setbit) ;
         if ( bitfield[15-setbit]  == 1 )  sum2 |= (1<<setbit) ;
         if ( bitfield[23-setbit]  == 1 )  sum3 |= (1<<setbit) ;
         if ( bitfield[31-setbit]  == 1 )  sum4 |= (1<<setbit) ;
     }
     sum = sum1+sum2+sum3+sum4;

     if(sum != chk) {
         // checksum error return error
         return(100);
      }

    *Out_Humid=Humid; *Out_Temp=Temp;

return(0);

//-------error exits------------------------------------
// checksum error = 100 as per above

expire1:
     err=1; goto exit;
expire2:
     err=2;goto exit;
expire3:
     err=3; goto exit;
expire4:
     err=4;
exit:
     // something gone wrong

     return(100+err);
}

 

Last Edited: Mon. Nov 6, 2017 - 01:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So do you get the same problem using some standard, "known-good" code ... ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gechxx wrote:

goto

surprise

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

goto is not bad in itself (if you are not religious) , as an exit statement .  :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you're using that as an excuse ...

 

cheeky

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ohhh no, Im just pragmatic ;)  (had I been in ada I would have used raise ..)

 

So what "of the shelf code" would you recommend me to use  for the DHT.
 

Last Edited: Mon. Nov 6, 2017 - 02:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have a recommendation.

 

Arduino would be the obvious place to start ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The temperature sensitivity makes the internal RC Osc the #1 suspect.

 

Add the external crystal and report back!

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, but it seems to be  the temperature of the DHT rather than the M8 that seem to cause the err.

(and actually the code as it is, should cope with a shift in freq. for the m8, since its based on counting on the repsonse)

Will do, but some encouraging coffe first.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Comments:

I've seen the timing on these DHT type sensors vary a bit from the datasheet timings, so use a generous margin when checking state changes (you do seem to have some timing tolerances already).

 

You seem to use busy loops to count wait cycles, but have other code between loops which also consume time, coupled with (what seems like) assumptions on the cycle count. One alternative could be to use a timer and read the timer counter after each pin state change, this way your code in between checking pin state changes do not interfere with your time measurement (as long as your in between code doesn't exceed the shortest state change time by much).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are quite right. I have been a bit "sloppy", and feeling "well some extra instructions may possibly not hurt", to be more on deterministic/calculable side should (probably) go for timers instead

But guess what, the darn contraption has now been runnig fault free for more than 24hours, just mocking me. I dont like this kind of, as earlier stated, margin-designs, if it is one. My next will

be to first see if I can get it fail again, then to substitute the DHT for another piece, and not solder that one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, the solution seem to be found: I checked over the circuit and found that a capacitor on the 7805 power stab

wasnt well solderd. So currently it seems that things work with no problem. Would then have been disturbancies in the power supply that knocked

the DHT. Thanks for tuning in and good suggestions. 

/g

Last Edited: Thu. Nov 9, 2017 - 04:39 PM