Notify when gpio value is changed

Viewed 2510

I'm currently trying to poll gpio value with only shell script.

I basically developped the script with a test file before using /sys/class/gpio/gpioxx/value

This is the solution I found :

#!/bin/bash

SCRIPT_DIR=$(dirname $(readlink -f $0))
FILE_NAME=$SCRIPT_DIR"/fileTest"

while true
do
    inotifywait -qq -e modify $FILE_NAME
    read val < $FILE_NAME
    echo $val
    ### do something here ###
done

This is working with a basic file but I have two problems with this solution.

1 - The "modify" event is triggered when the file is saved, not when the content of the file has changed. So if I'm writing the same value in the file, the event is triggered but it should not.

2 - I remarqued that this solution doesn't works for gpios, if I'm using a simple ascii file it works but when I use inotifywait on /sys/class/gpio/gpioxx/value it depends.

If I use echo value > /sys/class/gpio/gpioxx/value the event is detected, but if I configure the pin as an input and connect it to 3v3 or 0V nothing is triggered.

Does someone know how I could trigger this change using only scripts?

3 Answers

From linux/Documentation/gpio/gpio-legacy.txt:

"/sys/class/gpio/gpioN/edge"
          ... reads as either "none", "rising", "falling", or
          "both". Write these strings to select the signal edge(s)
          that will make poll(2) on the "value" file return.

So you can do:

echo input > /sys/class/gpio/gpioN/direction
echo both > /sys/class/gpio/gpioN/edge

Now, you have to find a command that call poll (or pselect) on /sys/class/gpio/gpioN/value. (I will update my answer if I find one)

This is tight loop solution (which is more resource intensive), but will do the trick if you got nothing better:

gpio_value=$(cat /sys/class/gpio/gpio82/value)
while true; do
  value=$(cat /sys/class/gpio/gpio82/value)
  if [[ $gpio_value != $value ]]; then
    gpio_value=$value
    echo "$(date +'%T.%N') value changed to $gpio_value"
  fi
done

Example output:

13:09:52.527811324 value changed to 1
13:09:52.775153524 value changed to 0
13:09:55.439330380 value changed to 1
13:09:55.711569164 value changed to 0
13:09:56.211028463 value changed to 1
13:09:57.082968491 value changed to 0

I use it for debug purposes.

Actually, I usually use this one-liner more often:

printf " Press any key to stop...\n GPIO value:   " ; until $(read -r -t 0 -n 1 -s key); do printf "\033[2D$(cat /sys/class/gpio/gpio82/value) " ; done ; echo

Again, for debug purposes.

You may use libgpiod that provide some useful tools to monitor GPIOs. However, you need to use new GPIO API available from Linux 4.8.

Related