# Access to GPIO on Raspberry Pi?

**URL:** <https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438>\
**Category:** Discussion\
**Tags:** raspberry-pi\
**Created:** [September 13, 2021, 12:13pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438 "2021-09-13T12:13:33Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![MrProLogic](https://avatars.discourse-cdn.com/v4/letter/m/848f3c/32.png) [@MrProLogic](https://swi-prolog.discourse.group/u/MrProLogic)\
**Post date:** [September 13, 2021, 12:13pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/1 "2021-09-13T12:13:33Z")

</div>

I am doing a little reading around before beginning a project and looking to use Prolog for a control system.

Does SWI-Prolog give you access to the GPIO pins on a Raspberry Pi? Is it possible to initiate Prolog searches by a GPIO input and produce a signal on a pin as the result of a rule?

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [September 13, 2021, 12:36pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/2 "2021-09-13T12:36:28Z")

</div>

I don’t think you can access the pin directly from Prolog but if there exists a c based library to access the pins, then the FFI package could possibly be used.

[https://www.swi-prolog.org/pack/list?p=ffi](https://www.swi-prolog.org/pack/list?p=ffi)

Edit –

Perhaps its possible to use a setup that is combined with Python. Python accessess the pins and forwards the values to Prolog --with Prolog embedded or called from Python.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 13, 2021, 1:15pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/3 "2021-09-13T13:15:04Z")

</div>

A quick Google search leads me to [How to Control GPIO Hardware from C or C++ | ICS](https://www.ics.com/blog/how-control-gpio-hardware-c-or-c), which tells me that the GPIO pins are simply controlled through the filesystem. Translating the code there gives something like below. Not tested (I have a Pi, but nothing  
to connect to the GPIO pins directly ready ☹ ).

```prolog
blink :-
    setup_call_cleanup(
        open('/sys/class/gpio/export', write, Out1),
        write(Out1, 24),
        close(Out1)),

    setup_call_cleanup(
        open('/sys/class/gpio24/direction', write, Out2),
        write(Out2, out2),
        close(Out2)),

    setup_call_cleanup(
        open('/sys/class/gpio/gpio24/value', write, Out3),
        blink(100, Out3),
        close(Out3)).

blink(N, Out) :-
    N > 0,
    !,
    write(Out, 1),
    flush_output(Out),
    sleep(0.05),
    write(Out, 0),
    flush_output(Out),
    sleep(0.05),
    N2 is N - 1,
    blink(N2, Out).
blink(_,_).

```

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [September 13, 2021, 1:25pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/4 "2021-09-13T13:25:07Z")

</div>

thats great.

I tried to see if reading from the file system would then be reading input – and i guess the approach is polling driven … to identify a change in input.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 13, 2021, 1:42pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/5 "2021-09-13T13:42:09Z")

</div>

A more complete overview of the fs API is at [GPIO Programming: Using the sysfs Interface | ICS](https://www.ics.com/blog/gpio-programming-using-sysfs-interface). Seems you can read `'/sys/class/gpio/gpioNN/value'` and get a 0 or a 1. That seems to be a polling interface ☹ I don’t see what you need to poll again, i.e., do you have to go through the open/close or maybe you can use seek/4 to go back to the start and try again. One needs better docs or a Pi to tell 🙂

Easy enough to build a nice library and submit as a pack. Someone?

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [September 19, 2021, 7:29pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/6 "2021-09-19T19:29:36Z")

</div>

The `sysfs` gpio interface has been [deprecated](https://www.kernel.org/doc/html/latest/admin-guide/gpio/sysfs.html).

The new kernel inteface is through a character device that can be easily accessible using [libgpiod](https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/). It is easy enough to use by calling the executables included with `libgpiod` or it can be called directly from C with ffi.

One of the nice executables provided by libgpiod (besides `gpioget` and `gpioset`) is called `gpiomon`. It allows monitoring rising edges, falling edges and even setup pull down or pull up biases, printing to stdout as events happen:

```prolog

NAME
       lt-gpiomon - manual page for lt-gpiomon v1.6.3

SYNOPSIS
       lt-gpiomon [OPTIONS] <chip name/number> <offset 1> <offset 2> ...

DESCRIPTION
       Wait for events on GPIO lines and print them to standard output

OPTIONS
       -h, --help:
              display this message and exit

       -v, --version:
              display the version and exit

       -l, --active-low:
              set the line active state to low

       -B, --bias=[as-is|disable|pull-down|pull-up] (defaults to 'as-is'):

              set the line bias

       -n, --num-events=NUM: exit after processing NUM events

       -s, --silent:
              don't print event info

       -r, --rising-edge:
              only process rising edge events

       -f, --falling-edge:
              only process falling edge events

       -b, --line-buffered:
              set standard output as line buffered

       -F, --format=FMT
              specify custom output format

   Biases:
       as-is: leave bias unchanged

       disable:
              disable bias

       pull-up:
              enable pull-up

       pull-down:
              enable pull-down
[...]

```

Here is an [article](https://blog.adafruit.com/2018/11/26/sysfs-is-dead-long-live-libgpiod-libgpiod-for-linux-circuitpython/) showing why libgpiod is much better than sysfs.

---

<div class="post-metadata">

**Author:** ![grossdan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/grossdan/32/23_2.png) [@grossdan](https://swi-prolog.discourse.group/u/grossdan)\
**Post date:** [September 20, 2021, 4:57am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/7 "2021-09-20T04:57:15Z")

</div>

A short tutorial on the use of FFI to directly access c would be great.

Dan

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [September 20, 2021, 5:11am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/8 "2021-09-20T05:11:18Z")

</div>

Check out the [ffi add-on page](https://www.swi-prolog.org/pack/list?p=ffi).

It has a simple example to call the [`statfs`](https://man7.org/linux/man-pages/man2/statfs.2.html) libc function:

```prolog
:- use_module(library(ffi)).
:- use_module(library(cerror)).

:- c_import("#include <sys/vfs.h>", % include file where C functions are found
            [libc], % dynamic library(ies) to load
            [statfs(string, -struct(statfs), [int]) % function(s) to import, and description
                                                     % of parameters and return value
            ]).

statfs(File, FsStat) :- % regular prolog predicate
    statfs(File, FsStat, Status), % now we call the C function
    posix_status(Status, statfs, file, File). % covert posix errors to prolog exception

```

Query:

```prolog
?- statfs(".", FsStat), c_load(FsStat[f_bavail], A).
FsStat = <C struct statfs[1]>(0x55a2c9d5bae0),
A = 66197957.

```

More detailed documentation for the ffi add-on is found in this [pdf](https://github.com/JanWielemaker/ffi/wiki/files/ffi.pdf).

**EDIT** : By the way, strictly speaking you don’t have to use posix\_status/4 above, it is just used to convert posix error codes into prolog exceptions.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 20, 2021, 8:54am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/9 "2021-09-20T08:54:07Z")

</div>

> [@swi](#):
>
> The new kernel inteface is through a character device that can be easily accessible using [libgpiod](https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/).

Possibly simply opening, reading and writing to this character device is easier than using libgpio? Sometimes it is … The advantage of using a library is than mostly that if the kernel interface changes again, the library is probably changed to deal with that. Usually, kernel interfaces are pretty stable though.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [September 20, 2021, 8:39pm UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/10 "2021-09-20T20:39:10Z")

</div>

The advantage of using libgpiod, instead of the character device directly, is that libgpiod provides for managing for simultaneous access to the gpio from several processes/threads. As it says in the [linux docs](https://www.kernel.org/doc/html/latest/driver-api/gpio/using-gpio.html):

> For structured and managed applications, we recommend that you make use of the [libgpiod](https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/) library. This provides helper abstractions, command line utlities and arbitration for multiple simultaneous consumers on the same GPIO chip.

---

<div class="post-metadata">

**Author:** ![nicos](https://avatars.discourse-cdn.com/v4/letter/n/7feea3/32.png) [@nicos](https://swi-prolog.discourse.group/u/nicos)\
**Post date:** [September 27, 2021, 10:30am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/11 "2021-09-27T10:30:41Z")

</div>

Is this example slightly incomplete ?

As far as I can see  
posix\_status/4 is defined in ffi/prolog/cerror.pl  
and should be loaded with something like

```prolog
:- use_module(library(cerror)).

```

?

Regards,

## Nicos Angelopoulos

> **[Nicos Angelopoulos](https://stoics.org.uk/~nicos/)**
>
> logic programming

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [September 28, 2021, 5:51am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/12 "2021-09-28T05:51:55Z")

</div>

Nicos, you are correct, fixed the example above. Should probably be fixed on the ffi add-ons README also.

Thanks for pointing it out.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 28, 2021, 7:07am UTC](https://swi-prolog.discourse.group/t/access-to-gpio-on-raspberry-pi/4438/13 "2021-09-28T07:07:49Z")

</div>

> [@swi](#):
>
> Should probably be fixed on the ffi add-ons README also.

Fixed. Also updated version and pushed a new version with the issue solved for Nicos using this package on the Raspberry pi using Ubuntu 21.04 (variation in `ldconfig` output and deal with systems where `char` is by default _unsigned_). The library now provides a primitive type `schar` next to `uchar` and `char`, where `schar` is explicitly signed and `char` does what the compiler does by default.
