• AVR Freaks

Hot!C Code to Interface Humidity Sensor (DHT22)

Page: < 12345 > Showing page 2 of 5
Author
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 03:22:11 (permalink)
0
I was thinking, probably there is no need to use interrupts nor to poll, I could use the checksum sended by the sensor. With that I can know if the sensor is connected and working properly. I have a question, tough. In the image I uploaded in post #6 it says that the firts 8 bits are the Integral part of Relative Humidity, and the second 8 bits are the decimal part, but ... In the proteus simulation I set the Relative Humidity in the sensor as 80.1, and the consequent Relative Humidity signal sended is: 0000001100100001, converting all that binary number in decimal is equal to 801, and only have to divide between 10 to obtain 80.1, so, the image in post #6 is wrong, isn't it? If I were to take the 8 first bits as the integral part (00000011) it would be 3, wich make no sense
post edited by delfindelfin - 2019/04/19 03:55:16

MPLAB X IDE v5.05
XC8 2.00
#21
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 03:53:00 (permalink)
0
Probably something like this:
 

 
 
 
 
 
 
 
char tr_bit = 0;
 
char humid_high = ( humid & 65280 ) >> 8 ; // ( HHHHHHHH LLLLLLLL & 11111111 00000000 ) >> = HHHHHHHH
char humid_low = humid & 255 ; // ( HHHHHHHH LLLLLLLL & 00000000 11111111 ) = LLLLLLLL
char temp_high = ( temp & 65280 ) >> 8;
char temp_low = temp & 255 ;
 


char theor_checksum = humid_high + humid_low + temp_high + temp_low ; // Computing Theoretical Checksum

if( (checksum == theor_checksum) && (checksum != 0) )
{
tr_bit = 1;
}
 
 
 
 
 
 
 

post edited by delfindelfin - 2019/04/19 04:16:05

MPLAB X IDE v5.05
XC8 2.00
#22
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 04:03:10 (permalink)
0
Altough, now that I think about it, probably I have to do something for the cases that the code waits RC2 to be High or Low and never detects it. Probably a Timer Interrupt or that Polling technique after 4.8 ms that is the maximum time that the sensor's signal could take. 
 
By the way, how do I convert properly the shor int type of humid and temp to floating points to show decimal parts?
 

float f_temp = temp / 10.0f;
float f_humid = humid / 10.0f;
 

post edited by delfindelfin - 2019/04/19 04:24:50

MPLAB X IDE v5.05
XC8 2.00
#23
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/19 04:22:45 (permalink)
0
delfindelfin
...
Probably a Timer Interrupt or that Polling technique after 4.8 ms that is the maximum time that the sensor's signal could take

This is precisely what I was talking about at the end of post#13

Nearly there...
#24
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 04:29:40 (permalink)
0
qhb
 
This is precisely what I was talking about at the end of post#13




Sorry, I am slow learner, Could you help me with the other intricacies of the code? The correct way to convert short int to floating point. I think floating point takes much space (4 Bytes), is there another way to use numbers with decimal point?

MPLAB X IDE v5.05
XC8 2.00
#25
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 04:30:32 (permalink)
+1 (1)
Yes, the simulator does not seem right according to the spec. I read the spec, as you did, that there should be 2 bytes with implied decimal point. So the sencond byte is in units of 1/256. Do not assume that the proteus simulator is correct. Most likely is the datasheet is correct, and simulation is wrong.

Write your masks in hex 65280 = 0xFF00 and 255 = 0x00FF.
It makes no difference to your code, but it is a lot easier for us to read. I. Really have no idea if 65280 is the correct mask for the high byte or not, because I never see it written that way. 0xFF00 I know is correct just by looking.

Checksum should be checked but yes, you also need to cope with if there is no reply from the sensor or bits are missed, etc. Set the timer so it times out after at least 4.8ms, then poll the timer flag in your loops and give up and get out of the function with an error if it set.
#26
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/19 04:32:37 (permalink)
0
The easiest way is to just stick with integers, and treat every number in terms of 1/100 if you want two decimal places.
It's only right at the end, where you want to display the number, that you need to insert the "."
 

Nearly there...
#27
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 04:50:55 (permalink)
+1 (1)
delfindelfinSorry, I am slow learner, Could you help me with the other intricacies of the code? The correct way to convert short int to floating point. I think floating point takes much space (4 Bytes), is there another way to use numbers with decimal point?
It’s not so much the space for storing the numbers, it’s the amount of library code required to manipulate them on an 8 bit processor with no floating point hardware support. Also this is very slow.
But in your application just for printing out you should not have a problem with floats.

The other option with fixed decimals, is print the first byte as a number.
Then print a decimal point.
Then print the second number multiplied by 100 and right shifted by 8 bits. Shifting right is a very fast divide by power of 2. Eight shifts are therefore divide by 256, and so you have effectively done n = n * 100 / 256.
This will convert your 0 to 255 fractional part to an integer number in the range 0 to 99 instead.
Make sure you print numbers less than 10 with a leading zero, otherwise 2.01 gets displayed as 2.1
post edited by pcbbc - 2019/04/19 04:55:59
#28
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 05:21:51 (permalink)
0
pcbbc
It’s not so much the space for storing the numbers, it’s the amount of library code required to manipulate them on an 8 bit processor with no floating point hardware support. 




Are there any PICs with floating point hardware support?
post edited by delfindelfin - 2019/04/19 06:56:46

MPLAB X IDE v5.05
XC8 2.00
#29
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 05:32:48 (permalink)
0
Any recommendations of how to use this:
 

 
unsigned char buffer_temp[6];
sprintf(buffer_temp, "%.0f", f_temp ); // Convert temperature to string

Lcd_Write_String(buffer_temp);
 

 
To convert the Float Temperature to String to display it on the LCD
 

MPLAB X IDE v5.05
XC8 2.00
#30
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 06:26:16 (permalink)
+1 (1)
delfindelfinAre there PICs with floating point hardware support?
No. I’m just pointing out you don’t have any of the features people have become used to on more advanced CPUs.

About the closest you get is some integer multiply support.

To use that code first you must calculate f_temp from the value you have read, coverted to float and divide by 256.0
#31
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 08:22:56 (permalink)
0
But if I want to do it with the first method. I have the next error:
 
:0:: error: (1347) can't find 0x48 words (0x48 withtotal) for psect "text25" in class "CODE" (largest unused contiguous range 0x27)

MPLAB X IDE v5.05
XC8 2.00
#32
jack@kksound
code tags!
  • Total Posts : 3201
  • Reward points : 0
  • Joined: 2014/05/14 10:03:19
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/19 08:59:32 (permalink)
+1 (1)
delfindelfin
But if I want to do it with the first method. I have the next error:
 
:0:: error: (1347) can't find 0x48 words (0x48 withtotal) for psect "text25" in class "CODE" (largest unused contiguous range 0x27)


delfindelfin
But if I want to do it with the first method. I have the next error:
 
:0:: error: (1347) can't find 0x48 words (0x48 withtotal) for psect "text25" in class "CODE" (largest unused contiguous range 0x27)


If by "first method" you mean the sprintf() function approach then you have not paid attention. The printf() family of functions can take up huge amounts of program memory, especially when floating point values are used. Your error message says you have run out of memory in the program FLASH ROM.


#33
1and0
Access is Denied
  • Total Posts : 9464
  • 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/19 10:06:31 (permalink)
+1 (1)
The two data bytes are shown as integral and decimal bytes, but from what I briefly read online, the 16-bit data for humidity is in unit of 1/10, and the 16-bit data for temperature is also in unit of 1/10 but with the most significant bit as the sign bit.
 
So, simply convert the 16-bit binary data to BCD and display it with one decimal place.  There's no need for floating point math or printf(). ;)
 
#34
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 02:03:22 (permalink)
0
Could you help me with the Double Dabble Algorithm to Convert Binary to Natural BCD?
 

char Binary = 125; // 01111101

char Hundreds = 0; // 00000000
char Tens = 0; // 00000000
char Ones = 0; // 00000000

char i;
char mask;

for(i=0; i<8; i++){

if(Hundreds >= 5){
Hundreds += 3;
}
if(Tens >= 5){
Tens += 3;
}
if(Ones >= 5){
Ones += 3;
}


Hundreds <<= 1;
mask = (Tens & 0x08) >> 3; // ( xttt & 1000 = x000 ) >> 3 = 000x

if(mask ==1){

Hundreds |= 1 ; // hhhh | 0001 = hhh1
}
else{
// hhhh = hhh0
}

Tens <<= 1;
mask = (Ones & 0x08) >> 3; // ( xttt & 1000 = x000 ) >> 3 = 000x

if(mask ==1){

Tens |= 1 ; // hhhh | 0001 = hhh1
}
else{
// hhhh = hhh0
}

Ones <<= 1;
mask = (Binary & 0xFF) >> 7; // ( xttt & 1000 = x000 ) >> 3 = 000x

if(mask ==1){
Ones |= 1 ; // hhhh | 0001 = hhh1
}
else{
// hhhh << 1 = hhh0
}

Binary <<= 1;

}
 

 
I don't know how to apply the correct masks to perform this operation: // hhhh Bitwise-Operator 0000 = hhh0
post edited by delfindelfin - 2019/04/20 03:03:25

MPLAB X IDE v5.05
XC8 2.00
#35
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 03:18:06 (permalink)
+1 (1)
If it helps, here's what I use for my double-dabble:
typedef union {
    uint16_t value16;
    uint24_t value24;
    struct {
        uint8_t lo;
        uint8_t hi;
        uint8_t digit;
    };
} DD;

DD dd;

char double_dabble(uint8_t div)
{
    dd.digit = 0;
    uint8_t bits = 16;
    do
    {
        dd.value24 <<= 1;
        if (dd.digit >= div)
        {
            dd.digit -= div;
            dd.lo |= 1;
        }
    } while (--bits);
    return dd.digit + 0x30;
}

void main()
{
    dd.value16 = 1234;
    char ones = double_dabble(10);
    char tens = double_dabble(10);
    char hund = double_dabble(10);
}

 
It's a bit different from the standard algorithm, for a number of reasons:
1. The function is optimised to compile to some very compact PIC code.
2. It is designed to be able to return just the number of digits you need.
3. It can also convert from other bases, or mixes of them.  For example, say your value is encoded in seconds:
dd.value = 5025;
char sec_ones = double_dabble(10);
char sec_tens = double_dabble(6);
char min_ones = double_dabble(10);
char min_tens = double_dabble(6);
char hrs_ones = double_dabble(10);
Gives you the digits 1:23:45
#36
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 03:42:26 (permalink)
+1 (1)
Or doing it your way:
uint8_t Binary = 125;
 
char Hundreds = 0;
char Tens = 0;
char Ones = 0;
 
uint8_t i;
 
for(i=0; i<8; i++) {
    if (Hundreds >= 5) {
        Hundreds += 3;
    }
    if (Tens >= 5) {
        Tens += 3;
    }
    if (Ones >= 5) {
        Ones += 3;
    }
    Hundreds <<= 1;
    if (Tens & 0x08) {
        Hundreds |= 1;
    }
    Tens <<= 1;
    if (Ones & 0x08) {
        Tens |= 1;
    }
 
    Tens &= 0xF;
    Ones <<= 1;
    if (Binary & 0x80) {
        Ones |= 1;
    }
 
    Ones &= 0xF;
    Binary <<= 1;
}

 
Edit - Or more compactly:
uint8_t Binary = 125;
 
char Hundreds = 0;
char Tens = 0;
char Ones = 0;
 
uint8_t i;
 
for(i=0; i<8; i++) {
    Ones <<= 1;
    Tens <<= 1;
    Hundreds <<= 1;
    if (Binary & 0x80) {
        Ones++;
    }
    if (Ones >= 10) {
        Ones -= 10;
        Tens++;
    }
    if (Tens >= 10) {
        Tens -= 10;
        Hundreds++;
    }
    Binary <<= 1;
}

post edited by pcbbc - 2019/04/20 04:30:08
#37
delfindelfin
Super Member
  • Total Posts : 374
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 11:32:22 (permalink)
0
How did you came up with the more compactly version? it is another algorithm 

MPLAB X IDE v5.05
XC8 2.00
#38
pcbbc
Super Member
  • Total Posts : 1188
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 13:22:34 (permalink)
+2 (2)
delfindelfinHow did you came up with the more compactly version? it is another algorithm 
No, same basic algorithm. Came up with it by understanding it!


Here’s what I think happened....

Somewhere in the mists of time, double dabble was adapted to work with packed BCD. There you only have 4 bits per digit. In that case it is important that no single digit ever exceeds 15, or it will overflow. So, to account for that, the “dabble” is moved to before the “double”, and some clever arithmetic done to make it work and ensure all digits remain in the range 0-15 while being “double dabbled”, and also to automatically propagate carries between 4-bit nibbles.

This is a perfectly valid approach if you are working with a 4-bit ALU CPU (a lot of early calculator implementations, for example), or are packing BCD as 2 digits per byte on an 8-bit CPU.

Unfortunately it also significantly complicates things if you are working with unpacked BCD. In that case you can do the simpler, and also I think easier to understand, version that I gave. Here, when we “double” digits, they can temporarily be in the range 0-19 because we have the whole 8 bit byte to work with (not just 4 bits). Then we adjust them back to 0-9 with the “dabble” and propagate the carry by adding 1 to the next digit.

Also note that unpacked it is now correctly “double” and then “dabble”! The versions that are usually described are the packed version, which require “dabble” then “double” for the reasons I gave. But then they also require lots of other unnecessary stuff when you then decide you are working unpacked. Because lots of the stuff they do (comparing with 5 instead of 10, and adding 3 instead of subtracting 10 and carrying 1) are there explicitly to deal with the packed requirement.

Regrettably most of the explainations I see describe the packed algorithm, but then go on to give C code implementations using unpacked. That means they have a lot of extra “bloat” in them, which only serves to further obviscate what is really going on!
#39
Mysil
Super Member
  • Total Posts : 3326
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/20 14:16:33 (permalink)
0
Hi,
You are right that the second algorithm in message #37 is not double dabble algorithm.
 
There is a long thread some time ago investigating different algorithms for binary to decimal conversion:
https://www.microchip.com/forums/FindPost/854819
The thread is mostly concentrated on 16 bit binary to decimal conversion,
and is mostly coded in asseembly.
There was double dabble algorithm tried, but there are other methods more efficient.
On PIC16 processors, binary search and subtraction was found to be most efficient.
On PIC18 and other processors that have hardware multiplication, it is more efficient to use multiplication scaling.
 
The simplest algorithm to program in C, is to subtract 100 until the value is not positive,
then subtract 10 repeatedly, until the value is no longer positive.
 
Attached is my wrapping of code for several different PIC devices.
Some of the alternatives are assembly code wrapped in a C function.
See also:
https://www.microchip.com/forums/FindPost/1055315
 
    Mysil
post edited by Mysil - 2019/04/20 14:45:49
#40
Page: < 12345 > Showing page 2 of 5
Jump to:
© 2019 APG vNext Commercial Version 4.5