1
\$\begingroup\$

I am using a BeagleBone Black to trigger an ultrasonic sensor and expecting the Echo pin-connected GPIO to be sensed as HIGH by my program, but it almost crashes the system.

while(1)
    {
    // Reset
    system("echo 0 > /sys/class/gpio/gpio44/value");printf(ret); 

    // Trigger
    system("echo 1 > /sys/class/gpio/gpio44/value");
    usleep(10); // 10us
    system("echo 0 > /sys/class/gpio/gpio44/value");

     // read value
     result = read(pollfds[0].fd, readBuf, MAX_BUFFER_SIZE);
     if (result > 0){
            // read data ... do something
     }
     else{
            // do something else
    }

    usleep(1000*10); // sleep for 5ms
    }
}

On running it, the CPU usage spikes all the way from 3% to 72% and above. I noticed that significantly increasing the delay (usleep()) solves the problem but I can't afford delay more than a few ms.

Am I doing something wrong or is this a limitation of the device?

\$\endgroup\$
11
  • 1
    \$\begingroup\$ That's not an electronics question. Your PC also consumes a lot of power running an infinite loop of polling for data without any breaks sleeping between calls. \$\endgroup\$ Commented Oct 16, 2022 at 20:53
  • 2
    \$\begingroup\$ Maybe you are trying to do a realtime task on a non-realtime system. If the device runs a multitasking OS it can't guarantee it will run your code with timing you want, if what you want is just polling GPIO in a loop. \$\endgroup\$ Commented Oct 16, 2022 at 21:17
  • 3
    \$\begingroup\$ System() creates an entire shell and asks it to execute your command in my understanding. This is very costly for what amount to simple file io. Open that file for writing inside your program and see if the load goes down. \$\endgroup\$ Commented Oct 16, 2022 at 21:36
  • 2
    \$\begingroup\$ The CPU of your board has only 1 CPU core. And it is running a multitasking Linux OS. It will have to go do other stuff more impotant than run a GPIO polling. Network, USB, etc handling. It will be difficult to get even moderate results. It is more troublesome than what you think. \$\endgroup\$ Commented Oct 16, 2022 at 21:42
  • 3
    \$\begingroup\$ "but I can't afford delay more than a few ms." Yes, you are running a real-time system. Having a do-not-exceed requirement on delay is the definition of a real time system. \$\endgroup\$ Commented Oct 16, 2022 at 22:42

2 Answers 2

1
\$\begingroup\$

You should use the select() or poll() or epoll() calls. Those calls allow you to wait for data to be ready on a file description with a timeout.

\$\endgroup\$
3
  • \$\begingroup\$ I have tried that but the values are no longer read after the first time. See the issue explained better here (forum.beagleboard.org/t/poll-a-gpio-pin-with-no-blocking/32998). I see no other option other than reopening the file descriptor every time. \$\endgroup\$ Commented Oct 16, 2022 at 21:04
  • \$\begingroup\$ just edited the question based on latest observations \$\endgroup\$ Commented Oct 16, 2022 at 21:14
  • 1
    \$\begingroup\$ Try something like in this module: github.com/mkaczanowski/BeagleBoneBlack-GPIO Apparently there are additional paths like ".../edge" you can use. Look at the waitForEdge method. \$\endgroup\$ Commented Oct 16, 2022 at 21:15
1
\$\begingroup\$

The function system() is very inefficient, open the device file directly and write to it instead.

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int fh=open("/sys/class/gpio/gpio44/value",O_WRONLY);
if(fh < 0) 
  perror("open fail");
else if ( write(fh,"0\n",2) < 2 )
  perror("write 0 fail");

usleep(10); // 10us
if(fh > 0) 
  IF (lseek(fh,0,SEEK_SET) < 0 ); // not sure if this is needed
    perror("lseek not work");

if(fh < 0) 
  perror("open fail");
else if ( write(fh,"1\n",2) < 2 )
  perror("write 1 fail");

write(fh,"0\n",2);
close(fh);

lseek above may not be needed. or you may need to instead close and reopen he device.

further

printf(ret);

Is almost certainly wrong , especially if user or system data is ever part of ret."100%no"

\$\endgroup\$
4
  • \$\begingroup\$ Compiling it and running gives write 0 fail:Invalid argument \$\endgroup\$ Commented Oct 17, 2022 at 6:20
  • 2
    \$\begingroup\$ @PeDro they meant 1\n instead of 1/n \$\endgroup\$ Commented Feb 24, 2023 at 20:44
  • 1
    \$\begingroup\$ By the way: this method is faster than system but still has a bunch of overhead between your program and the pin. If this is still too slow, then maybe using Linux isn't the best option. \$\endgroup\$ Commented Feb 24, 2023 at 20:45
  • 1
    \$\begingroup\$ mmap() if it works here would be faster, but direct file manipulation is an easy first step. \$\endgroup\$ Commented Feb 24, 2023 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.