• AVR Freaks

Hot!C Code to Interface Humidity Sensor (DHT22)

Page: < 12345 > Showing page 4 of 5
Author
mlp
boots too small
  • Total Posts : 794
  • Reward points : 0
  • Joined: 2012/09/10 15:12:07
  • Location: previously Microchip XC8 team
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/22 11:50:56 (permalink)
0
(to stop the flashy)
#61
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 02:21:00 (permalink)
0
By the way, Do you know how much the microcontroller and the general electronics is affected by low temperatures? I wanted to test the sensor inside a freezer to see if it was detecting correctly negative numbers, and I noticed that the LCD was refreshing significantly slower the display outputs

MPLAB X IDE v5.05
XC8 2.00
#62
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 02:34:03 (permalink)
+1 (1)
delfindelfinI noticed that the LCD was refreshing significantly slower the display outputs
Most likely not the MPU.


LCDs are notoriously sluggish when cold.  Basically the liquid in the display (the L part of LCD!) starts to freeze.  If you car has a LCD for the stereo or clock, check it on a cold morning.
 
I wouldn't recommend much below -10C for an LCD - you may damage it (check the manufacturers spec).  Also check your PIC datasheet for its recommended operating temperatures.
 
A better way to test for cold temperatures is to either:
a) Only put the sensor in the test environment, leave the other electronics outside
b) Get an aerosol freeze spray
#63
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 03:13:04 (permalink)
0
pcbbc

Is it perhaps only reading the sensor the first time, displaying a value, and then hanging on the second read?
Write a counter, 1, 2, 3, 4... to the screen every time you make another reading.



Yes, it is hanging on the second read. I wrote a counter that starts in 1 before the sensor reading and it only reachs 2 
post edited by delfindelfin - 2019/04/23 06:05:35

MPLAB X IDE v5.05
XC8 2.00
#64
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 03:29:48 (permalink)
0
delfindelfinYes, it is hanging on the second read. I wrote a counter that starts in 1 before the sensor reading and it only reach 2

When you have finished reading, does RC2 not need to be high again for a certain period?
i.e. before you pull low for 18ms?
Are you doing that?
Although if that is a requirement, how it works the first time I do not know.
 
Post your full (partially) working code.  I don't believe you've shown us that yet.
#65
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 06:04:16 (permalink)
0
This is it, the full (partially) working code that doesn't refresh values
 
 

MPLAB X IDE v5.05
XC8 2.00
#66
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 06:52:42 (permalink)
+1 (1)
Do you have a pullup on C2?
Or does the sensor have one internally?
It's not clear to me.
 
Also these lines:
    __delay_us(80);     // DHT22 Responds Low for 80 uS 
    __delay_us(80);     // DHT22 Responds High for 80 uS

I think you should be testing for the relavent bus transitions - not just assuming the 80us delay is accurate.
For a start i think the 20-40us at the start of the timing diagram is determined by the DHT - not you (as you have it coded currently).  There is 20us of uncertainty right there.
 
Also, with the external pullup I would think there is never any need to drive the line high?  In fact I would think doing so would cause an issue if the device is at the same time attempting to pull low, as then you have both MPU and device attempting to drive line in different directions (a short).
void Init_Humid_Sensor()
{
    TRISCbits.TRISC2 = 0;   // RC2 as Output PIN 
    PORTCbits.RC2 = 0;
    __delay_ms(18);         // RC2 Low for 18 ms   
    TRISCbits.TRISC2 = 1;   // RC2 as Input PIN
    while (PORTCbits.RC2 == 0);  // Wait until RC2 is hight again (should be near instant with pullup resistor)
    while (PORTCbits.RC2 == 1);  // Wait while high 20-40us
    while (PORTCbits.RC2 == 0);  // DHT pulls low 80us
    while (PORTCbits.RC2 == 1);  // DHT pulls high 80us
    //Next positive edge is start of first bit (26-28us = 0, 70us = 1)
}

 
Anyway, that's my take on it.  But not used one of these sensors myself.  Just reading the spec.
#67
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 07:07:51 (permalink)
0
Yes, I am using a 4.7 kOhms pull up in C2 ... Another thing I am fearing is that the sensor is not calibrated or something, because the display says 24.1 C, but it feels cooler
 
The 20-40us at the start of the timing diagram it is supposed to be determined by me. Chek the image
post edited by delfindelfin - 2019/04/23 10:01:19

Attached Image(s)


MPLAB X IDE v5.05
XC8 2.00
#68
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 10:12:32 (permalink)
+1 (1)
delfindelfinYes, I am using a 4.7 kOhms pull up in C2 ... Another thing I am fearing is that the sensor is not calibrated or something, because the display says 24.1 C, but it feels cooler

You'll need to compare against a calibrated thermometer then.
DHT22 spec seems to say temperature accuracy +- 0.5 Celsius
 
Did you try the changes I suggested?  Did they make any difference?
 
Some other observations:
a) Function BCD_ASCII_Converter is no longer used.  You can remove it.
b) //// Declaring Global Variables (Sensor Output).
It's not great coding that these are all declared global.  Really functions should have variables passed in/out, and not rely on global.  See end of post for some suggestions.
c) Data_Corruption_Bit is only ever cleared, never set (except at initialization).
What will happen if you get corrupt data after the first read?
d) char temp_high = ( temp & 65280 ) >> 8;
You are still masking with a "magic number": 65280.  As explained, 0xFF00 is more readable.
Also you are still mixing and matching char and uint8_t types. Use char for actual characters, uint8_t for all 8 bit non-character data.
e) if( (checksum == theor_checksum) && (checksum != 0) )
What if temperature and humidity are zero?  Then checksum is zero.  Why have you decided that is invalid?
But also see point c).
f) if (temp_bit_sign == 1) {
You'd normally check this thus: if (temp & 0x8000) {
Also you must mask out the top bit if it is set, or your negative decimal to BCD will be incorrect:
temp &= 0x7FFF;
g) Lcd_Set_Cursor(6,1); etc
You realise that after Lcd_Write_String (and Lcd_Write_Char) the cursor is positioned at the next character after the string (or character) written?
Therefore most of these calls are unnecessary.
 
uint8_t Read_Humid_Sensor(char* s_humid, char* s_temp)
....
    if (checksum != theor_checksum) {
        return 0;
    }
....
    s_humid[2] = '.';
    Binary_BCD_ASCIIConverter(s_humid[3], s_humid[1], s_humid[0], humid);
    s_humid[4] = 0;
 
    if(temp_bit_sign == 1){      
        s_temp[0] = '-' ;
    }else{
        s_temp[0] = ' ' ;   
    }
    s_temp[3] = '.';
    Binary_BCD_ASCIIConverter(s_temp[4], s_temp[2], s_temp[1], temp);
    s_temp[5] = 0;
....
    return 1;
}
 
char humidity[5];
char temperature[6];
....
if (Read_Humid_Sensor(humidity, temperature))
{
....
    Lcd_Write_String("Temp:");
    Lcd_Write_String(temperature);
....
    Lcd_Write_String("Humi:");
    Lcd_Write_String(humidity);
}
else
{
....
}

#69
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 10:28:26 (permalink)
0
So, do I change all of these to char
 

 
 
 
uint8_t Humid_Decim;
 
 
 
uint8_t Humid_Ones;
uint8_t Humid_Tens;

uint8_t Temp_Decim;
uint8_t Temp_Ones;
uint8_t Temp_Tens;
 
 
 

 
Because they are actually characters
 
What will happen if you get corrupt data after the first read?
 
It will display the messege of "bad signal", and if at the second read is not corrupted it will display normally, altough I guess somehow you have to clear the display
 
I added your code
 
void Init_Humid_Sensor()
{
    TRISCbits.TRISC2 = 0;   // RC2 as Output PIN 
    PORTCbits.RC2 = 0;
    __delay_ms(18);         // RC2 Low for 18 ms   
    TRISCbits.TRISC2 = 1;   // RC2 as Input PIN
    while (PORTCbits.RC2 == 0);  // Wait until RC2 is hight again (should be near instant with pullup resistor)
    while (PORTCbits.RC2 == 1);  // Wait while high 20-40us
    while (PORTCbits.RC2 == 0);  // DHT pulls low 80us
    while (PORTCbits.RC2 == 1);  // DHT pulls high 80us
    //Next positive edge is start of first bit (26-28us = 0, 70us = 1)
}

 
And it is doing the same thing, altough I don't understand really well why
 
Why have you decided Checksum= 0 is invalid?
I was thinking in the case the sensor is not connected and the MCU reads zero in C2, but now that I think about it, is not going to be zero, is going to be floating
post edited by delfindelfin - 2019/04/23 10:48:20

MPLAB X IDE v5.05
XC8 2.00
#70
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 15:07:42 (permalink)
+1 (1)
Yes. Those variables contain characters, so should ideally be char type.

It will display the messege of "bad signal", and if at the second read is not corrupted it will display normally, altough I guess somehow you have to clear the display.

No, that’s what you think will happen. Actually it will display nonsense readings and never go in the bit of code you want it to after the first good reading.
You start off with: Data_Corruption_Bit = 1, which is set by the compiler on startup of your program
Then, if you get a good checksum you set Data_Corruption_Bit = 0
Q: How does it get set back to 1?
A: It never does - unless you power off and back on again. That’s because you don’t have any code to set it back to 1 anywhere.

The datasheet is not well written. You need to know how the bus works electrically.

As an input the device is high impedance. That means it acts like a high value resistor and draws very little current. A digital input like this has no way to tell the difference between having +V connected directly to it, and a pull-up resistor connected to +V. There is just +V on the input and that is all it can tell.

As outputs the device uses an open collector. Electrically it is an NPN transistor with the emitter connected to ground and the collector as the output. That means it can only ever drive the bus low; it cannot put a high value on the bus directly. To get a high value it just does not drive the output transistor, and relies on the pull-up to put the +V on the bus. Of course nothing else on the bus should be driving it low, or that device will “win out” over the pull-up resistor.

Unless you do it this way on a bi-directional bus there is the possibility one device is driving low and the other is driving high (like you were doing) at the same time. When this happens you have a short between ground and +V. I shouldn’t need to explain why that is bad.

So the MPU needs to act exactly as the device does. Only ever drive bus low, and to get a high just do not drive the output pin at all (set it as in input). Then it would float, but you have the pull-up to ensure that doesn’t happen and it is at +V instead.

I was thinking in the case the sensor is not connected and the MCU reads zero in C2, but now that I think about it, is not going to be zero, is going to be floating

It’s not going to be floating, it’s going to be high because of the pull-up. Unless I suppose you disconnect the pull-up as well?
And it’s not going to read anything because the reading code relies on edges, and if there are no edges it won’t even get that far.
This is why you should be checking for timeouts and not just expecting to read every message correctly every time.

You should probably put the pull-up on your main board, and check for the sensor pulling the line low to decide if it is connected or not: Bus not pulled low after 50us, assume device is not connected.

This datasheet says:
See below figure for overall communication process, the interval of whole process must beyond 2 seconds.

Not sure what that means? It’s not good English. Maybe you should only read a value every 2 seconds or more?
Have you tried longer waits between reads?
#71
1and0
Access is Denied
  • Total Posts : 9612
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 17:01:55 (permalink)
+1 (1)
pcbbc
Unless you do it this way on a bi-directional bus there is the possibility one device is driving low and the other is driving high (like you were doing) at the same time. When this happens you have a short between ground and +V. I shouldn’t need to explain why that is bad.

In such situation, I usually use a series resistor of 470 to 1K ohm.
 

See below figure for overall communication process, the interval of whole process must beyond 2 seconds.

Not sure what that means? It’s not good English. Maybe you should only read a value every 2 seconds or more?
Have you tried longer waits between reads?

According to this the DHT22 has a sampling rate of 0.5 Hz, i.e. one reading every two seconds.
#72
1and0
Access is Denied
  • Total Posts : 9612
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 17:06:50 (permalink)
+1 (1)
Not going to edit my previous post as there is a link, so ...
 
Looking at the "electrical connection diagram" in the datasheet linked by pcbbc, I am guessing the sensor probably has a series resistor built-in already in the data pin. ;)
 
Edit:
 
Quoted from same datasheet:
 
"Data-bus's free status is high voltage level. When communication between MCU and AM2302 begins, MCU will pull low data-bus and this process must beyond at least 1~10ms to ensure AM2302 could detect MCU's signal, then MCU will pulls up and wait 20-40us for AM2302's response.
 
When AM2302 detect the start signal, AM2302 will pull low the bus 80us as response signal, then AM2302 pulls up 80us for preparation to send data."
 
 
post edited by 1and0 - 2019/04/23 17:12:57
#73
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/23 22:41:20 (permalink)
+1 (1)
Yes, I saw all that. Unfortunately we are just guessing, and also guessing how big a series resistor that is (if it even exists beyond the on impredence of the output driver). Safer to assume there isn’t one, and either supply our own (as you suggest) or not use one at all and never pull the line high (just use external pull-up).

The English in the datasheet is not particularly good, and it doesn’t give us a block diagram of the internals of the sensor. And no mention of any bus voltages beyond GND and Vcc. There should be an intermediate voltage during the 20-40us when the host is (supposedly meant to be) pulling up at the same time as the device is pulling down. I’m taking the datasheet entirely with a pinch of salt.

If you look at other one wire devices you’ll see they are implemented as open collector. Well, open drain actually as it’s usually a MOSFET driving the data line. So at least from their end they are not capable of “<insert device here> pulls up” the data bus. And yes, I do see the bit where it says “our 1 wire bus is specially designed and different from the Maxim/Dallas 1 wire bus and so incompatible with Dallas 1 wire bus”. Unfortunately it doesn’t tell us how it is special, different or incompatible.

As delfindelfin has already demonstrated the device works with just the pull-up and so the “MCU will pulls up” step is not needed. Unfortunately OP still does not appear to be able to get device to work beyond first sensor reading. That part is still a mystery.
#74
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 01:19:15 (permalink)
0
What is this?:
 

 
nRBPU = 0;    //Enable PORTB internal pull up resistor
 

 
Do I have to enable that?

MPLAB X IDE v5.05
XC8 2.00
#75
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 01:47:44 (permalink)
+1 (1)
delfindelfinWhat is this?:

nRBPU = 0;    //Enable PORTB internal pull up resistor

It configures (or in this case un-configures) weak internal pullups on port B inputs.
 
delfindelfinDo I have to enable that?

Depends on what do you have configured on PORTB?
Your sensor is on PORTC, so it isn't going to help with that.
 
But if you switch the sensor to PORTB, then you could probably remove the external pull-up resistor and use the internal one instead.
It's not going to "help" with anything though, other than eliminating one external component.
#76
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 02:50:47 (permalink)
0
PORTC doesn't have internal Pull-Ups resistors?

MPLAB X IDE v5.05
XC8 2.00
#77
pcbbc
Super Member
  • Total Posts : 1250
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 03:09:34 (permalink)
+3 (3)
delfindelfinPORTC doesn't have internal Pull-Ups resistors?
Do you see it in the datasheet?


#78
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 04:13:45 (permalink)
+2 (2)
delfindelfin
PORTC doesn't have internal Pull-Ups resistors?

Really. Stop being so lazy and read the datasheet for yourself. That's where we all look to answer your questions!
 

Nearly there...
#79
1and0
Access is Denied
  • Total Posts : 9612
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/24 07:20:41 (permalink)
+1 (1)
pcbbc
Yes, I saw all that. Unfortunately we are just guessing, and also guessing how big a series resistor that is (if it even exists beyond the on impredence of the output driver). Safer to assume there isn’t one, and either supply our own (as you suggest) or not use one at all and never pull the line high (just use external pull-up).

Agreed.  During prototype stage, I'd use a series resistor.  Also, use an external pull-up but clear RC2 before setting the pin to output:

PORTCbits.RC2 = 0;
TRISCbits.TRISC2 = 0; // RC2 as Output PIN

and then tri-state the pin (as input) instead of outputting a high.


As delfindelfin has already demonstrated the device works with just the pull-up and so the “MCU will pulls up” step is not needed. Unfortunately OP still does not appear to be able to get device to work beyond first sensor reading. That part is still a mystery.

I would wait at least two seconds between readings of the sensor.
#80
Page: < 12345 > Showing page 4 of 5
Jump to:
© 2019 APG vNext Commercial Version 4.5