Love Pulse Posted December 29, 2019 Share Posted December 29, 2019 My last post, part 4 in the GPIO Programming series, showed some ways to program GPIO from Python. Python offers a number of advantages as a programming language including a short learning curve, no need for compilation, and the availability of many add-on modules. However, true compiled languages like C or C ++ can offer some advantages in embedded applications, such as higher performance. Because you are working closer to the level of the hardware you don't have to worry about what a JIT compiler or interpreter might be doing. If desired, you can look at the compiler's generated code or even use in line assembly language. There is also no need to ship full source code to end users. That said, you still should not expect to do hard real-time programming under a standard Linux-based system. But you often can do soft real-time, such as reading buttons and slow sensors, driving LEDs, motors, etc. In this installment we'll look at a couple of ways to control GPIO hardware from the C programming language. The examples will also be valid C ++ programs. Note that if you want to try running this program, it is recommended to run it as root, otherwise you may run into file locking timing issues with udev that cause access errors. I did some benchmarking of this example on a Raspberry Pi 3B. With delays removed, it would toggle the GPIO pin at a rate of about 350 kilohertz. This gives some idea of what can be done at this level of programming. Without using other programming tricks, there is no guarantee that the program won't be periodically preempted to run other tasks. The size of the binary when optimized and stripped was about 6K. and it had few dependencies on other shared libraries. This is several orders of magnitude smaller than Python, for example. The Raspberry Pi also has hardware support for PWM on some pins, and other features that can help optimize programs like this, and there are other performance optimization techniques like direct GPIO register access. We may look at this in a future post. WiringPi WiringPi [1] is a GPIO access library for the Raspberry Pi. Written in C, it is usable from C or C ++ or any language than can call C APIs. Third party bindings for a number a number of languages including Ruby, Python, and Perl are also available. Released under a GNU LGPLv3 license. it is available from Raspbian Linux or you can build it from source. It supports a similar API to the Wiring IDE supported on Arduino microcontrollers, making it easier to port hardware control code between the Raspberry Pi and Arduino platforms. As well as the Raspberry Pi GPIO pins, it also supports some add-on boards like the PiFace and Gertboard. The gpio command we looked at in an earlier blog post is part of WiringPi. The library provides basic functions to read and write pins, including pullup and pulldown resistors and hardware PWM. It also provides routines for software delays down to the microsecond level. There is also support for higher level protocols including serial, SPI, and I2C. In practice, WiringPi is very easy to use. Functions are defined in the header file <wiringPi.h>. You call a setup function to initialize the library, set the GPIO pin modes, and then call methods to read or write. The trickiest issue is probably getting the pin numbers correct - WiringPi uses a pin numbering convention based on the Broadcom SOM channel names, not physical pins. The documentation covers this (and the command gpio readall will also show it in tabular form). There is also a function you can call to convert physical pin numbers to WiringPi numbers. I did a few performance measurements on the code in demo2.c. Running the loop with no delays produced a GPIO pin cycling at a rate of almost 12 MHz on a Raspberry Pi 3. The main reason for the high performance is that it uses direct register access to avoid the kernel / user space context switching and other overhead needed with sysfs. Using delays of delayMicroseconds (10) produced a very consistent and accurate 50 kHz square wave. Conclusions These examples, implemented in C or C ++, are more representative of how commercial and industrial embedded applications are usually written. The resource requirements are significantly lower and performance is higher than when using Python or other interpreted languages. The cost is the additional complexity in programming and building. I highly recommend using WiringPi as it is high performance and provides a nice API for programming. It's main downside is being tied to the Raspberry Pi platform. Shortly before I wrote this blog post, the new Raspberry Pi 4 was released. This model is approximately three times faster and has a number of features and performance improvements. Initial benchmarks indicate it is significantly faster at GPIO handling than the Pi 3. The new model needs new version of the WiringPi, which was available on release day of the Raspberry Pi 4, but not yet included in Raspbian Linux as a package. Link to comment Share on other sites More sharing options...
Recommended Posts