Orange PI PC - How to use GPIO for push buttons : Tutorial


Recommended Posts

Hi, This topic was a initially a question and become a tutorial to use push buttons on orange pi PC.

This tutorial has been made with an Orange PI PC running on "Armbian_5.35_Orangepipc_Debian_jessie_default_3.4.113.img".

 

With this example you will be able to launch 3 different scripts for each push button : 

/usr/local/bin/run<Wpi GPIO number>short.sh   -> immediately launched when a button is pressed

/usr/local/bin/run<Wpi GPIO number>long.sh  ->  launched after a long pression

/usr/local/bin/run<Wpi GPIO number>release.sh  -> launched when a button is released (but not after a long pression)

 

 

I've made this image to know easily see the correspondence between WiringOP and physical Orange PI PC connector :

 

Pinout2.thumb.jpg.3d6076415349088c1bcd76cf2a26d17e.jpg

 

Mhhh if you want to modify it, you'll find the excel source file here.

 

Sources :

http://orangepi.club/showthread.php?tid=2173     -> excellent tutorial for beginners !

https://github.com/zhaolei/WiringOP     -> a modified WiringPi for OrangePi

http://nix.zeya.org/wiki/разработка_средств_аппаратного_управления_для_orange_pi_pc     -> a very good example of program in C to use Orange PI GPIO with push buttons

 

To install and compile the WiringOP library :

mkdir downloads
cd downloads
git clone https://github.com/zhaolei/WiringOP.git -b h3
cd WiringOP/
sudo ./build

 

Make a test :

gpio readall

 

You should obtain something like that :

 +-----+-----+----------+------+---+-Orange Pi+---+---+------+---------+-----+--+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 |     |     |     3.3v |      |   |  1 || 2  |   |      | 5v       |     |     |
 |  12 |   8 |    SDA.0 | ALT5 | 0 |  3 || 4  |   |      | 5V       |     |     |
 |  11 |   9 |    SCL.0 | ALT5 | 0 |  5 || 6  |   |      | 0v       |     |     |
 |   6 |   7 |   GPIO.7 | ALT3 | 0 |  7 || 8  | 0 | ALT3 | TxD3     | 15  | 13  |
 |     |     |       0v |      |   |  9 || 10 | 0 | ALT3 | RxD3     | 16  | 14  |
 |   1 |   0 |     RxD2 | ALT3 | 0 | 11 || 12 | 0 | ALT3 | GPIO.1   | 1   | 110 |
 |   0 |   2 |     TxD2 | ALT3 | 1 | 13 || 14 |   |      | 0v       |     |     |
 |   3 |   3 |     CTS2 |   IN | 1 | 15 || 16 | 0 | ALT3 | GPIO.4   | 4   | 68  |
 |     |     |     3.3v |      |   | 17 || 18 | 0 | ALT3 | GPIO.5   | 5   | 71  |
 |  64 |  12 |     MOSI | ALT4 | 0 | 19 || 20 |   |      | 0v       |     |     |
 |  65 |  13 |     MISO | ALT4 | 0 | 21 || 22 | 0 | ALT3 | RTS2     | 6   | 2   |
 |  66 |  14 |     SCLK | ALT4 | 0 | 23 || 24 | 0 | ALT4 | CE0      | 10  | 67  |
 |     |     |       0v |      |   | 25 || 26 | 0 | ALT5 | GPIO.11  | 11  | 21  |
 |  19 |  30 |    SDA.1 | ALT5 | 0 | 27 || 28 | 0 | ALT5 | SCL.1    | 31  | 18  |
 |   7 |  21 |  GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v       |     |     |
 |   8 |  22 |  GPIO.22 |   IN | 1 | 31 || 32 | 0 | ALT3 | RTS1     | 26  | 200 |
 |   9 |  23 |  GPIO.23 |   IN | 1 | 33 || 34 |   |      | 0v       |     |     |
 |  10 |  24 |  GPIO.24 |   IN | 1 | 35 || 36 | 0 | ALT3 | CTS1     | 27  | 201 |
 |  20 |  25 |  GPIO.25 | ALT5 | 0 | 37 || 38 | 0 | ALT3 | TxD1     | 28  | 198 |
 |     |     |       0v |      |   | 39 || 40 | 0 | ALT3 | RxD1     | 29  | 199 |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+-Orange Pi+---+------+----------+-----+-----+

 

 

Now we are going to write a program in C to detects pushes on buttons :

nano pushbuttons.c

The copy / paste the C program below :

(you should modify the numbers of buttons that you use, the WiringOP pins that you use, you can create scripts later)

 

Spoiler


// Example of GPIO use On Orange PI PC
// To use with push buttons : this program run scripts when a button is pushed / released or when it is pressed during a long time
// Version 1.0
// By Schmurtz
// https://forum.armbian.com/topic/7067-orange-pi-pc-how-to-use-gpio-for-push-buttons-tutorial/


// Sources :
// http://orangepi.club/showthread.php?tid=2173     -> excellent tutorial for beginners !
// https://github.com/zhaolei/WiringOP     -> a modified WiringPi for OrangePi
// http://nix.zeya.org/wiki/разработка_средств_аппаратного_управления_для_orange_pi_pc  -> a very good example of program in C to use Orange PI GPIO with push buttons */


#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <wiringPi.h>


// === Paramètres personnalisables ===
# define num 4                                        // Number of PINs used

unsigned int nums = 4;                                // Number of PINs used again
unsigned int WpiPinsSelection[] = {21, 22, 23, 24};   // List of GPIO used by buttons in Wpi semantics
unsigned char script_path[50] = "/usr/local/bin/";    // Folder where the scripts will be executed
unsigned int delay_time = 40;                         // Delay in ms between each check of GPIO
// Calculer en fonction du nombre total de boutons.

// === Global Variables ===

unsigned int curr_state[num];       // array of current states
unsigned int old_state[num];        // array of previous states
unsigned int trigg_0;               // trigger event for all inactive inputs
unsigned int act_inputs = 0;        // variable of the number of active inputs

unsigned int i;                     // counter
unsigned int CountTime = 0;         // counter for the time of pressed buttons
unsigned int MaxCountTime = 40;     //  Number of CountTime periods before running a long pression action for example : 40 * 40 = 1600 ms + execution time
unsigned char presstype[7];			// short press , long press or realease


// following pins assignation is probably good only for Orange PI PC only
unsigned int OpiPinsAvailable[] = {3, 5, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 40}; // physical pins
unsigned int WpiPinsAvailable[] = {8, 9, 7, 15, 16, 0, 1, 2, 3, 4, 5, 12, 13, 6, 14, 10, 11, 30, 31, 21, 22, 26, 23, 24, 27, 25, 28, 29}; // wiringPi pins


// === FONCTIONS ===

// Find the physical PIN on opi from selected wiringPi pin
unsigned int find_OpiPin(unsigned int WpiPin )
{
  int j;
  for (j = 0; j < 27; j++)    // We loop through all the pins to find the correct PIN
  {

    if (WpiPin == WpiPinsAvailable[j])
    {
      return OpiPinsAvailable[j];
    }
  }

}


// Function of starting an external process
void run_script(unsigned int act_butt_num, unsigned char ActionType[] )
{
  printf("  =============    Action : %s from WPI pin %d (physical pin %d)    =============\n", ActionType, WpiPinsSelection[i], find_OpiPin(WpiPinsSelection[i]));
  unsigned char command[50];
  sprintf(command, "%s" "%s" "%u" "%s" "%s", script_path, "run", act_butt_num, ActionType, ".sh");  // Create command
  system (command);                 // Run the child process
  return;
}

 // GPIO initialization function
void init_gpio()
{
  wiringPiSetup();              // Select the output numbering system - wiringPi, look at the output wPi column gpio readall
  for (i = 0; i < nums; i++)    // We loop through all the pins and set each parameter
  {
    printf("init WiringOP GPIO %d - Physical Opi PC Pinout : %d \n", WpiPinsSelection[i], find_OpiPin(WpiPinsSelection[i]));
    pinMode(WpiPinsSelection[i], INPUT);            // Set the port function to input
    pullUpDnControl(WpiPinsSelection[i], PUD_UP);  // Connect the pull-up extension.  resistor from the power bus
  }
  return;
}

 // Input polling function
void scan_inputs()
{
  act_inputs = 0;                             // Reset the active input counter
  for (i = 0; i < nums; i++)                  // We loop through all the inputs
  {
    curr_state[i] = digitalRead(WpiPinsSelection[i]);    // Record the state of each entry in the array of current states
    /*  // For debugging !
        printf("i : %d", i);
        printf("       Pin: %d", WpiPinsSelection[i]);
        printf("       Oldstate: %d", old_state[i]);
        printf("       State: %d\n", curr_state[i]);*/

    if (curr_state[i] == 0)                 // If the input is active - the increment of the counter
    {
      act_inputs++;
      //      printf("act_input: %u\n" ,  act_inputs);
    }
  }
  //printf("-----\n");
  return;
}

 // Function of copying state arrays from new to old
void copy_states()
{
  for (i = 0; i < nums; i++)
  {
    old_state[i] = curr_state[i];
  }
  return;
}

 // Initialize the previous state array
 // After startup, no input is active
void old_state_init()
{
  for (i = 0; i < nums; i++)
  {
    old_state[i] = 1;
  }
  return;
}


 // Function of comparing states and performing actions - the logic of actions
void logic()
{
  if (act_inputs == 0)   // === If there are no active inputs ...
  {

    for (i = 0; i < nums; i++)
    {
      // if state is now desactivated
      if (curr_state[i] == 1 && old_state[i] == 0)
      {
        printf("      ----- info : PIN %d has been activate during %d periods -----   \n", WpiPinsSelection[i], CountTime);
        if (CountTime < MaxCountTime)
        {
          //    unsigned char command[50];
          //printf("short press released on PIN %d\n",WpiPinsSelection[i] );
          run_script(WpiPinsSelection[i], "release");
          //    sprintf(command, "%s" "%s" "%u" "%s", script_path, "run", act_butt_num, ".sh");  // Forme la commande en tant que texte
          //  system (command);                 // Exécute le processus fils
        }
      }

    }

    copy_states();
    CountTime = 0 ;
    if (trigg_0 == 1)     // ... and if the inactivity event trigger is set ...
    {
      return;          // ... complete the function
    }
    else                 // ... otherwise cock the trigger and execute the zero-action script
    {
      trigg_0 = 1; // ...
      // run_script(0);
      return;
    }
  }
  else if (act_inputs > 1)     // === If there are more than two active inputs - update the state and exit
  {
    printf("act_inputs > 1");

    return;
  }
  else if (act_inputs == 1)    // === If there is one active input - start comparison
  {
    trigg_0 = 0;             // Reset the Zero Activity Trigger
    for (i = 0; i < nums; i++)
    {
      // if state changed in activated state
      if (curr_state[i] == 0 && old_state[i] == 1)
      {

        old_state[i] = curr_state[i];
        run_script(WpiPinsSelection[i], "short");
      }
      // if state is desactivated
      else if (curr_state[i] == 1 && old_state[i] == 0)
      {
        old_state[i] = curr_state[i];
        printf("Never Ever ! Never Ever ! Never Ever ! Never Ever ! Never Ever !");
      }
      else if (curr_state[i] == 0 && old_state[i] == 0)
      {
        CountTime++;
        if (CountTime == MaxCountTime)
        {
          //    printf("Long Press from %d !!!!!     ----->    ", WpiPinsSelection[i]);
          run_script(WpiPinsSelection[i], "long");
        }
      }
    }
    return;

  }
}


 // === Controller ===
int main(void)
{
  //  printf ("start\n"); // debug

  init_gpio();      // Initialize GPIO
  old_state_init(); // Initial initialization of the array of old states
  scan_inputs();    // We make the first poll of the inputs
  while (1)
  {
    logic();             // process states and perform actions
    scan_inputs();       // scan the inputs
    delay (delay_time);  // delay between polls
  }
  return 0;
}

 

 

OK now compile it and run it :
 

gcc -lwiringPi -lwiringPiDev -o pushbuttons pushbuttons.c
./pushbuttons

 

Press a button and you're done ;)

 

FYI : To use the native button on the motherboard of the orange PI PC you can use  "acpid" to make working for reboot

 

I hope it will be useful to some of you.

 

Link to post
Share on other sites
Donate and support the project!

Nice script, but it's not working on my OPiZeroPlus2 H5

 

The problem is outdated WiringPO library - from zhaolei

 

More updated library from Orange http://www.orangepi.org/Docs/WiringPi.html  can be compiled on actual armbian

gpio recognize opizeroplus2 board, but pushbuttons script frozen hole board ...

 

Is any project on sf or github for these boards and GPIO contol ..??

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...