0

I am using Debian (8.3.0-6) on an embedded custom board and working on the dht11 sensor. Briefly, I need to read 40 bits from a GPIO pin and each bit can take a max 70 microseconds. When bit-level is high for max 28us or 70us, it means is logic 0 or 1, respectively. (So I have a timeout controller for each bit and if a bit takes more than 80us, I need to stop the process.). enter image description here enter image description here In my situation, sometimes I can read all 40 bits correctly but sometimes I can't do it and the function of libgpiod gpiod_line_get_value(line); is missing the bit (my code is below). I am trying to figure out that why I cant read and lose a bit, what is the reason for that. But I haven't found a sensible answer yet. So I was wondering What am I missing out?, What is the proper way to GPIO programming?

Here is what I wanted to show you, How do I understand what I am missing a bit? Whenever I catch a bit, I am setting and resetting another GPIO pin at the rising and falling edge of a bit (So I can see which bit missing). Moreover, as far as I see I am always missing the two edges on one bit or one edge on two bits consecutively (rising and falling or falling and rising). In the first picture, you can see which bit I missed, the second is when I read all bits correctly.

enter image description here

enter image description here

Here it is my code:

//********************************************************* Start reading data bit by low level (50us) ***************************
    for (int i = 0; i < DHT_DATA_BYTE_COUNT ; i++) //DHT_DATA_BYTE_COUNT = 5
    {
        for (int J = 7; J > -1; J--)
        {
             GPIO_SetOutPutPin(testPin); //gpiod_line_set_value(testPin, 1);
             int ret;
             start = micros();
             do
             {
                 ret = GPIO_IsInputPinSet(dht11pin);//gpiod_line_get_value(dht11pin);
                 delta = micros() - start;
                 if(ret == -1)
                 {
                     err_step.step = 9;
                    err_step.ret_val = -1;
                    return -1;
                 }
                if(delta > DHT_START_BIT_TIMEOUT_US) //80us
                {
                    err_step.step = 10;
                    err_step.ret_val = -2;
                    err_step.timestamp[is] = delta;
                    err_step.indx[is].i = i;
                    err_step.indx[is++].j = J;
                    GPIO_ResetOutPutPin(testPin);
                    return -2;
                }
             }while(ret == 0);


                GPIO_ResetOutPutPin(testPin);
                err_step.ret_val = 10;


                GPIO_SetOutPutPin(testPin);

            start = micros();
            do
             {
                 ret = GPIO_IsInputPinSet(dht11pin);
                 delta = micros() - start;
                 if(ret == -1)
                 {
                     err_step.step = 11;
                    err_step.ret_val = -1;
                    return -1;
                 }
                 if(delta > DHT_BEGIN_RESPONSE_TIMEOUT_US) //80us
                {
                    err_step.step = 12;
                    err_step.ret_val = -2;
                    err_step.timestamp[is] = delta;
                    err_step.indx[is].i = i;
                    err_step.indx[is++].j = J;
                    return -2;
                }
             }while(ret == 1);

                    err_step.timestamp[is] = delta;
                    err_step.indx[is].i = i;
                    err_step.indx[is++].j = J;
                GPIO_ResetOutPutPin(testPin);
                err_step.ret_val = 10;

            (delta > DHT_BIT_SET_DATA_DETECT_TIME_US) ? bitWrite(dht11_byte[i],J,1) : bitWrite(dht11_byte[i],J,0);
        }
    }
0andriy
  • 4,183
  • 1
  • 24
  • 37
Zafer SEN
  • 105
  • 1
  • 12
  • 2
    That subtle signal timing is not going to be reliable in user mode code. Linux kernel version 3.14 onwards has a dht11 driver selected by `CONFIG_DHT11` and is part of the Linux Industrial I/O subsystem. It needs a GPIO line that supports interrupts on rising and falling edges. It needs to be configured in the device tree. See the device tree bindings at https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/humidity/dht11.txt or https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/humidity/dht11.yaml – Ian Abbott Jan 05 '22 at 10:28
  • What do you mean by signal timing?Could you elaborate it please. Do you mean I get the time by micros and I calculate the differences? if it exceeds the threshold, I stop the reading in the code above. if you mean is that. my problem is not that. briefly, why gpiod reading funct.(gpiod_line_get_value) cannot catch the bit. Thanks a lot for your patience – Zafer SEN Jan 08 '22 at 18:12
  • Thanks for the guidance. I'll check these links to understand. I am new at linux gpio programming on Linux. So I just wanted to figure out from simple way to proper / in a perfect way – Zafer SEN Jan 08 '22 at 19:04
  • By the way, I calculate the percentage of corruption of data, it is % 83. I collected 12288 data with a sec interval, 10267 of them are corrupt data. Absolutely, it is unreliable. – Zafer SEN Jan 08 '22 at 23:34
  • 1
    Use in-kernel driver as @IanAbbott suggested. And use `libiio`. It has a lot of nice features and good documentation. – 0andriy Jan 11 '22 at 20:08
  • if there is someone interested in the differences between userspace gpio programming and kernel gpio programming. I also observed the percentage of corruption in kernel gpio programming on dht11 sensor. it was % 62. I collected 4714 temp and humidity data and 2933 of them was corrupted. Only 1788 of them was acceptable correct data. – Zafer SEN Apr 15 '22 at 16:08

0 Answers0