bigmuscle
bigmuscle

Reputation: 449

How to make DHT22 readings more reliable?

I'm reading from DHT22 temperature/humidity sensor in C++ application on Linux (Armbian Bookworm on RockPiS board). I control GPIO using the IOCTL+poll/read interface and it works most of the time and I get the correct temperature/humidity readings. The example code follows:

// request rising edge events
struct gpioevent_request eventreq = { 0 };
eventreq.lineoffset = m_line;
eventreq.handleflags = GPIOHANDLE_REQUEST_INPUT;
eventreq.eventflags = GPIOEVENT_REQUEST_RISING_EDGE;
strcpy(eventreq.consumer_label, "DHT22");

if (ioctl(m_fd, GPIO_GET_LINEEVENT_IOCTL, &eventreq) == -1) {
    trace("DHT22: Error setting the line event (%d)\n", errno);
    break;
}

uint64_t reading = 0;
uint64_t last_timestamp = 0;

while (m_running) {
    // wait for rising edge
    struct pollfd pfd = { 0 };
    pfd.fd = eventreq.fd;
    pfd.events = POLLIN;
    int ret = poll(&pfd, 1, 1); // 1 millisecond timeout (= end of reading)

    if (ret == -1) {
        trace("DHT22: Error while polling event from GPIO (%d)\n", errno);
    } else if (pfd.revents & POLLIN) {
        // rising edge
        struct gpioevent_data event_data;
        read(eventreq.fd, &event_data, sizeof(event_data));
        // ... processing of data here ...
    } else if (ret == 0) {
        // timeout
        // ... finalizing the data here ...
    }
}

The problem lies in the situation when there is higher CPU usage from another application. Then the readings are not occasionally read correctly but still works in 80% of cases which is sufficient for our purpose. I think the problem lies in the fact that DHT sensor is very sensitive to timings.

But the situation is much worse with 100% CPU usage. Then it is not possible to read anything from the sensor at all. The polling always time outs regardless the set timeout. There should be about 40 events but there is always only 1 event in this case. Any ideas to improve this to get at least occasional readings?

I tried setting the thread to realtime priority but the result makes no difference. I also tried using Linux DHT kernel driver (which allows direct temperatur reading from /sys/bus/iio/devices/iio:device0/in_temp_input) but it behaves in the same way. It seems that the problem is not the polling itself - accidental data misses due to high latency, but rather that the kernel is not able to process GPIO interrupts at all when CPU usage is high.

Upvotes: 0

Views: 237

Answers (0)

Related Questions