DHT22 Sensor's checksum not valid - c++

The read bits from DHT22 sensor as follow:
0000000111010001000000001110111111101111
If we calculate the check sum of them by the formula that they gave:
Reference: https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf
If you convert each of their octets in the example to decimal and compare it with the last 8 bits (checksum) - they are equal.
Binary: Decimal:
00000001 1 //First 8 bits
11010001 209 //Second 8 bits
00000000 0 //Third 8 bits
11101111 239 //Fourth 8 bits
---------------------------------->
Summed: 449
------------ Not equal ----------->
11000001 193 //Check sum
When the 16 bits for the Humidity and 16 bits for Temperature are converted they show correct results based on other popular DHT22 libraries, but the checksum is not valid.

I misunderstood the formula that they have given.
By last 8 bits they mean the last 8 bits of the 4 octets sum:
Binary: Decimal:
00000001 1 //First 8 bits
11010001 209 //Second 8 bits
00000000 0 //Third 8 bits
11101111 239 //Fourth 8 bits
---------------------------------->
Summed: 449
449 as Binary: 111000001
449's last 8 bits: 11000001
11000001 as decimal: 193
----------------------------- Equal ----------->
11000001 193 //Check sum
I hope someone who had the same problem came to that, because it took me hours of experimenting to find what was causing the problem.
In their example their sum is also lower that 255 and it is even harder to catch it, because you doesn't need to remove a bit, because the value is no bigger than 8 bits.

Related

Is there a formula to find the numbers of bits for either exponent or significand in a floating point number?

Recently, I have been interested with using bit shiftings on floating point numbers to do some fast calculations.
To make them work in more generic ways, I would like to make my functions work with different floating point types, probably through templates, that is not limited to float and double, but also "halfwidth" or "quadruple width" floating point numbers and so on.
Then I noticed:
- Half --- 5 exponent bits --- 10 signicant bits
- Float --- 8 exponent bits --- 23 signicant bits
- Double --- 11 exponent bits --- 52 signicant bits
So far I thought exponent bits = logbase2(total byte) * 3 + 2,
which means 128bit float should have 14 exponent bits, and 256bit float should have 17 exponent bits.
However, then I learned:
- Quad --- 15 exponent bits --- 112 signicant bits
- Octuple--- 19 exponent bits --- 237 signicant bits
So, is there a formula to find it at all? Or, is there a way to call it through some builtin functions?
C or C++ are preferred, but open to other languages.
Thanks.
Characteristics Provided Via Built-In Functions
C++ provides this information via the std::numeric_limits template:
#include <iostream>
#include <limits>
#include <cmath>
template<typename T> void ShowCharacteristics()
{
int radix = std::numeric_limits<T>::radix;
std::cout << "The floating-point radix is " << radix << ".\n";
std::cout << "There are " << std::numeric_limits<T>::digits
<< " base-" << radix << " digits in the significand.\n";
int min = std::numeric_limits<T>::min_exponent;
int max = std::numeric_limits<T>::max_exponent;
std::cout << "Exponents range from " << min << " to " << max << ".\n";
std::cout << "So there must be " << std::ceil(std::log2(max-min+1))
<< " bits in the exponent field.\n";
}
int main()
{
ShowCharacteristics<double>();
}
Sample output:
The floating-point radix is 2.
There are 53 base-2 digits in the significand.
Exponents range from -1021 to 1024.
So there must be 11 bits in the exponent field.
C also provides the information, via macro definitions like DBL_MANT_DIG defined in <float.h>, but the standard defines the names only for types float (prefix FLT), double (DBL), and long double (LDBL), so the names in a C implementation that supported additional floating-point types would not be predictable.
Note that the exponent as specified in the C and C++ standards is one off from the usual exponent described in IEEE-754: It is adjusted for a significand scaled to [½, 1) instead of [1, 2), so it is one greater than the usual IEEE-754 exponent. (The example above shows the exponent ranges from −1021 to 1024, but the IEEE-754 exponent range is −1022 to 1023.)
Formulas
IEEE-754 does provide formulas for recommended field widths, but it does not require IEEE-754 implementations to conform to these, and of course the C and C++ standards do not require C and C++ implementations to conform to IEEE-754. The interchange format parameters are specified in IEEE 754-2008 3.6, and the binary parameters are:
For a floating-point format of 16, 32, 64, or 128 bits, the significand width (including leading bit) should be 11, 24, 53, or 113 bits, and the exponent field width should be 5, 8, 11, or 15 bits.
Otherwise, for a floating-point format of k bits, k should be a multiple of 32, and the significand width should be k−round(4•log2k)+13, and the exponent field should be round(4•log2k)−13.
The answer is no.
How many bits to use (or even which representation to use) is decided by compiler implementers and committees. And there's no way to guess what a committee decided (and no, it's not the "best" solution for any reasonable definition of "best"... it's just what happened that day in that room: an historical accident).
If you really want to get down to that level you need to actually test your code on the platforms you want to deploy to and add in some #ifdef macrology (or ask the user) to find which kind of system your code is running on.
Also beware that in my experience one area in which compilers are extremely aggressive (to the point of being obnoxious) about type aliasing is with floating point numbers.
I want to see if there's a formula is to say if 512bit float is put in as standard, it would automatically work with it, without the need of altering anything
I don't know of a published standard that guarantees the bit allocation for future formats (*). Past history shows that several considerations factor into the final choice, see for example the answer and links at Why do higher-precision floating point formats have so many exponent bits?.(*) EDIT: see note added at the end.
For a guessing game, the existing 5 binary formats defined by IEEE-754 hint that the number of exponent bits grows slightly faster than linear. One (random) formula that fits these 5 data points could be for example (in WA notation) exponent_bits = round( (log2(total_bits) - 1)^(3/2) ).
This would foresee that a hypothetical binary512 format would assign 23 bits to the exponent, though of course IEEE is not bound in any way by such second-guesses.
The above is just an interpolation formula that happens to match the 5 known exponents, and it is certainly not the only such formula. For example, searching for the sequence 5,8,11,15,19 on oeis finds 18 listed integer sequences that contain this as a subsequence.
[ EDIT ]   As pointed out in #EricPostpischil's answer, IEEE 754-2008 does in fact list the formula exponent_bits = round( 4 * log2(total_bits) - 13 ) for total_bits >= 128 (the formula actually holds for total_bits = 64, too, though it does not for = 32 or = 16).
The empirical formula above matches the reference IEEE one for 128 <= total_bits <= 1472, in particular IEEE also gives 23 exponent bits for binary512 and 27 exponent bits for binary1024.
UPDATE : I've now incorporated that into a single unified function that perfectly lines up with the official formula while incorporating the proper exponents for 16- and 32-bit formats, and how the bits are split between sign-bit, exponent bits, and mantissa bits.
inputs can be in # of bits, e.g. 64, a ratio like "2x", or even case-insensitive single letters :
"S" for 1x single, - "D" for 2x double,
"Q" for 4x quadruple, - "O" for 8x "octuple",
"X" for 16x he"X", - "T" for 32x "T"hirty-two,
-— all other inputs, missing, or invalid, defaults to 0.5x half-precision
gcat <( jot 20 | mawk '$!(_=NF)=(_+_)^($_)' ) \
<( jot - -1 8 | mawk '$!NF =(++_+_)^$(_--)"x"' ) |
{m,g}awk '
function _754(__,_,___) {
return \
(__=(__==___)*(_+=_+=_^=_<_) ? _--^_++ : ">"<__ ? \
(_+_)*(_*_/(_+_))^index("SDQOXT", toupper(__)) : \
__==(+__ "") ? +__ : _*int(__+__)*_)<(_+_) \
\
? "_ERR_754_INVALID_INPUT_" \
: "IEEE-754-fp:" (___=__) "-bit:" (_^(_<_)) "_s:"(__=int(\
log((_^--_)^(_+(__=(log(__)/log(--_))-_*_)/_-_)*_^(\
-((++_-__)^(--_<__) ) ) )/log(_))) "_e:" (___-++__) "_m"
}
function round(__,_) {
return \
int((++_+_)^-_+__)
}
function _4xlog2(_) {
return (log(_)/log(_+=_^=_<_))*_*_
}
BEGIN { CONVFMT = OFMT = "%.250g"
}
( $++NF = _754(_=$!__) ) \
( $++NF = "official-expn:" \
+(_=round(_4xlog2(_=_*32^(_~"[0-9.]+[Xx]")))-13) < 11 ? "n/a" :_) |
column -s':' -t | column -t | lgp3 5
.
2 _ERR_754_INVALID_INPUT_ n/a
4 _ERR_754_INVALID_INPUT_ n/a
8 IEEE-754-fp 8-bit 1_s 2_e 5_m n/a
16 IEEE-754-fp 16-bit 1_s 5_e 10_m n/a
32 IEEE-754-fp 32-bit 1_s 8_e 23_m n/a
64 IEEE-754-fp 64-bit 1_s 11_e 52_m 11
128 IEEE-754-fp 128-bit 1_s 15_e 112_m 15
256 IEEE-754-fp 256-bit 1_s 19_e 236_m 19
512 IEEE-754-fp 512-bit 1_s 23_e 488_m 23
1024 IEEE-754-fp 1024-bit 1_s 27_e 996_m 27
2048 IEEE-754-fp 2048-bit 1_s 31_e 2016_m 31
4096 IEEE-754-fp 4096-bit 1_s 35_e 4060_m 35
8192 IEEE-754-fp 8192-bit 1_s 39_e 8152_m 39
16384 IEEE-754-fp 16384-bit 1_s 43_e 16340_m 43
32768 IEEE-754-fp 32768-bit 1_s 47_e 32720_m 47
65536 IEEE-754-fp 65536-bit 1_s 51_e 65484_m 51
131072 IEEE-754-fp 131072-bit 1_s 55_e 131016_m 55
262144 IEEE-754-fp 262144-bit 1_s 59_e 262084_m 59
524288 IEEE-754-fp 524288-bit 1_s 63_e 524224_m 63
1048576 IEEE-754-fp 1048576-bit 1_s 67_e 1048508_m 67
0.5x IEEE-754-fp 16-bit 1_s 5_e 10_m n/a
1x IEEE-754-fp 32-bit 1_s 8_e 23_m n/a
2x IEEE-754-fp 64-bit 1_s 11_e 52_m 11
4x IEEE-754-fp 128-bit 1_s 15_e 112_m 15
8x IEEE-754-fp 256-bit 1_s 19_e 236_m 19
16x IEEE-754-fp 512-bit 1_s 23_e 488_m 23
32x IEEE-754-fp 1024-bit 1_s 27_e 996_m 27
64x IEEE-754-fp 2048-bit 1_s 31_e 2016_m 31
128x IEEE-754-fp 4096-bit 1_s 35_e 4060_m 35
256x IEEE-754-fp 8192-bit 1_s 39_e 8152_m 39
===============================================
Similar to the concept mentioned above, here's an alternative formula (just re-arranging some terms) that will calculate the unsigned integer range of the exponent ([32,256,2048,32768,524288], corresponding to [5,8,11,15,19]-powers-of-2) without needing to call the round function :
uint_range = ( 64 ** ( 1 + (k=log2(bits)-4)/2) )
*
( 2 ** -( (3-k)**(2<k) ) )
(a) x ** y means x-to-y-power
(b) 2 < k is a boolean condition that should just return 0 or 1.
The function shall be accurate from 16-bit to 256-bit, at least. Beyond that, this formula yields exponent sizes of
– 512-bit : 23
– 1024-bit : 27
– 2048-bit : 31
– 4096-bit : 35
(beyond-256 may be inaccurate. even 27-bit-wide exponent allows exponents that are +/- 67 million, and over 40-million decimal digits once you calculate 2-to-that-power.)
from there to IEEE 754 exponent is just a matter of log2(uint_range)

Why do these two functions to print binary representation of an integer have the same output?

I have two functions that print 32bit number in binary.
First one divides the number into bytes and starts printing from the last byte (from the 25th bit of the whole integer).
Second one is more straightforward and starts from the 1st bit of the number.
It seems to me that these functions should have different outputs, because they process the bits in different orders. However the outputs are the same. Why?
#include <stdio.h>
void printBits(size_t const size, void const * const ptr)
{
unsigned char *b = (unsigned char*) ptr;
unsigned char byte;
int i, j;
for (i=size-1;i>=0;i--)
{
for (j=7;j>=0;j--)
{
byte = (b[i] >> j) & 1;
printf("%u", byte);
}
}
puts("");
}
void printBits_2( unsigned *A) {
for (int i=31;i>=0;i--)
{
printf("%u", (A[0] >> i ) & 1u );
}
puts("");
}
int main()
{
unsigned a = 1014750;
printBits(sizeof(a), &a); // ->00000000000011110111101111011110
printBits_2(&a); // ->00000000000011110111101111011110
return 0;
}
Both your functions print binary representation of the number from the most significant bit to the least significant bit. Today's PCs (and majority of other computer architectures) use so-called Little Endian format, in which multi-byte values are stored with least significant byte first.
That means that 32-bit value 0x01020304 stored on address 0x1000 will look like this in the memory:
+--------++--------+--------+--------+--------+
|Address || 0x1000 | 0x1001 | 0x1002 | 0x1003 |
+--------++--------+--------+--------+--------+
|Data || 0x04 | 0x03 | 0x02 | 0x01 |
+--------++--------+--------+--------+--------+
Therefore, on Little Endian architectures, printing value's bits from MSB to LSB is equivalent to taking its bytes in reversed order and printing each byte's bits from MSB to LSB.
This is the expected result when:
1) You use both functions to print a single integer, in binary.
2) Your C++ implementation is on a little-endian hardware platform.
Change either one of these factors (with printBits_2 appropriately adjusted), and the results will be different.
They don't process the bits in different orders. Here's a visual:
Bytes: 4 3 2 1
Bits: 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1
Bits: 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
The fact that the output is the same from both of these functions tells you that your platform uses Little-Endian encoding, which means the most significant byte comes last.
The first two rows show how the first function works on your program, and the last row shows how the second function works.
However, the first function will fail on platforms that use Big-Endian encoding and output the bits in this order shown in the third row:
Bytes: 4 3 2 1
Bits: 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1
Bits: 8 7 6 5 4 3 2 1 16 15 14 13 12 11 10 9 24 23 22 21 20 19 18 17 32 31 30 29 28 27 26 25
For the printbits1 function, it is taking the uint32 pointer and assigning it to a char pointer.
unsigned char *b = (unsigned char*) ptr;
Now, in a big endian processor, b[0] will point to the Most significant byte of the uint32 value. The inner loop prints this byte in binary, and then b[1] will point to the next most significant byte in ptr. Therefore this method prints the uint32 value MSB first.
As for printbits2, you are using
unsigned *A
i.e. an unsigned int. This loop runs from 31 to 0 and prints the uint32 value in binary.

Understanding two's complement

I don't understand why an n-bit 2C system number can be extended to an (n+1)-bit 2C system number by making bit bn = bn−1, that is, extending to (n+1) bits by replicating the sign bit.
This works because of the way we calculate the value of a binary integer.
Working right to left, the sum of each bit_i * 2 ^ i,
where
i is the range 0 to n
n is the number of bits
Because each subsequent 0 bit will not increase the magnitude of the sum, it is the appropriate value to pad a smaller value into a wider bit field.
For example, using the number 5:
4 bit: 0101
5 bit: 00101
6 bit: 000101
7 bit 0000101
8 bit: 00000101
The opposite is true for negative numbers in a two's compliment system.
Remember you calculate two's compliment by first calculating the one's compliment and then adding 1.
Invert the value from the previous example to get -5:
4 bit: 0101 (invert)-> 1010 + 1 -> 1011
5 bit: 00101 (invert)-> 11010 + 1 -> 11011
6 bit: 000101 (invert)-> 111010 + 1 -> 111011
7 bit: 0000101 (invert)-> 1111010 + 1 -> 1111011
8 bit: 00000101 (invert)-> 11111010 + 1 -> 11111011

Why (char)433 is equal to -79'+-' in c++?

When I type cast 433 to char I get this.
How does 433 equal to -79 while ASCII for 4 & 3 are 52 & 51 respectively, according to this table.
The decimal number 433 is 0x1b1, and is an int and is usually 32 bits longs. What happens when you cast it to a char (which usually have 8 bits) is that all but the lowest 8 bits are just thrown away, leaving you with 0xb1 which is -79 as a signed two-complement 8-bit integer.

represent negative number with 2' complement technique?

I am using 2' complement to represent a negative number in binary form
Case 1:number -5
According to the 2' complement technique:
Convert 5 to the binary form:
00000101, then flip the bits
11111010, then add 1
00000001
=> result: 11111011
To make sure this is correct, I re-calculate to decimal:
-128 + 64 + 32 + 16 + 8 + 2 + 1 = -5
Case 2: number -240
The same steps are taken:
11110000
00001111
00000001
00010000 => recalculate this I got 16, not -240
I am misunderstanding something?
The problem is that you are trying to represent 240 with only 8 bits. The range of an 8 bit signed number is -128 to 127.
If you instead represent it with 9 bits, you'll see you get the correct answer:
011110000 (240)
100001111 (flip the signs)
+
000000001 (1)
=
100010000
=
-256 + 16 = -240
Did you forget that -240 cannot be represented with 8 bits when it is signed ?
The lowest negative number you can express with 8 bits is -128, which is 10000000.
Using 2's complement:
128 = 10000000
(flip) = 01111111
(add 1) = 10000000
The lowest negative number you can express with N bits (with signed integers of course) is always - 2 ^ (N - 1).