• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes
• AVR Freaks

### Hot!C Code to Interface Humidity Sensor (DHT22)

Page: < 12345 > Showing page 3 of 5
Author
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/20 17:06:41 (permalink)
0
MysilHi, You are right that the second algorithm in message #37 is not double dabble algorithm.
It’s not exactly what is classically described, no. But I’m convinced my unpacked implementation is where double dabble originated from. It esentially works the same, but it just it does the dabble after the double, not before.

At some point double dabble was modified for efficient implementation in packed BCD. That was the point the dabble operation moved to before the double. There’s no reason to do it that way if you are working unpacked, and in fact it quite significantly complicates things if you do, for no additional gain.

Unfortunately most implementations describe the packed form, but then implement it in C for unpacked. That leads to some unnecessary complex code.
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/20 18:40:03 (permalink)
0
pcbbc
It’s not exactly what is classically described, no. But I’m convinced my unpacked implementation is where double dabble originated from. It esentially works the same, but it just it does the dabble after the double, not before.

https://en.wikipedia.org/wiki/Double_dabble#Historical

"Historical

In the 1960s, the term double dabble was also used for a different mental algorithm, used by programmers to convert a binary number to decimal. It is performed by reading the binary number from left to right, doubling if the next bit is zero, and doubling and adding one if the next bit is one.[5] In the example above, 11110011, the thought process would be: "one, three, seven, fifteen, thirty, sixty, one hundred twenty-one, two hundred forty-three", ..."
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/20 22:14:11 (permalink)
0
Any suggestions of how to convert Natural BCD to ASCII? I was thinking in just adding 48 to the BCD Bytes

` uint8_t BCD_ASCII_Converter( uint8_t BCD ){ uint8_t ascii; ascii = BCD + 48;  return ascii;} `

post edited by delfindelfin - 2019/04/20 22:33:58

MPLAB X IDE v5.05
XC8 2.00
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/20 23:29:44 (permalink)
+2 (2)
delfindelfin
Any suggestions of how to convert Natural BCD to ASCII? I was thinking in just adding 48 to the BCD Bytes
`uint8_t BCD_ASCII_Converter( uint8_t BCD ){uint8_t ascii;ascii = BCD + 48;  return ascii;}`

No need for a function but if you like ...
`char BCD_ASCII_Converter( uint8_t BCD ){    return BCD + '0';}`

Edit: The return type should be char for an ASCII character; uint8_t is for an 8-bit integer.  Use '0' for better readability than 48 or 0x30.

post edited by 1and0 - 2019/04/20 23:40:01
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/20 23:33:10 (permalink)
0
... or
`#define BCDToAscii(x) ((x) + '0')`

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/21 03:35:38 (permalink)
+1 (1)
1and0Historical In the 1960s, the term double dabble was also used for a different mental algorithm, used by programmers to convert a binary number to decimal. It is performed by reading the binary number from left to right, doubling if the next bit is zero, and doubling and adding one if the next bit is one. In the example above, 11110011, the thought process would be: "one, three, seven, fifteen, thirty, sixty, one hundred twenty-one, two hundred forty-three", ..."

Yes. I’m not sure about “different” though. ;) At their hearts they both involve doubling the decimal number, then adding one if the next binary digit is one. All the above is is just a natural language description of how a human would do it.

When you boil it down the differences are:

a) How the number is doubled. You can either:
Packed: Fix up decimal digits which are greater than or equal to five, and shift left by one. With this method the shift “automatically” propagates the carries to the next nibble, which is convenient.
Unpacked: Multiply all the decimal digits by 2. Then subtract 10 and manually carry for any digit greater than 9. That’s what I do mentally, and it’s what my second implementation does.
Either way it results in a doubling of the decimal number at this step of the algorithm.

b) How you perform the add one step. You can either:
a) Shift all the packed decimal digits and the binary number in the shift step. The next binary digit is automatically added “for free” by virtue of the carry shift in. Usually this needs assembler, as cross-variable shifts with carry propagation are tricky in C.
b) Check the next bit of the binary number and, if it is 1, add 1 to the decimal number. This is more what a human would do, and also what we usually code in C (as a workaround not having direct access to the carry flag).
Either way it’s “add one if the next bit is one”.

It’s like saying the algorithm to “calculate an average of two numbers” is “add both numbers and divide by two”. And then claiming:
`unsigned int avg = (a + b) / 2;`

Is a different algorithm from:
`unsigned int avg = (a + b) >> 1;`

Clearly these are just different implementations of the same “average” algorithm.

If you still don’t agree, then observe that either “double dabble” implementation involves iterating over all the bits in the binary number exactly once. And that after each step, the BCD number (packed or unpacked) is doubled and has one added if the binary digit was one.
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/21 08:22:35 (permalink)
+1 (1)
Agreed, one implementation is "dabble double" while the other one is "double dabble". ;)

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/21 13:34:22 (permalink)
0
I am not able to detect when RC2 is equal to 0, it doesn't matter where I place that line of code

`   void Init_Humid_Sensor(){ TRISCbits.TRISC2 = 0; // RC2 as Output PIN  PORTCbits.RC2 = 0; __delay_ms(18); // RC2 Low for 18 ms  PORTCbits.RC2 = 1; __delay_us(30); // RC2 High for 30 us    TRISCbits.TRISC2 = 1; // RC2 as Input PIN  while (PORTCbits.RC2 != 0); // Wait until RC2 is Low   }   `

It is so strange, if the sensor were sending the 80 uS Low Response Signal I shouldn't be stuck in the infinite loop where RC2 is never Low

MPLAB X IDE v5.05
XC8 2.00
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/21 21:51:36 (permalink)
0
delfindelfin
I am not able to detect when RC2 is equal to 0, it doesn't matter where I place that line of code
`PORTCbits.RC2 = 0;__delay_ms(18); // RC2 Low for 18 ms`

It is so strange, if the sensor were sending the 80 uS Low Response Signal I shouldn't be stuck in the infinite loop where RC2 is never Low

One datasheet I read that the host should pull the data bus low for at least 18 ms AND at least 500 us, and another datasheet states 1~10 ms; so maybe try 2 ms.?!
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/22 02:22:43 (permalink)
0
I think Proteus is simulating the version that pulls tha data bus low for at least 18 ms. The funny thing is that in the real life, it doesn't have that problem, yet the sensor reading is incorrect
post edited by delfindelfin - 2019/04/22 05:26:51

MPLAB X IDE v5.05
XC8 2.00
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/22 05:38:40 (permalink)
+1 (1)
delfindelfin
I think Proteus is simulating the version that pulls tha data bus low for at least 18 ms. The funny thing is that in the real life, it doesn't have that problem, yet the sensor reading is incorrect

Skip the simulator and use real devices. If it reads incorrect data, issue is most likely with your code.
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/22 06:16:31 (permalink)
0

post edited by delfindelfin - 2019/04/22 06:24:50

MPLAB X IDE v5.05
XC8 2.00
qhb
Superb Member
• Total Posts : 9998
• Reward points : 0
• Joined: 2016/06/05 14:55:32
• Status: offline
Re: C Code to Interface Humidity Sensor (DHT22) 2019/04/22 06:29:00 (permalink)
+1 (1)
Pointless making that sort of comment without explaining what happened when you tried your code.

Nearly there...
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/22 07:24:30 (permalink)
+1 (1)
Can help with the simulator or device. But this code....
`if (binary & 0x80) {            Ones++;        }`

Is not correct for a 16 bit value. You need 0x8000 to test the top bit here.
Also 4 digits is not enough for a 16 bit unsigned which can range 0-65535. Of course your binary values may only have 4 digits (0-9999 max) in which case this is not necessarily a problem.

Also what is with O, T, H and Th in main? Why have these temp variables for the result and then copy to the real variables? Why not straight to their destinations in the first place?
`BinaryBCDConverter(&Humid_Decimals, &Humid_Ones, &Humid_Tens, &Unused, binary);`

What you have works, it’s just a somewhat obtuse.
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/22 07:36:00 (permalink)
+1 (1)
pcbbc
Also what is with O, T, H and Th in main? Why have these temp variables for the result and then copy to the real variables? Why not straight to their destinations in the first place?
`BinaryBCDConverter(&Humid_Decimals, &Humid_Ones, &Humid_Tens, &Unused, binary);`

What you have works, it’s just a somewhat obtuse.

Agreed. Also, I would just go ahead and convert it to ASCII by adding '0'.

For temperature, OP will need to mask off the MS bit before doing the conversion. For the sign bit, set the character to '-'   or   ' ' instead of 0.

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/22 08:18:40 (permalink)
0
But if I use

` BinaryBCDConverter(&Humid_Decimals, &Humid_Ones, &Humid_Tens, &Unused, binary); `

How do I declare the function?

` void BinaryBCDConverter(uint8_t *O, uint8_t *T, uint8_t *H, uint16_t binary ){  uint8_t Hundreds = 0; uint8_t Tens = 0; uint8_t Ones = 0;  uint8_t i;  for(i=0; i<16; i++) { Ones <<= 1; Tens <<= 1; Hundreds <<= 1;  if (binary & 0x8000) { Ones++; } if (Ones >= 10) { Ones -= 10; Tens++; } if (Tens >= 10) { Tens -= 10; Hundreds++; } if (Hundreds >= 10) { Hundreds -= 10; } binary <<= 1; }  *O = Ones; *T = Tens; *H = Hundreds; }   `

If I declare it this way:

` void BinaryBCDConverter(uint8_t *Humid_Decimals, uint8_t *Humid_Ones, uint8_t *Humid_Tens, uint16_t binary ){  uint8_t Hundreds = 0; uint8_t Tens = 0; uint8_t Ones = 0;  uint8_t i;  for(i=0; i<16; i++) { Ones <<= 1; Tens <<= 1; Hundreds <<= 1;  if (binary & 0x8000) { Ones++; } if (Ones >= 10) { Ones -= 10; Tens++; } if (Tens >= 10) { Tens -= 10; Hundreds++; } if (Hundreds >= 10) { Hundreds -= 10; } binary <<= 1; }  *Humid_Decimals = Ones; *Humid_Ones = Tens; *Humid_Tens = Hundreds; }  `

When I change to the temperature values I am going to have problems
post edited by delfindelfin - 2019/04/22 08:22:40

MPLAB X IDE v5.05
XC8 2.00
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/22 08:25:59 (permalink)
+1 (1)
delfindelfinWhen I change to the temperature values I am going to have problems
Define the function just as you are now.

You seem to have misunderstood how parameters are passed to your functions. It’s not by matching on name, but by position.

What you call parameters in your function, and what you call them where you call that function can be, and very often are, totally diffferent.

Edit: Same goes for binary in main. No need for that either, just pass humid or temp in directly. Just these lines and keep your function unchanged:
`BinaryBCDConverter(&Humid_Decimals, &Humid_Ones, &Humid_Tens, &Th, humid);BinaryBCDConverter(&Temp_Decimals, &Temp_Ones, &Temp_Tens, &Th, temp);`
post edited by pcbbc - 2019/04/22 08:32:34
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/22 09:12:55 (permalink)
0
Well, now it looks a little bit more decent. The real life sensor displays 24.2 C and 60.9 % of Relative Humidity. The problem is that is not refreshing the values

MPLAB X IDE v5.05
XC8 2.00
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/22 09:53:52 (permalink)
+1 (1)
delfindelfin
Well, now it looks a little bit more decent. The real life sensor displays 24.2 C and 60.9 % of Relative Humidity. The problem is that is not refreshing the values
Well done.

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.
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/22 10:38:00 (permalink)
0
delfindelfin
How do I declare the function?

As pcbbc said, you don't seem to understand how parameters are passed to functions. The way you coded is wasting resources and inefficient.  Here's how I would code it:
`void BinaryBCDConverter(uint8_t *ones, uint8_t *tens, uint8_t *hund, uint8_t *thou, uint16_t bin){  uint8_t i = 16;  *thou = *hund = *tens = *ones = 0;   do {    *ones <<= 1;    *tens <<= 1;    *hund <<= 1;    *thou <<= 1;     if (bin & 0x8000) {      (*ones)++;    }    if (*ones >= 10) {      *ones -= 10;      (*tens)++;    }    if (*tens >= 10) {      *tens -= 10;      (*hund)++;    }    if (*hund >= 10) {      *hund -= 10;      (*thou)++;    }    bin <<= 1;  } while (--i); // uncomment these if you want it to convert to ascii too// and change the type to 'char'/*  *thou += '0'; // convert to ASCII  *hund += '0';  *tens += '0';  *ones += '0';*/}`

Page: < 12345 > Showing page 3 of 5