Introduction to accessing the Raspberry Pi’s GPIO in C++ (sysfs)

Introduction

In this blog entry I will demonstrate how one can access the Raspberry Pi’s GPIO in C++. There are two approaches to accomplish this. The first is to directly manipulate the Raspberry Pi’s GPIO’s registers much like one would do when programming a microcontroller without an operating system (OS) or a memory management unit (approach using mmap). The advantage of this approach is that because the OS (Linux) is being completely bypassed, the GPIO pins can toggle very fast. Bypassing the OS however means that if two processes (instances of a programs) are trying to access the same physical GPIO registers at the same time, a unsafe resource conflict can happen. Examples of this approach to GPIO coding can be found here.

The second approach is the “Linux approach” (sysfs). Linux already has a built-in driver for safely accessing the GPIOs. It basically views each property of each GPIO pin as a file. This is the preferred method of GPIO access. One disadvantage of this approach is that it tends to make for slower (but safer) GPIO pin toggling. Example code for this approach can be found here, and a wiki on how to access GPIO signals using this approach can he found here. This approach will be used in this tutorial. The file accesses will be wrapped in a C++ class to make GPIO access easy and foolproof (sort of).

Setting up the  test hardware

In order to test our GPIO access program we will need to connect the GPIO pins to actual hardware components. I decided to to use GPIO pin 4 as an output pin that turns on an LED and GPIO pin 17 as an input pin that reads the state of a pushbutton. A connection diagram is provided in Figure 1.

Figure 1 Raspberry Pi Connection Diagram

Figure 1 Raspberry Pi Connection Diagram

GPIO4 is connected to an LED via a 330Ohm current limiting resistor. GPIO17 is connected to a 10KOhm pull-up resistor and a push-button. An unpressed pushbutton will cause the voltage on GPIO17 to be 3.3V. When the button is pressed, the voltage of GPIO17 will be 0V.

The connections between the Raspberry Pi and the other parts can be made via Male-to Female jumper wires or via one of Adafruit’s Pi cobbler kits (ver1  or ver2).

Accessing GPIO From the Terminal

  • When using the Linux (sysfs) way to access GPIO, we must ensure that we’re logged in as root:
pi@raspberrypi ~ $ sudo -i
  • we then must “export the pin” in question. For example to use pins GPIO4 & 17 we  must first export them by writing the GPIO pin numbers to the file “/sys/class/gpio/export” as follows:
root@raspberrypi:~# echo "4" > /sys/class/gpio/export
root@raspberrypi:~# echo "17" > /sys/class/gpio/export

The next step is to set pin 4 as output and pin 17 as input. This is achieved by writing “out” into the “/sys/class/gpio/gpio4/direction” file and writing “in” into the “/sys/class/gpio/gpio17/direction” file as follows:

root@raspberrypi:~# echo "out" > /sys/class/gpio/gpio4/direction
root@raspberrypi:~# echo "in" > /sys/class/gpio/gpio17/direction

To set the output GPIO4 pin high and therefore cause the LED to light-up, we need to write a “1” to the “/sys/class/gpio/gpio4/value” file:

root@raspberrypi:~# echo "1" > /sys/class/gpio/gpio4/value

To clear the output GPIO4 pin to low and therefore cause the LED to turn off we need to write a “0” to the “/sys/class/gpio/gpio4/value” file:

root@raspberrypi:~# echo "0" > /sys/class/gpio/gpio4/value

To read the state of the input pin GPIO17, we need to read the “/sys/class/gpio/gpio17/value” file.  This will return either a “0” if the pin is connected to 0V or a “1” if the pin is connected to 3.3V:

root@raspberrypi:~#cat /sys/class/gpio/gpio17/value

And finally, when we’re done with the GPIO pins we must unexport them by writing the GPIO pin numbers to the “/sys/class/gpio/unexport” file!

root@raspberrypi:~#echo "4" > /sys/class/gpio/unexport
root@raspberrypi:~#echo "17" > /sys/class/gpio/unexport

Notice how the sysfs approach reduces the problem of GPIO access to reading and writing files! This is by the way the norm for Linux. All I/O access (serial ports, console, printers e.t.c.) involves reading to and writing from files. The next step will be to perform the same functions in C++!

Writing a GPIO C++ Class

The goal of the GPIOClass class is to enable the control of a single GPIO  pin. The class was designed so that the GPIO pin number must be passed to the GPIOClass object when its created via an overloaded constructor. The “GPIOClass.h” header file is provided below

#ifndef GPIO_CLASS_H
#define GPIO_CLASS_H

#include <string>
using namespace std;
/* GPIO Class
 * Purpose: Each object instantiated from this class will control a GPIO pin
 * The GPIO pin number must be passed to the overloaded class constructor
 */
class GPIOClass
{
public:
    GPIOClass();  // create a GPIO object that controls GPIO4 (default
    GPIOClass(string x); // create a GPIO object that controls GPIOx, where x is passed to this constructor
    int export_gpio(); // exports GPIO
    int unexport_gpio(); // unexport GPIO
    int setdir_gpio(string dir); // Set GPIO Direction
    int setval_gpio(string val); // Set GPIO Value (putput pins)
    int getval_gpio(string& val); // Get GPIO Value (input/ output pins)
    string get_gpionum(); // return the GPIO number associated with the instance of an object
private:
    string gpionum; // GPIO number associated with the instance of an object
};

#endif

Each GPIOClass object has member functions that enable us to export/unexport GPIO pins, set the direction of the GPIO pins as well as set and get the value of the GPIO pins. The GPIOClass object has one private variable which is the GPIO pin number. The implementation of these member functions  are provided below “GPIOClass.cpp”:

#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include "GPIOClass.h"

using namespace std;

GPIOClass::GPIOClass()
{
	this->gpionum = "4"; //GPIO4 is default
}

GPIOClass::GPIOClass(string gnum)
{
	this->gpionum = gnum;  //Instatiate GPIOClass object for GPIO pin number "gnum"
}

int GPIOClass::export_gpio()
{
	string export_str = "/sys/class/gpio/export";
	ofstream exportgpio(export_str.c_str()); // Open "export" file. Convert C++ string to C string. Required for all Linux pathnames
	if (exportgpio < 0){
		cout << " OPERATION FAILED: Unable to export GPIO"<< this->gpionum <<" ."<< endl;
		return -1;
	}

	exportgpio << this->gpionum ; //write GPIO number to export
    exportgpio.close(); //close export file
    return 0;
}

int GPIOClass::unexport_gpio()
{
	string unexport_str = "/sys/class/gpio/unexport";
	ofstream unexportgpio(unexport_str.c_str()); //Open unexport file
	if (unexportgpio < 0){
		cout << " OPERATION FAILED: Unable to unexport GPIO"<< this->gpionum <<" ."<< endl;
		return -1;
	}

	unexportgpio << this->gpionum ; //write GPIO number to unexport
    unexportgpio.close(); //close unexport file
    return 0;
}

int GPIOClass::setdir_gpio(string dir)
{

	string setdir_str ="/sys/class/gpio/gpio" + this->gpionum + "/direction";
	ofstream setdirgpio(setdir_str.c_str()); // open direction file for gpio
		if (setdirgpio < 0){
			cout << " OPERATION FAILED: Unable to set direction of GPIO"<< this->gpionum <<" ."<< endl;
			return -1;
		}

		setdirgpio << dir; //write direction to direction file
		setdirgpio.close(); // close direction file
	    return 0;
}

int GPIOClass::setval_gpio(string val)
{

	string setval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
	ofstream setvalgpio(setval_str.c_str()); // open value file for gpio
		if (setvalgpio < 0){
			cout << " OPERATION FAILED: Unable to set the value of GPIO"<< this->gpionum <<" ."<< endl;
			return -1;
		}

		setvalgpio << val ;//write value to value file
		setvalgpio.close();// close value file 
	    return 0;
}

int GPIOClass::getval_gpio(string& val){

	string getval_str = "/sys/class/gpio/gpio" + this->gpionum + "/value";
	ifstream getvalgpio(getval_str.c_str());// open value file for gpio
	if (getvalgpio < 0){
		cout << " OPERATION FAILED: Unable to get value of GPIO"<< this->gpionum <<" ."<< endl;
		return -1;
			}

	getvalgpio >> val ;  //read gpio value

	if(val != "0")
		val = "1";
	else
		val = "0";

	getvalgpio.close(); //close the value file
    return 0;
}

string GPIOClass::get_gpionum(){

return this->gpionum;

}

In order to open and close files in C++, the ifstream/ofstream  classes where used. Even though the C++ string class was used, the C++ strings had to be converted into C strings since pathnames in Linux can only be interpreted as C strings.  The GPIOClass is pretty self explanatory. It is also very basic I intend to clean in up a bit in the future, but for now it will have to do.

Writing a Test Main

A main program “GPIOtest1.cpp that tests this class is provided below:

#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "GPIOClass.h"

using namespace std;

int main (void)
{

	string inputstate;
	GPIOClass* gpio4 = new GPIOClass("4"); //create new GPIO object to be attached to  GPIO4
	GPIOClass* gpio17 = new GPIOClass("17"); //create new GPIO object to be attached to  GPIO17

	gpio4->export_gpio(); //export GPIO4
	gpio17->export_gpio(); //export GPIO17

	cout << " GPIO pins exported" << endl;

	gpio17->setdir_gpio("in"); //GPIO4 set to output
	gpio4->setdir_gpio("out"); // GPIO17 set to input

	cout << " Set GPIO pin directions" << endl;

	while(1)
	{
		usleep(500000);  // wait for 0.5 seconds
		gpio17->getval_gpio(inputstate); //read state of GPIO17 input pin
		cout << "Current input pin state is " << inputstate  <<endl;
		if(inputstate == "0") // if input pin is at state "0" i.e. button pressed
		{
		    cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
	            usleep(20000);
                    cout << "Checking again ....." << endl;
                    gpio17->getval_gpio(inputstate); // checking again to ensure that state "0" is due to button press and not noise
		    if(inputstate == "0")
		    {
		    	cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
		    	gpio4->setval_gpio("1"); // turn LED ON

		    	cout << " Waiting until pin is unpressed....." << endl;
		    	while (inputstate == "0"){ 
		    	gpio17->getval_gpio(inputstate);
		    	};
		    	cout << "pin is unpressed" << endl;

		    }
		    else
		    	cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;

		}
		gpio4->setval_gpio("0");

	}
	cout << "Exiting....." << endl;
	return 0;
}

The GPIOtest1.cpp program is pretty straightforward. It first instantiates two GPIOClass objects attached to GPIO4 & GPIO17 (gpio4 and gpio17) on the heap. Note that the object names was chosen to reflect the GPIO pin number but could’ve been called anything else.

The GPIOs are then exported, GPIO4 set to output and GPIO17 set to input. At this point code execution enters into an infinite loop that reads the status of the input pin GPIO17. If the pin has a state of “0”, this means that the button could be pressed. The state of the GPIO17 pin is checked again to ensure that this is indeed the case. If so the GPIO4 pin is set to high, causing the LED to turn ON. Another while loop ensures that the LED is ON, so long as the button continues to be pressed. Note that line before “return 0;” , “cout << “Exiting…..” << endl;” never executes.

Using Signals

There is a major flaw in this program and that is, the only way to exit the program is to press ctrl-C. Terminating the program in this way means that the program is unable to unexport the GPIO pins. More importantly it means that the program is unable to free the heap memory allocated for GPIOClass objects gpio4 & 17.

One way of fixing this problem is to write a signal handler (software interrupt handler) and attach it to the SIGINT (ctrl-C) signal (event). This enables the program to jump to the signal handler whenever ctrl-C is pressed, instead of directly exiting the program. The signal handler can then initiate a graceful exit of the program i.e. deallocate heap memory and unexport pins before exiting. First we have to include:

#include <signal.h>

The next step is then instantiate a sigaction struct and to fill it  as follows:

struct sigaction sig_struct;
sig_struct.sa_handler = sig_handler;
sig_struct.sa_flags = 0;
sigemptyset(&sig_struct.sa_mask);

The first line above instantiates a sigaction struct called sig_struct. The second line causes the signal handler field (sa_handler) of sig_struct to point to a function called “sig_handler”. The “sa_flags” in the sigaction structure can be used to trigger certain behaviors that modify the signal event. The sa_flags field was chosen to be zero because the functionality it provides is not needed.  Finally the last line of code ensures that the sa_mask field of the sigaction structure is empty. The sa_mask field enables certain additional set of signals to be blocked during execution of signal handler function.

Once the sigaction struct “sig_struct” is completed, the “sigaction” function is used to map the filled “sig_struct” structure with the SIGINT signal  as follows:

if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
		cout << "Problem with sigaction" << endl;
		return -1;
	}

We will also need to write the signal handler function “sig_handler”. This function’s entire purpose is to set a global boolean variable (a flag). When ctrl-C is pressed, program execution immediately jumps to the signal handler function and sets this boolean variable (flag) to “true”. In the infinite while loop in main this flag is polled. If it is asserted (by the signal handler), the program then exits gracefully ensuring all heap memory is deallocated and GPIO pins unexported properly.

void sig_handler(int sig)
{
	write(0,"nCtrl^C pressed in sig handlern",32);
	ctrl_c_pressed = true;
}

It is important to note here that functions called in signal handler functions must be re-entrant.  This is why the re-entrant “write” function was used instead of the non-re-entrant printf  or cout. The flag variable used in this example is “ctrl_c_pressed”.

The additional code added to the main program’s infinite while loop allows the program to exit gracefully and is provided below:

if(ctrl_c_pressed)
{
	cout << "Ctrl^C Pressed" << endl;
	cout << "unexporting pins" << endl;
	gpio4->unexport_gpio();
	gpio17->unexport_gpio();
	cout << "deallocating GPIO Objects" << endl;
	delete gpio4;
	gpio4 = 0;
	delete gpio17;
	gpio17 =0;
	break;

}

The complete code is provided below “GPIOTest2.cpp”

#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "GPIOClass.h"
using namespace std;

void sig_handler(int sig);

bool ctrl_c_pressed = false;

int main (void)
{

	struct sigaction sig_struct;
	sig_struct.sa_handler = sig_handler;
	sig_struct.sa_flags = 0;
	sigemptyset(&sig_struct.sa_mask);

	if (sigaction(SIGINT, &sig_struct, NULL) == -1) {
		cout << "Problem with sigaction" << endl;
		exit(1);
	}

	string inputstate;
	GPIOClass* gpio4 = new GPIOClass("4");
	GPIOClass* gpio17 = new GPIOClass("17");

	gpio4->export_gpio();
	gpio17->export_gpio();

	cout << " GPIO pins exported" << endl;

	gpio17->setdir_gpio("in");
	gpio4->setdir_gpio("out");

	cout << " Set GPIO pin directions" << endl;

	while(1)
	{
		usleep(500000);
		gpio17->getval_gpio(inputstate);
		cout << "Current input pin state is " << inputstate  <<endl;
		if(inputstate == "0")
		{
		   cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
		   usleep(20000);
                   cout << "Checking again ....." << endl;
                   gpio17->getval_gpio(inputstate);
		    if(inputstate == "0")
		    {
		    	cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
		    	gpio4->setval_gpio("1");

		    	cout << " Waiting until pin is unpressed....." << endl;
		    	while (inputstate == "0"){
		    		gpio17->getval_gpio(inputstate);
		    	};
		    	cout << "pin is unpressed" << endl;

		    }
		    else
		    	cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;

		}
		gpio4->setval_gpio("0");

		 if(ctrl_c_pressed)
				    {
				    	cout << "Ctrl^C Pressed" << endl;
				    	cout << "unexporting pins" << endl;
				    	gpio4->unexport_gpio();
				    	gpio17->unexport_gpio();
				    	cout << "deallocating GPIO Objects" << endl;
				    	delete gpio4;
				    	gpio4 = 0;
				    	delete gpio17;
				    	gpio17 =0;
				    	break;

				    }

	}
	cout << "Exiting....." << endl;
	return 0;
}

void sig_handler(int sig)
{
	write(0,"nCtrl^C pressed in sig handlern",32);
	ctrl_c_pressed = true;
}

It is important to note that in order for any of these programs to execute properly you need to run them as root either via the sudo command (i.e. “sudo ./GPIOtest) or preferably login into to your root account with “sudo -i” before running the GPIO based program(s).

For those of you interesting in learning more about Linux system programming, I highly recommend Beej’s Guide to Unix Interprocess Communication. For those that would like to learn even more, check out the following books:

This concludes our introduction to GPIO access in C++!!!  The source code discussed in this blog entry can be found (git)here.

UPDATE (26-08-2013). I’ve added a slightly modified version of the GPIOClass C++ class discussed above (git)here . This version makes the export & unexport functions private and calls them in the constructor & destructor respectively. This way the GPIO pins are automatically exported on object creation and unexported just before object destruction. I’ve also used the C system calls to do the File I/O as opposed to the C++ fstream (File I/O) libraries.

 

 

This entry was posted in Raspberry Pi, Raspberry Pi Peripherals. Bookmark the permalink.

54 Responses to Introduction to accessing the Raspberry Pi’s GPIO in C++ (sysfs)

  1. Jorge says:

    Hi Hussam Al-Hertani,

    First, apologize for my english.
    Second, thanks a lot your great tutorial.
    I’m making a similar job, I want to read the imput button, and then make an action, like take a photo or similar.

    Searching through internet i saw that the button need a resitor and I don’t know why and what the value of resistor (OHmios)

    thanks in advance,

    Jorge

  2. Jorge says:

    maybe a 1kohm for the resistor of the button??

    brown
    black
    red
    golden

    • halherta says:

      The resistor attached to the button and GPIO 17 (input pin) is a 10Kohm pullup resistor. This resistor ensures that the voltage on the input pin is pulled to 3.3V unless the button is pressed, at which point the voltage on the input pin will be 0V.

      The resistor connected in series with the LED is a 330 Ohm resistor and limits current going through the pin to ILED= (VCC-VLED)/R = (3.3-2.0)/330 = 3.9mA

      • Jorge says:

        thanks for you answer.

        Finally I did the circuit with two leds, two resistors and one button.
        this job it’s based in the gordon’s project (https://projects.drogon.net/raspberry-pi/gpio-examples/tux-crossing/3-more-leds-and-a-button/) and work fine.

        From the gordon project, refer to the button and gpio pin:
        ” The button is connected to wiringPi pin 8, (GPIO-0/SDA0), and the other side is connected to 0v. This pin has a 1.8KΩ resistor connecting it to +3.3v on the Raspberry Pi board ”

        So, I think that my raspberry it’s protected, yes??

        Thanks a lot

        • halherta says:

          Jorge the SDA0/SCL0 pins on the raspberry pi have 1.8K pull-up resistors connected to them on the board already as this is required by the I2C Spec. So yes you can simply attach a button to that pin without an additional pull-up. This 1.8K Pull-up is indeed adequate.

  3. Dominic Clifton says:

    Thanks for making the article.

  4. max says:

    Just curious about your Makefile, LDFLAGS and linking step to stdc++ …

  5. Jimbo says:

    So… not sure how many have tried the actual code listed above.
    1.) Thanks for quick tutorial and detailed explanation of your code.
    2.) GPIOClass.cpp needs to be included, not GPIOClass.h since it is included in GPIOClass.cpp
    3.) Ctrl^c is caught by the handler and gives the desired prompt but it doesn’t actually end the program loop. Currently thinking on how to fix this… (my c is a bit rusty, hence why I found and tried this tutorial)

    • halherta says:

      2).I tried this code and it worked…at least for me. I cross compiled the code (from my Kubuntu machine) with eclipse….You cannot explicitly include a .cpp file like #include “GPIOClass.cpp” . This simply won’t work. To build natively on the RaspberryPi put the GPIOClass.cpp GPIOClass.h & GPIOtest1.cpp in the same directory then invoke g++ as such “g++ -Wall -o GPIOtest1 GPIOClass.cpp GPIOtest1.cpp”. This command will look for the header file in the work directory by default. You’re explicitly telling the compiler to compile both src files.

      3.)Perhaps ctrl^C might not be mapped to SIGINT ??? though that’s unlikely.

      Please let me know if you manage to fix the problem.

      • Matt says:

        when I compile GPIOtest1.cpp only, it compiles, but doesn’t change the output of the pins when I run the program. When I compile GPIOClass.cpp, I get ‘multiple definition of’ errors.

        BTW thanks for the help with including the .cpp instead of .h.

        Matt

  6. Mihai Ignat says:

    Hello. Can you tell me, please, which program did you use to create this schematic:
    http://hertaville.com/wp-content/uploads/2012/11/RasberryPiGPIO1.jpg ?
    Thank you.

  7. Diaan says:

    Thank you! Finally found something that works. The
    #include "GPIOClass.cpp"
    is required, i kept getting linking errors without it! Great Tutorial.

  8. Joerg says:

    Hello,
    I have tried to put Your code in a QT application.
    But I get this error
    “/home/joerg/qtwork/LEDControl/ledcontroll.cpp:36: error: ‘gpio26′ was not declared in this scope”

    and have no idea to fix it.

    Thats the whole Project: https://dl.dropboxusercontent.com/u/98706767/LEDControl.zip

    Please help ;)

    Joerg

    • halherta says:

      Joerg, the “gpio26″ pointer variable of type GPIOClass is not declared in the scope of the LEDcontrol object as such the LEDControl object does not identify it. I’m not well versed in QT enough to help you fix this….perhaps add a variable parameter of type GPIOClass to the LEDCOntrol object and pass gpio26 by reference to LEDControl object ????? BTW i don’t think that gpio26 exists on the Pi!!!!

      Also What setup are you using ? You seem to be using QTCreator/QT-designer..are you using a cross compiling setup for QT4 ? if so I’d appreciate any pointers myself as I’d love to figure out how to cross compile QT4 applications for the Raspberry Pi.

      Take a look at this example….I got a very simple QT app to toggle an LED using the GPIOClass class. I did not use QTcreator…it’s all pure C++ developed and compiled natively on the Raspberry Pi. Hope it helps

  9. Joerg says:

    Yes I use Qt Creator and cross compile but not for pi. I use i.mx6 board. SabreLite and Mars. Its a little more powerfull as pi ;)

    On my search on web I found a lot about qt and pi.
    http://qt-project.org/wiki/RaspberryPi_Beginners_guide
    This should help You

  10. Joerg says:

    I get help on QT Forum and it works now :)

    To access gpio the program need to be root. Must be possible to change that. It will not be nice to open that door.

    • halherta says:

      Take a look at this example….I got a very simple QT app to toggle an LED using the GPIOClass class. I did not use QTcreator…it’s all pure C++ developed and compiled natively on the Raspberry Pi. Hope it helps

    • halherta says:

      Yes I had the same problem…If you run the GUI from HDMI…no problems (just sudo it). If running the GUI over an Xserver (ssh X tunneling or VNC) it will fail…..I succeeded by moving the .Xauthority in /home/pi to /root and change its permissions to 555

  11. Joerg says:

    sudo the program is the same as run it as root with ssh.
    So I thinking about changes permission of the /sys/class directory

    but tomorrow. It is midnight here now ;)

  12. Joerg says:

    Hi,
    did You get QT creator running?
    I figured out something to use a other user
    sudo nano /etc/udev/rules.d/99-gpio.rules
    paste:
    SUBSYSTEM==”gpio”, ACTION==”add”, PROGRAM=”/bin/sh -c ‘chown -R linaro:linaro /sys%p'”
    PROGRAM=”/bin/sh -c ‘chown -R linaro:linaro /sys/class'”

    save and reboot

    Joerg

    • halherta says:

      Joerg,
      Does that change the permissions of the /sys/class directory structure to user ‘linaro’ ? thanks for letting me know !
      As for QT, I didn’t get QTCreator running. It is not a major priority for me at this time. Also I’m happy developing QT natively on the Pi in pure c++ code w/o QT designer/creator

      thanks again!

  13. Joerg says:

    I have a problem.

    I only use one GPIO

    so I do
    gpio26 = new GPIOClass(“26″); //create new GPIO object to be attached to GPIO26
    gpio26->export_gpio(); //export GPIO26

    gpio26->setdir_gpio(“out”); //GPIO26 set to output

    i think the problem i must wait for execution of export. i try some for next but i think thats not work because first my for next are executed and than set dir

    so is it possible to ask “linux” that export is ready before do direction ?

    • halherta says:

      Joerg if you look at the export function, It opens the /sys/class/gpio/export file…writes 26 to it and then closes the file. Once the file is closed, the /sys/class/gpio/gpio26 file should appear immediately….so there should be no delay to export the gpio pin. Perhaps the file permission modification of /sys/class/gpio is causing this problem?

      • Joerg says:

        I put the things on a button
        press export
        press direction

        and it works

        when the program do it don´t work

        set direction is missing then

  14. Joerg says:

    you can test that on pi please?

    • halherta says:

      Joerg, I tested my example code (no gui) as root & without changing /sys/class permissions. That worked just fine i.e. gpio pins (4 & 17…no 26 on Pi) are exported and function normally.

    • halherta says:

      Joerg, I also re-tested the QT example code i posted in the comments section a few days ago. It also works fine when executed with sudo (i.e. with root permission). One problem with my example is that it doesn’t unexport the pins befor exit….because it was written that way….but pin exporting, setting direction and output work no problems on my Raspberry Pi. What kernel are you running? This is a shot in the dark…but I know with Kernel 3.8 & beyond you may have to rely of Device Tree Overlays for pin configuration….could this be the problem in your case ?

      Also if you’re testing this with your screen attached to your ARM board directly through an HDMI/VGA interface you should be ok. If however you’re running the GUI on a VNC server/ssh x tunneling, the X server will complain (application is run under root but x-server is still run by user). One workaround is to copy the .Xauthority file from the home directory of the RPi (or other ARM board) and copy it to root directory of the RPi (or other ARM board), then change its permission to 555.

      • Joerg says:

        i would like to see if it works on pi when you change permission with udev and run with pi user

        i running x-server direct on 22″ hdmi with touch ;)

  15. halherta says:

    I followed your instructions i.e. :
    create file on the Pi:
    sudo nano /etc/udev/rules.d/99-gpio.rules

    paste:
    SUBSYSTEM==”gpio”, ACTION==”add”, PROGRAM=”/bin/sh -c ‘chown -R linaro:linaro /sys%p’”
    PROGRAM=”/bin/sh -c ‘chown -R linaro:linaro /sys/class’”

    I then rebooted the Pi. I was unable to get user access for /sys/class/gpio. When I run the following from the command line “echo ‘4’ > /sys/class/gpio/export” , it tells me permission denied.

    When executing the program..program runs but fails to control gpio (a permission problem).

  16. Diego says:

    Hi, I’ve been trying to control and read the GPIOs from a C++ program. I followed your example and it works fine when I do it from the terminal, but when I do it from inside the program the output never changes and the input always read 1. What could it be?

    • halherta says:

      Diego, you need to run the c++ application as root…i.e. “sudo ./binaryfile_name”. Did you do that already ?

      • Diego says:

        yeap… already tried that

        • halherta says:

          Diego, in my particular example, the output only changes when the input changes…if the input is always 1 then the output will never change…..

          Perhaps the switch/ pushbutton attached to the input is not attached correctly ? Can you verify that the input on the RPi GPIO pin changes when the pushbutton/switch is activated/pressed with a multimeter ?

  17. Diego says:

    Both are attached correctly. If I export the pins manually they work. It’s when I try to do it from a C++ program that it fails to do so. I downloaded the source code you have at GitHub and compiled the examples and they don’t work for me… the input always read “1”. I noticed that if I manually export and configure the GPIOs and then run my program the LED turns on and off, but the switch doesn’t work even if I export it manually (only when I read it manually but never in C++)

  18. retux says:

    halherta,

    Thanks for publishing. I liked the approuch you took, and I learnt some extra things.
    Just changed the error handling, cos’ it wasn’t warking for me. I did it this way:

    if (! exportgpio.is_open() ){
    cout << " OPERATION FAILED: Unable to export GPIO"<gpionum <<" ."<< endl;
    return -1;

    Thanks!

  19. Ruben says:

    fantastic piece of code! thanks a million

  20. Anjesh says:

    wonderful efforts

  21. gyula says:

    Nice, but very slow, going trough the /sys/ file system.
    A mmory mapped approach would be rocket fast.

  22. Thomas says:

    Well… It may be a good job but it just doesn’t compile…
    Why don’t you add any compilation instruction ?

  23. Pingback: Controlling the Raspberry Pi’s GPIOs using Direct Register Access | Hertaville

  24. Jim says:

    You should construct your GPIOClass instances on the stack instead of using new, like this: GPIOClass gpio4("4");

    • halherta says:

      Jim, Agreed! For starters declaring the GPIO objects on the stack looks less intimidating…and makes signal handlers unnecessary.

      Classical example of solving an unnecessarily complex problem by complicating the problem further. That was me 2 years ago…..I’d do this very differently if I were to redo it again today.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>