Poll a GPIO pin with no blocking

Hi, I am trying to interface the Beaglebone with an ultrasonic sensor using its ARM CPU rather than the conventional PRU. I am able to toggle the GPIO pin to trigger the sensor and currently trying to poll the ECHO pin (GPIO45) until it goes from low to high. For this, I use the following snippet:

        #define DEVICE_NAME0 "/sys/class/gpio/gpio45/value";
        char readBuf[4];

        struct pollfd fd;
        fd = open(DEVICE_NAME0, O_RDONLY); // open file descriptor
        while(1)
{
	// Poll for Echo pin continuously
	 result = read(fd, readBuf, MAX_BUFFER_SIZE);
	 if (result > 0){
			printf("Message received from fd: %s\n\n",readBuf);
	}
        else
               print("fd is closed!");
}

But this only prints the value once and repeats “fd is closed!” (the else case) forever henceforth. I can solve this by opening the file descriptor (fd) each time else is called. But I am not sure if that is a good practice. What is the best way to constantly monitor/poll similar GPIO representing file descriptors ?

why don’t you use interrupt, instead of polling

2 Likes

I am new to this and my initial experiences with GPIO toggling led my decision to do this. Can you suggest me references that are alike my case ?
Thanks

@pradan

you may find this of some use /dev/gpiochip
and this
GPIO user space

2 Likes

@pradan

  1. I too had been exploring BBB since a few months and came across this playlist
    Let's code a Linux Driver - 11: Using GPIO Interrupts in a Linux Kernel Module - YouTube
  2. Write a kernel driver and configure the GPIO to which your sensor is connected as interrupt
  3. On receiving the interrupt send a signal to your user space code, which could be just a c code
  4. Watch the videos in the playlist mentioned above
  5. In case of any query please revert
1 Like

@pradan @zmatt has a nice example here:

Regards,

1 Like

@mathew

Writing a custom kernel driver is extreme overkill. You can receive edge interrupts in userspace using the sysfs gpio API, @RobertCNelson already linked to my tiny sysfs gpio library which shows how to do this.

It’s also possible to relay any kind of interrupt to userspace using the uio_pdrv_genirq driver instead of writing a custom one. My overlay-utils project includes some examples for uio devices, including some that are just an interrupt (e.g. the ehrpwm tz irq devices), and I have an outline for uio-based irq handling in userspace. This is mostly useful for receiving peripheral irqs, but you can use this for receiving GPIO events too (though I don’t see a good reason to do so and it would conflict with sysfs access to the gpio).

1 Like

@ RobertCNelson
Thank you
God bless you

I’m assuming that you are using the hc-sr04 or derivative. Your question is very specific, but your approach cannot effectively measure distance with this sensor. The ARM processor running linux on the BBB will never give you the micro second timing necessary for accurate measurements. Sometimes, the device is wrongly blamed in these circumstances.

I have found that these inexpensive sensors can be accurate, and useful, but only in ideal circumstances. Even if you take the plunge and tackle the PRU learning curve, it is STILL difficult. Measurements on a test bench can be spot on, but then be wildly off when deployed to useful environments. This is due to the WIDE field of vision that these sensors ‘SEE’. There seems to be always some obstacle the the sensor sees that is unintended for the application.

All that said, I have a (failed) app that uses an array of these sensors without polling. It uses the PRU low latency IO (r30, r31) to test the echo pin(s). Adding to the difficulty is the necessity to use level shifters if running the sensor at 5v.

good luck.

uh gonna stay away from PRU for now… until a more important need arises. Thanks

@mathew is it possible to kill any process(es) whenever an interrupt is generated by the GPIO going high/low ?