DHT22 running @ 8MHZ

Hello everyone, I'm trying to build the external part of a weather station, and I'm using a DHT22 as humidity and temperature sensor. I have a barebone atmega328p-pu running on a breadboard at 8 mhz. Everything's work fine, except for the DHT22. I think that the problem is related to the lower working frequency: I tried these two libraries without success :~

https://github.com/adafruit/DHT-sensor-library

https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib

For the first one I used the special constructor DHT dht(4, DHT22, 3);

Any help would be appreciated!

Thanks!

remarkable, an attiny @8Mhz is confirmed to work.

do you have the appropriate pull up resistor in place?

Is there more connected to your board?

Does my lib return an error code? if so which one?

which code do you use? what output does it generate?

what power supply are you useing? can you post a schematic?

lots of questions otherwise unable to reproduce your problem.

Does the sensor work at 16 MHZ

I use the library from the playground, that might be the same robtillaart version. Running at 8MHz is not problem for me. But interrupts messes up the timing. With a lot of interrupts (like I2C interrupts) I need to request data a number of times until I get my data.

I have this with DHT22 and DS18B20, I don't know how I fixed it for which one. I can look into it if you want.

The humidity of the DHT22 is not very accurate. I don't use them anymore.

check - http://forum.arduino.cc/index.php?topic=97915.0 -

Thanks Peter and Rob for your answers! I have the pulp resistor, and the library returns the checksum error. Maybe the error is that my code has the I2C interrupt (one every 8 seconds)! How did you fix this problem Peter? As soon as possible I will answer the other questions!

You do I2C only once per 8 seconds, that is very little. Perhaps there is another problem, like long cables that get a lot of electric noise. My I2C is sometimes more than 20 times a second, and also other interrupts.

I have to check my other computer to see how I fixed it.

efrem: Thanks Peter and Rob for your answers! I have the pulp resistor, and the library returns the checksum error. Maybe the error is that my code has the I2C interrupt (one every 8 seconds)! How did you fix this problem Peter? As soon as possible I will answer the other questions!

if you ignore the checksum error and just print the values of temperature an humidity, do they make sense? or partial?

Ok, I simplified the schematic. Now I have only my atmega328 on my arduino board (so I can check the logs) [u]running at 8mhz[/u] and the DHT22 sensor. I uploaded the example sketch. The sensor is powered by the 3,3V of the arduino board and has a 10K resistor from 3,3V to the data pin. It does not work.

So, with the same configuration, I flashed the [u]16 mhz bootloader[/u] again and it works!

Maybe the problem is with the bootloader/fuses? :~

robtillaart:

efrem: Thanks Peter and Rob for your answers! I have the pulp resistor, and the library returns the checksum error. Maybe the error is that my code has the I2C interrupt (one every 8 seconds)! How did you fix this problem Peter? As soon as possible I will answer the other questions!

if you ignore the checksum error and just print the values of temperature an humidity, do they make sense? or partial?

The output is always zero (both temperature and humidity)...

strange .... that means all bits clock in OK and are all zero except for the CRC....

I have a 8MHz 5V Arduino compatible, but it still has the DHT11 and also the DS18B20 on the same module. Every checksum is tested, and the DS18B20 is tried 30 times and the DHT11 15 times. The interrupts are not disabled during that. At the end it still could be wrong, but then I return an error, which is solved at a higher level.

Your problem has not to with the interrupts, but with the 3.3V. Google for : dht22 zeros 3.3v It seems that at 3.3V the DHT22 is sometimes okay, and sometimes not. Some are able to solve it with a higher voltage to the Vcc of the DHT22 (but the pullup resistor still to 3.3V), others add an extra long delay or use another library.

For example this : http://forums.adafruit.com/viewtopic.php?f=19&t=33071#p180961 refers to this : https://github.com/ringerc/Arduino-DHT22

Something I’ve seen mentioned is to wait a couple of seconds after it powers up before asking it for anything.

I’ve got a weather station with one of these, a BMP180 a nRF24L01+ radio and Sparkfun weather sensors all running off an Arduino Pro Mini @ 3.3v and 8Mhz without issue. I’m actually powering it down after reading it, when I want to read it again I power it up and wait for 2 seconds then read it using Rob’s library

I had a dht11 that was misbehaving. I opened the library files and noticed that they actually use delay for some of the timing aspects.

Since delay doesn't work during an interrupt routine, I took my call out of the interrupt service routine and instead, called it manually from within my loop function (using millis() to decide when to call it).

It sorted the problem for me.

Hey guys! Good news eventually :P

I tried another lib, this one https://github.com/markruys/arduino-DHT without success. So I opened the DHT.cpp file and I started to have fun with this library: in the main reading loop I just changed this

// A zero max 30 usecs, a one at least 68 usecs.
      if ( age > 30 ) {
        data |= 1; // we got a one
      }

to this:

// A zero max 30 usecs, a one at least 68 usecs.
      if ( age > 15 ) {
        data |= 1; // we got a one
      }

and it worked!!! :astonished:

Working SW is always good news.

however if I look at the solution it implies that somewhere the timing has changed by a factor 2
(side effect of going from 16MHz to 8MHz)

Can you confirm this effect also in the other DHT libs? Adafruit & mine?

update:
in my DHT lib these lines

        if ((micros() - t) > 40) // should be 20 ?  can you try?
        { 
            bits[idx] |= mask;
        }

robtillaart: Working SW is always good news.

however if I look at the solution it implies that somewhere the timing has changed by a factor 2 (side effect of going from 16MHz to 8MHz)

Can you confirm this effect also in the other DHT libs? Adafruit & mine?

update: in my DHT lib these lines

        if ((micros() - t) > 40) // should be 20 ?  can you try?
        { 
            bits[idx] |= mask;
        }

YEs, It works!!! How is possible? It seems that the DHT22 writes data twice faster that it should do... Or maybe something wrong while flashing the bootloader?

can you run this simple sketch

uint32_t last = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("start");
}

void loop()
{
  if (millis() - last >= 1000)
  { 
    Serial.print(millis());
    Serial.print("\t");
    Serial.println(micros());
    last = millis();
   }
}

it should dump millis and micros about once per second (you should count 21 22 23 to check you know)

if somewhere clocks run wrong the output should show it...

robtillaart: can you run this simple sketch

uint32_t last = 0;

void setup() {   Serial.begin(9600);   Serial.println("start"); }

void loop() {   if (millis() - last >= 1000)   {     Serial.print(millis());     Serial.print("\t");     Serial.println(micros());     last = millis();    } }




it should dump millis and micros about once per second (you should count 21 22 23 to check you know)

if somewhere clocks run wrong the output should show it...

The output is updated every two seconds :0 :~ So no problem with the libs... it's just my atmega! I guess that the atmega it's convinced that the clock is 16 mhz, so each timing function needs twice the time...

(so the good news is the libs are right ;)

does the Serial 9600 baud work as expected?

I think there are two reasons to default " checksum error".

first : digitalRead() is too slow second : millis() function is also too slow.

Perhaps you could replace digitalRead by digitalReadFast. I try it but I do'nt succeeded in make it work To avoid CheksumError I use direct port register , it works fine, but I lose the flexibility of Arduino pin naming.

You can remove millis(). It is absolutely not an obligation to know the time of the 0 or of 1. All you need is to have an representative image of the length of the 0 and 1 And this image is soon in the actual code :

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

loopCnt is the searched image

My proposal (it is that I use for my project): Two vars: loopCnt0 and loopCnt1 and the code with small modification : Exemple for the "1" loop :

loopCnt = 0;
    while(digitalRead(pin) == HIGH)
    {
        if (loopCnt1++ ==DHTLIB_TIMEOUT ) return DHTLIB_ERROR_TIMEOUT;
    }

To determine if "one" is longer or shorter than the "0" just compare if the value of loopCn1 is higher or lower that this of loopCnt0 millis () is no longer necessary.

Other possible improvement : Latest AOSONG datasheet says (a least for AM2302/DHT22) that the time "tgo" is comprise between 20µ and 200µs with a mean of 30µs. In actual library there is a fixed delay of 40 µs --> if you have a sample which have a tgo = 100µs even if it is in his spec, library will [u]always[/u] deliver a TIMOUT. For my use I change this fixed delay by a while loop which will detects the first transition to 0 corresponding to bit 0 of acknowledge