While the DHT11 and DHT22 temperature sensors work fine on the Raspberry Pi using default (Adafruit) libraries, the AMS2301/DHT21 I intended for the outdoor measurements did not. At first, I suspected the sensor to be faulty, but then discovered that the sensor worked fine when using an Arduino with c-libraries. Not the sensor, then.
More investigation showed a strange behaviour: On the Arduino, both a DHT22 and the DHT21 sensor worked by using the same configuration (according to the specs, they actually use the same serial protocol, so this is normal). On the Raspi, however, the DHT22 worked fine but the DHT21 delivers nonsense-readings despite using exactly the same configuration and libraries for both sensors.
So why?....Well, it is due to the way the reading of the signals is implemented in the Adafruit circuitpython libraries for the Raspi and the AMS2301 sending some undocumented(!) dummy data at the end of its actual signal.
The DHT protocol for reading data consists of a sequence of LOW (0V) and HIGH (5V) signals on the sensor wire, set by the Raspi or the sensor.
- the Raspi/Arduino sends a LOW (1ms for DHT22 and DHT21 or 18ms for DHT11) followed by a 40us HIGH.
- the sensor sends a LOW (80us for DHT22 and DHT21 or 50us for DHT11) followed by a 80us HIGH.
- the sensor sends a sequence of 40 times LOW-HIGH: LOW of 50us, and HIGH with 30us for "0" and 70us for "1".
From the sequence of 40 values (1 or 0 according to duration of HIGH), we can now compute humidity and temperature: The 40 values are actually a series of 5 byte (8 bit each), where byte 1 and 2 are ten times the humidity value and where byte 3 and 4 are ten times the temperature. Byte 5 is the checksum: Just add up bytes 1 to 4. So far so good.
The reason this failed is the way this is read differently by Arduino and the Raspberry Pi python library. Plus, the DHT21 actually keeps sending 64 bits of data, 8 byte, where only the 5 first carry meaning and the others are simply zero.
The Arduino library will simply do step 1 above, then wait for the LOW-HIGH of step 2, and finally start reading the 40 bits in step 3. This works, since anything after bit 40 is ignored. The python, however, first does step1, but then collects the transmitted bits (via an external C library) into a 40-bit long array, which only retains only the last 40 bits/5byte. For the DHT11/22 this works fine since the bits from step 2 are pushed out of the array by the 40 readings afterwards. However for the DHT21, the empty bytes at the end (byte 6-8) will not only push the 1 bit from step 2 out, but also the meaningful first 3 bytes of step 3.
In conclusion, I rewrote the library to retrieve 65bit from the c backend (1bit for step 2 and 8byte after that), and use bits 2-41 to compute my sensor readings.