Pi4J / pi4j-v2

Pi4J Version 2.0
Apache License 2.0
274 stars 60 forks source link

Unable to read DHT22 sensor #190

Closed aburnett397 closed 2 years ago

aburnett397 commented 2 years ago

I'm trying to port old pi4j-v1 code to the new API. Reading a DHT22 involves using a pin alternatively as an input and an output. When reading input, the duration between the edges encodes the desired information with the need to differentiate between 70us and 27us pulses.

I am loosely following this pigpio python implementation

I create the input and output for the pin like so:

cfgOut = DigitalOutput.newConfigBuilder(pi4j)
  .address(pin)
  .initial(DigitalState.HIGH)
  .shutdown(DigitalState.HIGH)
  .provider("pigpio-digital-output")
  .build();
cfgIn = DigitalInput.newConfigBuilder(pi4j)
  .address(pin)
  .pull(PullResistance.OFF)
  .provider("pigpio-digital-input")
  .build();

A reading is then triggered with the pin as an output before switching to an input and registering a listener (this is run every 30 seconds so the created input and output are recycled with initialize()):

//switch to output
if (out == null)
  out = pi4j.create(cfgOut);
else out.initialize(pi4j);

//set pin LOW for 10ms, then HIGH to trigger response
out.state(DigitalState.LOW);
long now = System.nanoTime();
while (System.nanoTime()-now < 10000000);
out.state(DigitalState.HIGH);
out.shutdown(pi4j);

//switch to input and register listener
if (in == null)
  in = pi4j.create(cfgIn);
else in.initialize(pi4j);
in.addListener(listener);

The listener simply tallies up the edges and logs the System.nanoTime(). After a few seconds, well after the DHT22 response time, reading is stopped:

in.removeListener(listener);
in.shutdown(pi4j);

When set as an input, I am only able to detect from 0 to 2 edges, a far cry from the 40 that the chip emits. And the spacing between those edges is measured as ~3ms up to ~15ms, an order of magnitude longer than what is expected. Unless my approach is fundamentally wrong, i get the feeling that I am nowhere near the proper timing requirements. For starters, the characteristics of the chip mean that a pin must reconfigure from output to input within 20us. Does pi4j expose the pigpio bindings in any way? It would be interesting to see the behavior of a1:1 port of the python code.

FDelporte commented 2 years ago

In the CrowPi project, students also tried many different approaches to read correct values from the DHT22. But it seems this type of component is not well-suited to be used in combination with an operating system, compared to a realtime system or microcontroller.

They found a solution by using a Linux system driver as you can read here: https://github.com/Pi4J/pi4j-example-crowpi/blob/main/src/main/java/com/pi4j/crowpi/components/HumiTempComponent.java