BeagleBone Black – Digital output using C/C++

Did some more digging after my last post and came up with C++ example for digital output on the BBB. I used it to drive an LED. This example controls GPIO1_28 (pin 12 on the P9 header). All the pins are listed on the user manual. Note that this pin is treated as pin 60 in the code. This is how it’s set up in Linux. Here’s how to convert. GPIOn_m is n x 32 + m. So GPIO1_28 is 32 x 1 + 28 = 60.

There are four steps to the process of using a GPIO pin. First, you export the pin, i.e. tell the OS that you want to use it for something. Second, you set the direction, e.g. “out” in this case. Third, you do what you want with the pin. In this example we toggle it between high and low. Fourth, when you are done with the pin, you must unexport it. Doing any of the above four steps with pins is like writing to a file. That’s why you need to check if the file is accessible right before every file write. And right after the file write, you need to close the file handle. It seems that this needs to be done after every file write. If you blink an LED 50 times, you close the handle after each high/low event.

Lastly, a note on the hardware side of things. The BBB is a 3.3V board and is NOT 5V tolerant. The recommended source/sink current is only about 4-6 mA. So if you’re driving an LED, use a transistor, say, a PN2222A. Use a 10K resistor on the base, and 100 ohm on the collector. For this setup, connect pin 7 on the P9 header (SYS_5V) to the LED. This is 5V from the USB. Connect the ground to pin 45 (GND) on the P9 header. Be sure to check the data sheet for your transistor. Different variations of the same transistors have different pinouts. I nearly connected mine all wrong while looking at the connections in one video I was following. Turned out I had a different 2222 transistor with different pinouts.

Hope this helps other new BBB users like me!

/*******************************************************
* Example code for digital output on a GPIO pin
* on the new beaglebone black running the
* Linux Angstrom distribution.
********************************************************
* 
* Instructions:
* -Compile and run from the root directory
* -Windows users can use WinSCP to transfer
* code files to the beaglebone. This will
* allow you to edit code in your favorite
* editor on Windows
* -It is recommended that you do not try to
* source more than 4 - 6 mA. Use a transistor
* e.g. the PN2222A to source higher currents,
* such as for driving an LED
*
* Code adapted from:
* - Derek Molloy, "Beaglebone: C/C++ Programming
* Introduction for ARM Embedded Linux Development
* using Eclipse CDT" video tutorial,
* (link: <a href="http://www.youtube.com/watch?v=SaIpz00lE84" title="http://www.youtube.com/watch?v=SaIpz00lE84">http://www.youtube.com/watch?v=SaIpz00lE84</a>)
* -  Mark A. Yoder, EBC Exercise 10 Flashing an LED
* (link: http://www.elinux.org/EBC_Exercise_10_Flashing_an_LED)
*
*******************************************************/

#include <stdio.h>
#include <unistd.h>
#include <string.h>

using namespace std;

int main(int argc, char** argv) {

    int GPIOPin=60, /* GPIO1_28 or pin 12 on the P9 header */ times=10;

    printf("\nStarting GPIO output program\n");
    FILE *myOutputHandle = NULL;
    char setValue[4], GPIOString[4], GPIOValue[64], GPIODirection[64];
    sprintf(GPIOString, "%d", GPIOPin);
    sprintf(GPIOValue, "/sys/class/gpio/gpio%d/value", GPIOPin);
    sprintf(GPIODirection, "/sys/class/gpio/gpio%d/direction", GPIOPin);

    // Export the pin
    if ((myOutputHandle = fopen("/sys/class/gpio/export", "ab")) == NULL){
        printf("Unable to export GPIO pin\n");
        return 1;
    }
    strcpy(setValue, GPIOString);
    fwrite(&setValue, sizeof(char), 2, myOutputHandle);
    fclose(myOutputHandle);

    // Set direction of the pin to an output
    if ((myOutputHandle = fopen(GPIODirection, "rb+")) == NULL){
        printf("Unable to open direction handle\n");
        return 1;
    }
    strcpy(setValue,"out");
    fwrite(&setValue, sizeof(char), 3, myOutputHandle);
    fclose(myOutputHandle);

    for(int i=0; i<times; i++){
        // Set output to high
        if ((myOutputHandle = fopen(GPIOValue, "rb+")) == NULL){
            printf("Unable to open value handle\n");
            return 1;
        }
        strcpy(setValue, "1"); // Set value high
        fwrite(&setValue, sizeof(char), 1, myOutputHandle);
        fclose(myOutputHandle);
        sleep(1); // wait for 1 sec

        // Set output to low
        if ((myOutputHandle = fopen(GPIOValue, "rb+")) == NULL){
            printf("Unable to open value handle\n");
            return 1;
        }
        strcpy(setValue, "0"); // Set value low
        fwrite(&setValue, sizeof(char), 1, myOutputHandle);
        fclose(myOutputHandle);
        sleep(1); // wait for 1 sec

    }

    // Unexport the pin
    if ((myOutputHandle = fopen("/sys/class/gpio/unexport", "ab")) == NULL) {
        printf("Unable to unexport GPIO pin\n");
        return 1;
    }
    strcpy(setValue, GPIOString);
    fwrite(&setValue, sizeof(char), 2, myOutputHandle);
    fclose(myOutputHandle);
    printf("\nCompleted GPIO output program\n");

    return 0;
}

Advertisements

BeagleBone Black – Controlling user LEDs using C/C++

The $45 BeagleBone Black is here! With all its GPIO ports, it can be a great tool for robotics projects. It ships with javascript example code (in the Cloud9 IDE). There are many examples on the internet showing pin manipulation with javascript and python. There are lots of examples on pin manipulation from the terminal. Unfortunately for a new BBB owner, I could only find suggestions on how to do this on C/C++. I could not find a complete, short, and plain C/C++ example which I could just copy and use as a starting point…something like the traditional “blink” example. Some people have posted their own C++ libraries for pin manipulation, but I find that confusing without understanding the basic concepts.

After a lot of digging, ssh-ing, and g++-ing, I finally got a “blink” example up and running on C++. Here it is. Hopefully, for all the new BBB users out there, this can serve as a starting point in understanding how to use the GPIO ports through C/C++.


/*******************************************************
 * Example code for user LEDs on the new beaglebone
 * black running the Linux Angstrom distribution
 ********************************************************
 * Instructions:
 * -Compile and run from the root directory
 * -For the older (white) beaglebone, change
 *  "beaglebone:green:usr0" to "beaglebone::usr0"
 *
 * Code adapted from:
 * - Derek Molloy, "Beaglebone: C/C++ Programming
 * Introduction for ARM Embedded Linux Development
 * using Eclipse CDT" video tutorial,
 * (link: www.youtube.com/watch?v=vFv_-ykLppo)
 * -  Mark A. Yoder, EBC Exercise 10 Flashing an LED
 * (link: "elinux.org/EBC_Exercise_10_Flashing_an_LED)
 *******************************************************/

#include <stdio.h>
#include <unistd.h>

using namespace std;

int main(int argc, char** argv) {

  FILE *LEDHandle = NULL;
  char *LEDBrightness = "/sys/class/leds/beaglebone:green:usr0/brightness";
  printf("\nStarting simple LED blink program\n");

  while(1){

    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
      fwrite("1", sizeof(char), 1, LEDHandle);
      fclose(LEDHandle);
    }

    sleep(1);

    if((LEDHandle = fopen(LEDBrightness, "r+")) != NULL){
      fwrite("0", sizeof(char), 1, LEDHandle);
      fclose(LEDHandle);
    }

    sleep(1);
  }
  return 0;

}