Functions (API)

Some of the functions in the WiringPi library are designed to mimic those in the Arduino Wiring system. There are relatively easy to use and should present no problems for anyone used to the Arduino system, or C programming in-general.

The main difference is that unlike the Arduino system, the main loop of the program is not provided for you – you need to write it yourself. This is often desirable in a Linux system anyway as it can give you access to command-line arguments and so on. See the examples page for some simple examples and a Makefile to use.

Before using the WiringPi library, you need to include its header file:

#include <wiringPi.h>

You may also need to add

-I/usr/local/include -L/usr/local/lib -lwiringPi

to the compile line of your program depending on the environment you are using. The important one is -lwiringPi

Setup Functions

There are three ways to initialise wiringPi.

  • int wiringPiSetup (void) ;
  • int wiringPiSetupGpio (void) ;
  • int wiringPiSetupSys (void) ;

One of the setup functions must be called at the start of your program. If it returns -1 then the initialisation of the GPIO has failed, and you should consult the global errno to see why.

The differences between the setup functions are as follows:

  • wiringPiSetup(void) ;

This initialises the wiringPi system and assumes that the calling program is going to be using the wiringPi pin numbering scheme. This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. See the pins page for a table which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector.

This function needs to be called with root privileges.

  • wiringPiSetupGpio(void) ;

This is identical to above, however it allows the calling programs to use the Broadcom GPIO pin numbers directly with no re-mapping.

As above, this function need to be called with root priveledges

  • wiringPiSetupSys(void)

This initialises the wiringPi system but uses the /sys/class/gpio interface rather than accessing the hardware directly. This can be called as a non-root user provided the GPIO pins have been exported before-hand using the gpio program. Pin number in this mode is the native Broadcom GPIO numbers.

Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface. You must export these pins before you call your program. You can do this in a separate shell-script, or by using the system() function from inside your program.

Also note that some functions (noted below) have no effect when using this mode as they’re not currently possible to action unless called with root privileges.

General wiring functions

  • void pinMode (int pin, int mode) ;

This sets the mode of a pin to either INPUT, OUTPUT, or PWM_OUTPUT. Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output. The pin number is the number obtained from the pins table.

This function has no effect when in Sys mode.

  • void digitalWrite (int pin, int value) ;

Writes the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output.

  • void digitalWriteByte (int value) ;

This writes the 8-bit byte supplied to the 8 GPIO pins. It’s the fastest way to set all 8 bits at once to a particular value, although it still takes twi write operations to the GPIO hardware.

  • void pwmWrite (int pin, int value) ;

Writes the value to the PWM register for the given pin. The value must be between 0 and 1024. (Again, note that only pin 1 (BCM_GPIO 18) supports PWM)

This function has no effect when in Sys mode (see above)

  • int digitalRead (int pin) ;

This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) depending on the logic level at the pin.

  • void pullUpDnControl (int pin, int pud) ;

This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors. The parameter pud should be; PUD_OFF, (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v)

This function has no effect when in Sys mode. If you need to activate a pull-up/pull-down, then you can do it with the gpio program in a script before you start your program.

PWM Control

PWM can not be controlled when running in Sys mode.

  • pwmSetMode (int mode) ;

The PWM generator can run in 2 modes – “balanced” and “mark:space”. The mark:space mode is traditional, however the default mode in the Pi is “balanced”. You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS.

  • pwmSetRange (unsigned int range) ;

This sets the range register in the PWM generator. The default is 1024.

  • pwmSetClock (int divisor) ;

This sets the divisor for the PWM clock.

To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.

Timing functions

  • unsigned int millis (void)

This returns a number representing the number if milliseconds since your program called one of the wiringPiSetup functions. It returns an unsigned 32-bit number which wraps after 49 days.

  • void delay (unsigned int howLong)

This causes program execution to pause for at least howLong milliseconds. Due to the multi-tasking nature of Linux it could be longer. Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days.

  • void delayMicroseconds (unsigned int howLong)

This causes program execution to pause for at least howLong microseconds. Due to the multi-tasking nature of Linux it could be longer. Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes.

Program/Thread Priority

  • int piHiPri (int priority) ;

This attempts to shift your program (or thread in a multi-threaded program) to a higher priority and enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum). This won’t make your program go any faster, but it will give it a bigger slice of time when other programs are running. The priority parameter works relative to others – so you can make one program priority 1 and another priority 2 and it will have the same effect as setting one to 10 and the other to 90 (as long as no other programs are running with elevated priorities)

The return value is 0 for success and -1 for error. If an error is returned, the program should then consult the errno global variable, as per the usual conventions.

Note: Only programs running as root can change their priority. If called from a non-root program then nothing happens.

Interrupts

With a newer kernel patched with the GPIO interrupt handling code, (ie. any kernel after about June 2012), you can now wait for an interrupt in your program. This frees up the processor to do other tasks while you’re waiting for that interrupt. The GPIO can be set to interrupt on a rising, falling or both edges of the incoming signal.

Note: Jan 2013: The waitForInterrupt() function is deprecated – you should use the newer and easier to use wiringPiISR() function below.

  • int waitForInterrupt (int pin, int timeOut) ;

When called, it will wait for an interrupt event to happen on that pin and your program will be stalled. The timeOut parameter is given in milliseconds, or can be -1 which means to wait forever.

The return value is -1 if an error occurred (and errno will be set appropriately), 0 if it timed out, or 1 on a successful interrupt event.

Before you call waitForInterrupt, you must first initialise the GPIO pin and at present the only way to do this is to use the gpio program, either in a script, or using the system() call from inside your program.

e.g. We want to wait for a falling-edge interrupt on GPIO pin 0, so to setup the hardware, we need to run:

gpio edge 0 falling

before running the program.

  • int wiringPiISR (int pin, int edgeType,  void (*function)(void)) ;

This function registers a function to received interrupts on the specified pin. The edgeType parameter is either INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH or INT_EDGE_SETUP. If it is INT_EDGE_SETUP then no initialisation of the pin will happen – it’s assumed that you have already setup the pin elsewhere (e.g. with the gpio program), but if you specify one of the other types, then the pin will be exported and initialised as specified. This is accomplished via a suitable call to the gpio utility program, so it need to be available.

The pin number is supplied in the current mode – native wiringPi, BCM_GPIO or Sys modes.

This function will work in any mode, and does not need root privileges to work.

The function will be called when the interrupt triggers. When it is triggered, it’s cleared in the dispatcher before calling your function, so if a subsequent interrupt fires before you finish your handler, then it won’t be missed. (However it can only track one more interrupt, if more than one interrupt fires while one is being handled then they will be ignored)

This function is run at a high priority (if the program is run using sudo, or as root) and executes concurrently with the main program. It has full access to all the global variables, open file handles and so on.

See the isr.c example program for more details on how to use this feature.

Concurrent Processing (multi-threading)

wiringPi has a simplified interface to the Linux implementation of Posix threads, as well as a (simplified) mechanisms to access mutex’s (Mutual exclusions)

Using these functions you can create a new process (a function inside your main program) which runs concurrently with your main program and using the mutex mechanisms, safely pass variables between them.

  • int piThreadCreate (name) ;

This function creates a thread which is another function in your program previously declared using the PI_THREAD declaration. This function is then run concurrently with your main program. An example may be to have this function wait for an interrupt while your program carries on doing other tasks. The thread can indicate an event, or action by using global variables to communicate back to the main program, or other threads.

Thread functions are declared as follows:

PI_THREAD (myThread)
{
  .. code here to run concurrently with
        the main program, probably in an
        infinite loop
}

and would be started in the main program with:

x = piThreadCreate (myThread) ;
if (x != 0)
  printf ("it didn't start\n")

This is really nothing more than a simplified interface to the Posix threads mechanism that Linux supports. See the manual pages on Posix threads (man pthread) if you need more control over them.

  • piLock (int keyNum) ;
  • piUnlock (int keyNum) ;

These allow you to synchronise variable updates from your main program to any threads running in your program. keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key, it will be stalled until the first process has unlocked the same key.

You may need to use these functions to ensure that you get valid data when exchanging data between your main program and a thread – otherwise it’s possible that the thread could wake-up halfway during your data copy and change the data – so the data you end up copying is incomplete, or invalid. See the wfi.c program in the examples directory for an example.

Misc. Functions

  • piBoardRev (void) ;

This returns the board revision of the Raspberry Pi. It will be either 1 or 2. Some of the BCM_GPIO pins changed number and function when moving from board revision 1 to 2, so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences.

  • wpiPinToGpio (int wPiPin) ;

This returns the BCM_GPIO pin number of the supplied wiringPi pin. It takes the board revision into account.

  • setPadDrive (int group, int value) ;

This sets the “strength” of the pad drivers for a particular group of pins. There are 3 groups of pins and the drive strength is from 0 to 7. Do not use this unless you know what you are doing.

Comments

Functions (API) — 226 Comments

  1. Hallo,
    first of all thanks for making this lib, it’s great!
    Would it be possible to get the actual voltage of an gpio pin? or does the raspberri only provide a binary signal? That would make it easy to get a signal of a sensor.
    Thanks

    • The BCM chip powering the Pi doesn’t have any analog inputs, so getting the voltage is not going to be easy without some additional hardware. Things in the pipeline are interfacing to an Arduino, and also the Gertboard which has on-board A/D converters (as well as provision for an ATmega chip with 6 on-board A/D converters!)

      -Gordon

  2. Hello, this library it’s very nice, very good work!
    I’ve got only one question: do you know if there are any libraries (like this one you made) for using I2C and/or SPI with C/C++? Thank you very much

    • In some of the newer/experimental kernels there is I2C and SPI support and I plan to be doing some work to test them soon and possibly put some “helpers” inside wiringPi for them – just need some more time!
      -Gordon

      • It’s a good news! It would be fantastic if you extend the wiringPI library you made with some functions for using SPI and/or I2C! I’m looking forward!
        (excuse me for the error but I’m not very well with english – I’m from Italy)

  3. I have downloaded and tried the LCD example – works great Thanks. But I also noticed that you have a shiftOut.h header file. I tried to use it but could not get it to work. Have you an example program that I could plod through to see how it works. I have built a board using a 74hc595 chip so I am all ready to go !!

    Thanks

    Paul

    • I’ve just put up a new page for it:
      https://projects.drogon.net/raspberry-pi/wiringpi/shift-library/

      but it ought to work without any issues – especially if you’ve alredy used it on the Arduino.

      To use (after including the headers)

      shiftOut (dPin, cPin, LSBFIRST, value) ;

      that should shift-out your 8-bit value on the dPin using cPin as the clock.

      You do need to configure the pins as outputs beforehand.

      Let me know how you get on.

      And you can always look at the source code if you want to modify it and adapt it for your own uses. I’m about to change the license on the whole of wiringPi to LGPL too, so that’ll make it a little less of a wory for people who want to hack it about and use it in their own projects…

      -Gordon

  4. Hi Gordon,

    Thanks a lot for your terrific work – really awesome. RPi and your work will become the basis for phase 2 of my project which implements WiFi technology in my modelrailway locomotives.

    Please, have a look at this youtube: http://m.youtube.com/watch?v=wEGdddldO6k

    Until now I needed a WiFi Router Board UART linked to an AVR Mega 2561 Board in my locomotives – controlled by an Android Smartphone.

    In the next project phase I will use a RPi with WiFi dongle. Advantages: cheaper, more powerful, more functionality – such as video streaming from a locomotive inside engineer’s perspective.

    One question: What is the PWM frequency and is there any chance to get a function call setting up the frequency to adopt to electrical locomotive motor characteristics ?

    Thanks in advance – great work done – anyway!

    Regards

    Karl

    • Hi,

      Looks like a fun project!

      In wiringPi at present, the PWM frquency is set to 600KHz, however once I’ve had a bit of time to (re) read the hardware manual, I’ll be changing this and making it settable from userland too (as well as the operating mode of the PWM pin – the SoC has a slightly modified wafeform output by default as well as the traditional modes.

      So keep an eye on it and I’ll post updates when I can.

      -Gordon

  5. Hi Gordon,

    Great work and interrupts now work a treat. However, to make it work I had to modify wfi.c in setup as follows:

    system(“../gpio/gpio edge 0 falling”);
    system(“../gpio/gpio -g mode 17 out”);
    system(“../gpio/gpio -g mode 18 out”);
    system(“../gpio/gpio export 17 out”);
    system(“../gpio/gpio export 18 out”);

    maybe I need to add gpio to my PATH, but I didn’t see instructions to that effect anywhere. Also I had to add the exports to make the LEDs light, though the interrupt still worked.

    • Just thought you’d be interested in some timing measurements I just made using a PicoScope USB oscilloscope and driving the interrupt from the signal generator.

      I modified the code to remove all console writes and to generate a single output pulse on each interrupt within the interrupt routine using sequential digitalWrites of 1 then 0. This produces a pulse of approx 6-10uS width with a latency of typically 30 – 50uS with occasional longer blips (I’ve read about the video DRAM refresh at 500mS and that would seem to be the main culprit – deterministic this isn’t!)

      Using wiringPi on an unclocked Pi can handle interrupts up to about 5000/sec using about 30% of the CPU, 11000/sec hits 100%.

      • Ah, that’s fantastic, thanks. I was going to do a test myself by using 2 Pis and have one send pulses to the other, deteding them using interrupts until it started to lose them…
        But having proper test kit is great 🙂
        Thanks,
        -Gordon

    • When you run the

      sudo make install

      in the gpio directory, it ought to copy the program into the /usr/local/bin directory, and change file permissions to make it run setuid. I’m guessing that you don’t have /usr/local/bin in your path, so change the system calls to

      system (“/usr/local/bin/gpio …”) ;

      And you’re right about the last 2 exports – I must start using unexportall to reset everything between projects.

      -Gordon

      • So having decided that ‘waitforinterrupt’ isn’t fast enough when operating from user space for what I need, I’m going to have to write my own kernel interrupt handler… though I’m not entirely sure how to start.

        I note that when you cat /proc/interrupts it lists interrupt 52 as BCM2708 GPIO catchall handler and 85 as GPIO and after running ‘wfi’ interrupt 85 GPIO is linked with gpiolib (“gpio unexport all” removes this linkage). That seems to happen when you set the ‘edge’ state on GPIO 0

        I’ve perused ‘Writing Linux Device Drivers’ but that confused me more than illuminated on the how… any other pointers you can give?

        • I didn’t write the actual low-level interrupt code for this – just some demos of how to use it from userland. You’ll need to have a pok around in the kernel sources to find out more I’m afraid…

          -Gordon

  6. Hi Gordon:

    First of all. Thanks for the lib. They work pretty smoothly. However, I have a question. I’m a newbie using PWM and I needed for a project. I’d like to know how the PWM module works, in you void call is just possible to enter one value between 0 – 1023. I think this value must be the pulse frequency. However, I can’t find how to calculate the frequency when the value in the function is 0, 1, … 1023. Doy you have any idea about this? In addition, do you know hoe the duty cycle can be changed? Is there a function for this? Thanks for your help to clarify this!

    Mario B.

    • The frequency of the PWM is set in the code and at present that can’t be changed (unless you modify the code). The value sets the duty cycle.

      Traditionally, within the entire cycle, a value of 0 would output 1024 0’s for each cycle, a value of 1 would output 1 x 1, then 1023 0’s, 512 would output 512 1’s, then 512 0’s and so on.

      However the Pi’s PWM isn’t quite configured like that by default and what it will do is try to balance out the pulses – I’m currently looking into changing the mode of the PWM to the ‘traditional’ mode.

      -Gordon

  7. Hi Gordon
    Thanks a lot for this great library. I am new to this environment, well not new just not been on Linux for almost 12 years. I tried the threading example but got some error that I did not expect. Obviously I am doing something stupid. Can you correct me please

    /usr/local/lib/libwiringPi.a(piThread.o): In function `piThreadCreate’:
    piThread.c:(.text+0x58): undefined reference to `pthread_create’
    collect2: ld returned 1 exit status

    And the code

    #include
    #include

    PI_THREAD (myThread)
    {
    /*
    .. code here to run concurrently with
    the main program, probably in an
    infinite loop
    */
    }

    int main(void)
    {
    int pin_LED = 7;
    int pin_switch = 8;
    int del = 250;
    printf (“Raspberry Pi wiringPi butone and led test \n”);
    if (wiringPiSetup() == -1)
    exit(1);
    pinMode(pin_LED, OUTPUT);
    pinMode(pin_switch , INPUT);

    int x = piThreadCreate (myThread) ;
    if (x != 0)
    printf (“it didn’t start\n”);

    for (;;){
    if (digitalRead (8) == 0)
    {
    del = 100;
    } else {
    del = 250;
    }

    digitalWrite(pin_LED,1);
    delay(del);
    digitalWrite(pin_LED,0);
    delay(del);
    }
    return 0;
    }

    • Hi Marius,

      code looks fine the missing link is that you need to add -lpthread to your compile command-line, so:

      cc -o mytest mytest.c -lwiringPi -lpthread

      -Gordon

  8. Hi Gordon

    Firstly, great project! I am really enjoying learning all this stuff!

    I have all the wiringPi/examples programs working fine apart from wfi. When I run it I am getting “gpio: Unable to open GPIO edge interface for pin 0: No such file or directory”.

    Is there something obvious I am missing here? I have tried running the program with and without sudo, and I get the same result.

    • I suspect your kernel version isn’t new enough.
      If your getting that error messge from the gpio program, then it’s not finding the ‘edge’ file that controls the interrupt trigger.
      Try upgrading – go through the sequence of:

      sudo apt-get update
      sudo apt-get upgrade
      (and sudo apt-get dist-upgrade if you need to too)
      and if that doesn’t help, then try the rpi-update script from here: https://github.com/Hexxeh/rpi-update/

      -Gordon

          • Sorry, yes – the wfi example program is working perfectly and counting my button presses 😉

            My original sd card image was debian6-19-04-2012. I ran the command line updates and rebooted after each, then it worked. I did not need to use the rpi-update script you mentioned.

  9. This is so simple to use. And the gpio command line utility is so useful for sanity testing the hardware. For someone who’s spent the last 20 years trying not to get his hands dirty on hardware, the first time that I got a led to light up was fantastic.

    Thank you for this library.

  10. Hi,

    Trust this finds u well and hope u are now progressing well with RTB.

    After doing good numbers of projects in Arduino… I have started using wiringPi. So, far I have been successful in LED using digitalWrite along with PWM. Yesterday evening I was trying to read analog data from TMP36 through MCP 3008. But it is only giving me value of 1 not analog values as we get in Arduino UNO. Same was happening when I was using MCP3002.

    My code is given below….
    #include
    #include

    //#define aref_voltage = 3.3

    int main() {
    // int readpin = 18; // using MCP3008 – not successful
    int readpin = 12; // using MCP3002
    system(“clear”);

    if(wiringPiSetup() == -1)
    { return 1;}

    pinMode(readpin, INPUT);

    int count;
    for(count = 0; count 3.3 V
    VREf —-> 3.3 V
    AGND —> GND
    CLK —->
    DOUT—->
    DIN—-> CH0 from MCP —-> pin # 18 in RPi
    CS—–>
    DGND—->GND
    CH0—-> Middle pin of TMP36

    //————————————-
    Connection for MCP 3002

    VSS —-> GND
    CH0 —-> middle pin of TMP 36
    CS/SHDN ——> Not connected
    VDD —–> 3.3 v
    CLK —-> SCLK
    Dout —–> MISO
    Din ——-> MOSI

    Cheers….

    Jishnu

  11. Thanks for putting this together! I’m able to run and compile the example programs, but I’m having trouble with SPI; I’m getting the error message “No such file or directory” on the command wiringPiSPISetup(0, 100000). The command wiringPiSetup() just prior to this command seems to work just fine. I’ve tried the sequence of update/upgrade/dist-upgrade/rpi-update and rebooted after the each of the last 3, but none of them seem to make a difference. Any idea what might be wrong? I can post my program also; it consists mostly of include statements and those two lines.

  12. Hi, thanks so much for all your work. I have installed the python version and can access the GPIO using wiringpi.

    I am using the latest version of squeeze and the latest firmware, however, I am unable to use the interrupts and I suspect that the version of wirinhpi which was ported to python does not include the lates code ??

    Here’s the output of dir(wiringpi):

    [‘GPIO’, ‘HIGH’, ‘INPUT’, ‘LOW’, ‘LSBFIRST’, ‘MODE_GPIO’, ‘MODE_PINS’, ‘MODE_SYS’, ‘MSBFIRST’, ‘OUTPUT’, ‘PUD_DOWN’, ‘PUD_OFF’, ‘PUD_UP’, ‘PWM_OUTPUT’, ‘Serial’, ‘WPI_MODE_GPIO’, ‘WPI_MODE_PINS’, ‘WPI_MODE_SYS’, ‘__builtins__’, ‘__doc__’, ‘__file__’, ‘__name__’, ‘__package__’, ‘_newclass’, ‘_object’, ‘_swig_getattr’, ‘_swig_property’, ‘_swig_repr’, ‘_swig_setattr’, ‘_swig_setattr_nondynamic’, ‘_wiringpi’, ‘delay’, ‘delayMicroseconds’, ‘digitalRead’, ‘digitalWrite’, ‘gertboardAnalogRead’, ‘gertboardAnalogWrite’, ‘gertboardSPISetup’, ‘millis’, ‘pinMode’, ‘pullUpDnControl’, ‘pwmWrite’, ‘readNesJoystick’, ‘serialClose’, ‘serialDataAvail’, ‘serialGetchar’, ‘serialOpen’, ‘serialPrintf’, ‘serialPutchar’, ‘serialPuts’, ‘setupNesJoystick’, ‘shiftIn’, ‘shiftOut’, ‘softPwmCreate’, ‘softPwmWrite’, ‘wiringPiSPIDataRW’, ‘wiringPiSPIGetFd’, ‘wiringPiSPISetup’, ‘wiringPiSetup’, ‘wiringPiSetupGpio’, ‘wiringPiSetupSys’]

    • wiringpi.wiringPiSetup()
      wiringpi.pinMode(1,0)
      wiringpi.waitForInterrupt (1,1000)
      >>>AttributeError: ‘module’ object has no attribute ‘waitForInterrupt’

    • Hi,

      Wish I could help, but I didn’t write the Python wrappers for wiringPi. I’d keep checking the github location for updates though.

      -Gordon

  13. Hi there, thanks for publishing all this its really improved my understanding of the pi and electronics in general. Is there any news on how i2c support is coming on? I’ve got a few i2c modules that I’d love to get going with this.

    Thanks again!

    Ian McC

    • I have plans to do something very similar for I2C that I did with SPI – I just need a little more of that ultra precious subtance; time!

      So keep watching!

      -Gordon

  14. This is an amazing piece of code, thanks much for making it available!

    I’ve got my RPi interrupting on pulses from my electric meter, and am graphing power consumption, but I’d like to add more granular power and maybe water flow and such.

    What do I need to do to interrupt on more than one pin? Can I have multiple ISR routines for different interrupts, or do I need to run a separate program for each interrupt, or do I have to have the one true ISR figure out which pin changed?

    Thanks!

    • You should be able to run multiples. Just create more than one “waitForIt” type function for each pin you need and remember to set it up with the gpio edge command first. Start wach different waitForIt with a call to piThreadCreate()

      So: waitForElectricPulse, waitForWaterPulse …

      piThreadCreate (waitForElectricPulse) ;
      piThreadCreate (waitForWaterPulse) ;

      and so on…

      -Gordon

      • Ah, I think I see how that’ll work, thanks!

        It looks like I can have a maximum of 4 ISRs, because there are only 4 ‘keys’ for locking, is that right? Is that 4 keys total, or 4 per program (can I run two programs and count interrupts on 8 pins?)

        Thanks!

        • The “keys” are just my own little wrapper round the mutex functions – have a look at the source code to see how they work and implement your own (or change the max. number!) You can have 1000’s … I was just trying to simplify things somewhat!

          -Gordon

      • Hi Gordon,
        I got your wifi example working without a single problem, cool, the wiringpi is so easy to use!
        I have the same problematic as Wiliam Smith. Instead of using multiple thread routines with mulitiple global variables, is it not possible to pass a parameter (or parameters) to the thread at creation time?

        I’m actually programming in C++ and was intending to send down a C++ class to the tread routing with information on what pin to wait on and so on. Then reading and writing that class via mutex semapore.
        Sorry I’m coming from Windows so maybe I’m not thinking this correctly.

        • Passing data into a thread is very possible – but not with my simplified wrappers – you have to delve a bit deeper and lookup all the ins and outs of the Posix threads library. Start by looking at the soure code for mine – that’ll give you the names of the underlying functions, and take it from there.

          Basically, I wrote those wrappers to simplify things for people new to the whole threads thing (and maybe C too). Getting your head round pointers to functions can be tricky if not used to it…

          -Gordon

  15. It almost looks like the PWM code could be transmogrified into something that would drive servos, essentially a 1-2ms pulse repeated “every once in a while”, anywhere between (say) 3 and 100 ms.

    Would that be easy to do?

    Thanks!

    • It could, but the timings for RC servos are somewhat critical – and while for driving an LED or motor, the occasionaly schedulling glitch is OK, it might make a servo “twitch” by too much… Also, the granularity is 100uS or 0.1mS so only 100 different intervals between hard left and hard right – it might be enough, but …

      However all is not lost – there is a kernel level driver to do just that – but I’m not sure how official it is though – search the raspberry Pi forums to find it.

      -Gordon

  16. And one last quick query:

    How easy would it be to make the RPi output a square wave in audio frequencies?

    Thanks!

    • It would be relatively easy – and it will be the subject of an article I’m going to write up soon as I’ve been doing some experiments 😉

      If the base pulse width is 100uS, then we have a square wave of a period 200uS, or 0.2mS or 5000Hz. so while it’s not going to be quite Radio 3 quality, it might be good enough to poduce a series of squzwks and buzzes – just like the old Apple II/ZX80, etc…

      We can take the min. pulse width lower, but below 100uS it needs “hard” coded loops which then consume 100% CPU.

      -Gordon

  17. Any news on what it takes to drive I2C devices from WiringPi? I found some DS1621 devices I’d like to try using for getting a temperature profile on a fridge, freezer, or hot water heater, but I can’t parse the difference between I2C and SPI…

    Thanks!

    • The latest version of witingPi has a gpio readall command:

      gordon @ pi1: gpio readall
      +----------+------+--------+-------+
      | wiringPi | GPIO | Name | Value |
      +----------+------+--------+-------+
      | 0 | 17 | GPIO 0 | Low |
      | 1 | 18 | GPIO 1 | Low |
      | 2 | 21 | GPIO 2 | Low |
      | 3 | 22 | GPIO 3 | Low |
      | 4 | 23 | GPIO 4 | Low |
      | 5 | 24 | GPIO 5 | Low |
      | 6 | 25 | GPIO 6 | Low |
      | 7 | 4 | GPIO 7 | Low |
      | 8 | 0 | SDA | High |
      | 9 | 1 | SCL | High |
      | 10 | 8 | CE0 | Low |
      | 11 | 7 | CE1 | Low |
      | 12 | 10 | MOSI | Low |
      | 13 | 9 | MISO | Low |
      | 14 | 11 | SCLK | Low |
      | 15 | 14 | TxD | High |
      | 16 | 15 | RxD | High |
      +----------+------+--------+-------+

      -Gordon

  18. Thank lot

    gordon @ pi1: gpio readall

    From what directory I should execute this command on a ssh session?

    • It will work from any directory if wiringPi is installed. Ssh session or on the console or in a terminal window when running X?

      -Gordon

  19. I was thinking of using the PI to build a tv infared control but not sure if it can be done. I used delayMicroseconds(8) but found the pulse/wave(whatever you call it, i’m new at this) varied from 9 to 165us. I’m guessing this is because of the mutlitasking operating system. Am I wasting my time here ?
    CODE:
    while(1){
    digitalWrite(17, 1);
    delayMicroseconds(8);
    digitalWrite(17, 0);
    delayMicroseconds(8);
    }

    thanks

    • I think doing it that way may well be wasting your time – the delays in the Pi at that lever are not accurate enough to generate the carrier wave.

      However there are projects that are doing this on the Pi with kernel level drivers – it’s not an area I’m overly familiar with though, however searching throug the Pi forums might turn something up…

      -Gordon

      • How about using GPCLK0 (GPIO4)? I would also be interested in using it for a carrier wave (IR) of 38Khz (13us ON, 13us OFF), but documentation is scarce to say the least.
        Or how about using osc_debug=500 which (may, untested) output the oscillator [=19.2MHz]/N to GPCLK1 (GPIO5 or CAM_GPIO, pin 11 of S5) ?

        • I’d need to re-read the (scant, as you say) ARM peripherals manual again to work out what’s possible (that’s documented anyway!) You might get away with a 13uS delay using wiringPi though, but it will be marginal…

          Then you have the issue of pulsing it on/off at the right rate to send the codes..

          -Gordon

  20. I’ve been looking at an Ada binding to (the basic parts of) wiringPi, and found that wpiPinToGpio() gives a segv if called after wiringPiSetupSys().

    Patch at http://db.tt/ExLinPYd (is there a better way to submit this?)

    I don’t suppose users of wiringPiSetupGpio() will need wpiPinToGpio(), but I guess it ought to work anyway, so the same change would be needed there.

    • I’ve not used your patch directly, but have added in more or less the same code to make it work. I’ll add your name to the contributors file.

      As for getting stuff to me – email works! See the contact page ..

      Cheers,

      -Gordon

  21. We Ada guys get all upset 🙂 when people say ADA. Named after Ada, Countess of Lovelace, the first programmer … apt-get install gnat

  22. Hello! And thank you for your help!!
    I was wondering about how long does the pwmWrite function last? For example, once I write to the PWM register, does it clear after one wave cycle? Or will it remain outputting the same duty cycle until I rewrite something to the register?
    Thanks again!

    • Once you change the register, it will output that value continually until you write a new value, so you don’t need to keep on writing it!
      -Gordon

  23. Thanks a ton Gordon for all your work. I’ve come across something I don’t understand. I am using your library to so something analogous to scanning a keypad. I set all the pins low with a function then set one pin high and check another pin with the following code:

    set_pins_low();
    pinMode (AWIREL, OUTPUT);
    digitalWrite (AWIREL, HIGH);
    if (digitalRead(BWIREL)) Do_Stuff();
    set_pins_low();

    The problem I am having is the when I touch the pins of interest (AWIREL and BWIREL) with my hands the circuit is completed and acts as though the two wires are touching. I thought this might have something to do with the changing of AWIREL from input to output without a delay so I added one but that didn’t fix the problem. Now I wonder if this phenomena has something to to with the GPIO working on a 3.3V system? I appreciate any help from anyone. Thanks again.

    • If input pins are not connected to anything then they will “float” and be susceptible to stray capacitance. The solution is to either use a resistor to tie them to +3.3v (or 0v), or use the internal pull up (or pull-down) resistors. So for the input pins, you can do something like:

      pinMode (BWIREL, INPUT);
      pullUpDnControl (BWIREL, PUD_UP) ;

      or use PUD_DOWN to bias them to 0v. The internal resistors are about 10K.

      If you pull them up, then they’ll read high when the button is not pushed, or when the scan has left the output pin high, but when the scan sets the output pin low and the button is pushed, then you’ll read low/0.

      -Gordon

      • Yeah, I have this as part of my set_pins_low function:

        void set_pins_low(void) {
        pinMode (AWIREL, INPUT);
        pinMode (BWIREL, INPUT);
        pullUpDnControl (AWIREL, PUD_DOWN);
        pullUpDnControl (BWIREL, PUD_DOWN);
        }

        Maybe I will have to use external pull-down resistors? I hope not. I have 7 GPIO pins that I am using alternatively as inputs and outputs to scan my system. Using external resistors will require an additional 7 pins (14 pins total) to control the pull-down resistors.

    • Ok, I think I’ve discovered that this is really a timing issue after all. Replacing the call to digitalRead with this function seems to do the trick:

      int readPin(int pin) {
      int i;
      for (i = 0; i < 80; i++) {
      if (digitalRead(pin)==0) return 0;
      }
      return 1;
      }

      Note that the value of 80 was determined experimentally. Feel free to comment. Thanks again for developing this library.

      • Ok Gordon, I’m sorry if I am cluttering up your page here. I guess you can clean it up. Sorry, but I am learning as I go. This may not be a timing issue after all. I’ve had to increase the number of consecutive high reads from 80 to 10,000 and I can still get the thing to trigger a false high if I rub the connectors between my fingers. Maybe this is a static issue?

        Also, I’ve bought two different RPi boards and pin 2 will not work as an input on either board. Could this be an issue with the library? It just seems to coincidental that the same pin is problematic on two different boards. Thanks again.

        • It sounds like the pull-up/downs aren’t being activated. If they are, then no amount of touching the pins should trigger changes. You can experiment with the gpio command – use it to set the pull-up/down then read the pin without running the program.
          First make sure you can change it – so if the pin is in input mode – gpio mode 1 in – then rea it – gpio read 1 – then change the pull-up/down – gpio mode 1 up or gpio mode 1 down (obviously substitute 1 for the pin you’re using) You should be able to read 1 or 0 just by changing the internal pull up/down.

          And when you say pin 2? Which pin 2? wiringPi pin 2 is bcm_gpio 21 on a rev 1 board, or 27 on a rev 2 board. make sure your board type is being correctly identified – run gpio -v to check.

          -Gordon

          • I don’t think that the CMOS, high impedance GPIO pins on the Raspberry Pi are capable of doing what I want, measuring a closed condition between GPIO pins without generating “false” closed conditions being reported by “touching” the pins with my hands. I think I am going to have to use some sort of arduino or PIC based buffer/signal conditioning daughter board.

            Even using the GPIO utility in a bash script triggers false high signals when I aggressively grip and rub the wires with my hands. If anyone thinks I am wrong please let me know because I don’t really want to rely on additional hardware. Thanks.

          • You need to bias the inputs pins to +3.3v or 0v via a suitable resistor. 10K is usually sufficient. You can also enable the internal pull-up or pull-down resistors.

            This is no different to the inputs of e.g. an ATmega or PIC, so you’d still have the same issues there.

            Using the gpio command:


            gpio mode up # Enable internal pull-up
            gpio mode
            down # Enable internal pull-down

            -Gordon

          • Well, this is my code:

            while :
            do
            gpio mode 3 out
            gpio write 3 1
            gpio mode 7 in
            gpio mode 7 down
            gpio read 7
            done

            It prints 0 to the output terminal until you touch both wires connected to pins 3 and 7 with your hands. Then it prints 1 while your are holding on to the pins until you let go of them. Sometimes it will print 0 when you touch both wires with your hands but if you grip them hard enough or have wet hands (increasing your electrical conductivity) it will eventually trigger a false high.

            I would really like this to work without the use of a daughter board so I appreciate your help with this.

          • If this is directly connected to the Pi – then I suspect that’s the way it is – you must be generating a lot of “noise” or static into the Pi to affect it at that level, but the internal pull-up/down resistors are quite “weak”, so maybe you need external ones. I’d start by connecting a 10K resistor between the GPIO pin and 0v.

            -Gordon

          • So I was thinking about this and it came to me. Rather than concerning myself with the value of the pull-down resistors, why don’t I just increase the resistance of the lines coming out of my enclosure. I experimented with different resistors across the lines to determine the threshold value that would trigger a high signal into the input line. A resistance of 70k – 80k ohms seemed to be the magic number. So I connected a 30k ohm resistor between the GPIO pins and the banana jacks on my enclosure box. So far it seems to be doing the trick. Sticking your tongue across the pins still seems to trigger a closed switch conditions but I think this will work. Now I will build a GUI for my system and put it to work to see how it performs. Thanks again for all you help. I’ll provide a link to my final product when I get it fine tuned.

  24. Hi Gordon. I wanted to thank you for making this great library available to everyone. Great work!

    I have one question. I am writing a reusable class that will control a camera shutter. Class takes two PIN numbers as parameters along with some other stuff to set delays, number of shots etc.

    At the moment I’m calling the wiringPiSetup() in my init function thus forcing the users of the class to use wiringpi pin numbers.

    The question is how would I check within my class that user has called one of the wiring pi setup functions before doing anything with the pins. This way i could give the user a choice of what pin numbering to use.

    Hope that makes any sense.

    Kind regards,
    Sandis

    • There’s no “official” way, however if you check the address of some of the functions, then you can tell if a setup function has been called. e.g.


      #include
      #include

      int main ()
      {
      if (pinMode == NULL)
      printf ("No Setup Yet\n") ;

      wiringPiSetupSys () ;

      if (pinMode == NULL)
      printf ("No Setup Yet\n") ;
      else
      printf ("a seputup has been called\n") ;

      return 0 ;
      }

      You can’t tell which setup though as the internal functions are declared static in the code (unless you change the code!)

      Maybe I’ll put some way to tell in the next release. It would be easy to do, but that might at least let you know if a setup has already been called.

      However, there’s no real problems by calling setup more than once… It will reset the mills () counter though.

      -Gordon

  25. Which process has more priority with piHiPri() 1 or 10? Is “inverted” like with nice command? I’m asking because I have better results reading DHT22 with lower (1) priority settings than with 99.

    • 99 is highest. However if you only call it once in a program (ie. not threads), then it really won’t matter what you use as it will have a higher priority than anything else, so there really ought to be no difference between 1 or 99.

      See the man page for sched_setscheduler for more details of what it’s doing.

      -Gordon

  26. Hi,

    Thanks for this lib, it’s very helpful.

    I think WiringPi.h is missing the INT_EDGE_BOTH definition :
    #define INT_EDGE_BOTH 3

    Daniel

    • Yes, well spotted there… It’s not actually used in the (new) Interrupt Service Routine code, but would need to be used by someone calling it…

      Cheers,

      -Gordon

  27. Hello, i have install this library but in codeblocks i have an error.
    I have include wiringPi but it don’t fount the function digitalWrite. I don’t know how i can add the arg -lwiringPi in codeblocks.

    Thanks

    PS : sorry for my english i’m french

  28. Hi! Thanks for this great job. I have a question about PWM. I want to drive a servo and i need 1 degree turn, so i can’t use 1024 range, but i think i can enlarge the range with pwmSetRange but i need 50Hz frequancy for my servo. Can i use pwmSetClock command for setting PWM freq’ if yes, how? thanks again

    • Don’t use the Pi’s PWM to drive servos – it’s really too much of a fiddle. Search for the servoblaster kernel module for the Pi – it’s much better for driving servo motors!

      I did produce a software version which runs like my softwarePWM module, but it’s not that accurate. servoblaster will do what you need it to do.

      -Gordon

      • Thanks for quick reply, i will research about servoblaster. Maybe i will use an encoder for my servo.

  29. Hi Gordon

    Thanks for the tough libraries, all fine.
    I have currently problems in reading a rotary encoder with pushbutton (its tied to three input pins, all w pullups). Is there a way to have multiple interrupts (or an or’ed) interrupt signal of all three inputs working? In the latter case I would have to sort the action of the rotary out in the isr…
    Or do you know anyone who has succees in reading a rotary with pushbutton?

    Thanks a lot, I really enjoy your work.
    Chris

    • Multipe interrupts are relatively easy now – look for the wiringPiISR() function in the latest release of wiringPi. Easy to have 2 (or many) interrupts – so when you take an interrupt, you then poll the state of the other pin to work out your direction.

      I think I might even have such a switch in my “box o bits”, so it migh make a good project too.

      -Gordon

      • Hello Gordon.
        I’m really interested in this library, as I see is maybe the only one provided interrupt handling throught GPIO. I see in the above post you mention there should a kernel patch that allows GPIO interrupting, but there’s no reference to such patch. I can figure out myself how to patch it probably, but the source of information of what you’ve used to enable this nice feature would be nice. Or is it not necessary and works right out of the box with the latest raspberry pi firmware files?

        • you don’t need any kernel patches – just go with any current Raspbian kernel installation and off you go. There are some example interrupt programs in the examples directory too – including an “oscillator” where I’ve connected an output to an interrupt input – max. speed appears to be in the oder of 66K ints/sec, but you don’t have much CPU left over at that!

          -Gordon

  30. I got multiple ISRs running, but is there a way to clear the interrupt flag at the end of the ISR? It seems like the bit is retriggered (assuming it is cleared while branching into the ISR).

    Thanks for your reply, Chris

    • The ISR is cleared right before the lower-level routine calls your own function, so if a 2nd interrupt comes in during your own processing, it’s latched and you get called again immediately.

      I did it that way as I had a sort of complaint that they were missing interrupts from a source – can’t please everyone )-:

      You may want to look in the actual wiringPi code itself to see how it’s working – maybe write your own module based on it to change the behaviour?

      -Gordon

  31. Total newb question here, but what is the meaning of the value being written to the PWM register in the function pwmWrite?

    Thanks

    • The value is the value of the PWM output. So with the default range of 1024, then 512 gives you a 50% dury cycle, 256 would be 25% and so on.

      -Gordon

  32. I am attempting to start my program which uses wiringPiSetup and wiringPiISR on boot. I have it to set to startup via systemd after multi-user.target (arch linux) as root, it runs as root. This means ntpd and network setup is complete. wiringPiSetup and wiringPiISR do not return -1, the process starts, but I do not get any interrupt callbacks. However if I restart the process manually, callbacks then start to work. Do you have any insight regarding the difference for WiringPi being called during startup, or are there other dependencies that may not have been started up yet that I need. I’m starting it as late as possible in the boot sequence.

    • the wiringPiISR thing need the sysfs (/sys/class/gpio/xxx) to be working – and I don’t know if that’s ‘mounted’ like /proc – is it possible that it’s not mounted before your program starts running?

      The ISR library also calls /usr/local/bin/gpio – so it expects that to be present and available too – are you checking the return code from wiringPiISR ()? It will be 0 on success, anything else is an fail and you might want to look at errno.

      -Gordon

      • Thanks for your reply Gordon. I verified /sys/class/gpio does exist at the time the program is started. gpio appears to be available, and wiringPiISR call returns 0. It’s oddly inconsistent… Sometimes it works if I put a 10 second sleep before the program starts. I also got it working by putting a “gpio unexportall” before the program is started… But it’s not completely consistent. It seems to depend on how I reboot or shutdown or pull the power, not sure, it’s frustrating.

  33. Hi. Thanks for great work. Would you consider adding callback with param for wiringPiISR? It would be realy usefull as you won’t have to write specialised callback for each PIN.

  34. I thought about general void * parameter. So if you realy need to you may alloc struct with some data related to pin. I came up to this as I’m making Qt wrapper on your library.

  35. Great lib, but it would be really great if there would be a function to unregister an interrupt handler, or is there any?

    • Give me an example of a situation where halft way through your program execution you’d need to un-register the handler and I’ll look into it. (Otherwise it’s “unregistered” when the program exists)

      -Gordon

      • I am using your library in a daemon that controls an external control board for the Pi (LCD, 4-way switch, …). Each time the Pi and my control board are communicating I need to attach an interrupt handler to listen to the external clock signal. While not transmitting I do not need to react on rising edges of the clock signal (which still occurs, because there are other devices on the same bus, which is a kind of SPI). So currently most times my interrupt handler is called without anything to do, and that’s my use case 😉

  36. Hi Gordon.
    I write this message http://www.raspberrypi.org/phpBB3/viewtopic.php?f=33&t=35739
    I’ve a problemm with this code:
    #include
    #include
    #include
    #include
    int main (void)
    {
    if (wiringPiSetup () == -1)
    {
    printf(“Error with wiringPiSetup”);
    return 1;
    }
    if (wiringPiSetupGpio () == -1)
    {
    printf(“Error with wiringPiSetupGpio”);
    return 1;
    }
    if (wiringPiSetupSys () == -1)
    {
    printf(“Error with wiringPiSetupSys”);
    return 1;
    }
    int x;
    pintMode(11, OUTPUT);
    digitalWrite(11, HIGH);
    x = digitalRead(11);
    printf(“%d\n”, x);
    return 0;
    } //
    Why this variable return 0(I mean x)?

    And with gpio load spi. How i can use 2 byte buffer? The value is in KB.
    And which function send 8 bits?
    Sorry for my English.

    • The first issue is that you are calling wiringPiSetup() more than once. Just call it once. Pick one of the three methods you want to use wiringPi and stick to it. Do not call it more than once.

      The issue you’re seeing is that the last call to it puts it into “sys” mode and in this mode pinMode() has no effect.

      You want to use pin 11 – which pin is this? There are many ways to describe the pins. See this page:

      https://projects.drogon.net/raspberry-pi/wiringpi/pins/

      If you want to write 16 bits over SPI, then just call the system write() function – e.g.

      unsigned char buffer [2] ;
      buffer [0] = 12 ;
      buffer [1] = 34 ;

      write (fd, buffer, 2) ;

      where fd is the file descriptor returned when opening the SPI device.

      -Gordon

      • “where fd is the file descriptor returned when opening the SPI device.”
        Sorry, I can’t this translate. Сan explain?
        Can I do something wrong to connect?
        DIN –> MOSI
        CLK –> SCLK
        LOAD –> CE1
        And my new code are:

        unsigned char buffer [2] ;
        fd = 1;// while connected CE1
        buffer [0] = 0x0C ; //Shutdown
        buffer [1] = 0x01 ;
        write (fd, buffer, 2) ;

    • I compile the program as follows:
      cc -o tablo tablo.c -I/usr/local/include -L/usr/local/lib -lwiringPi

  37. Awesome library. The only issue I had was that when registering the interrupt in an init script it didn’t always stay there.
    I had basically used your isr.c example and initiated it on bootup with an upstart script (/etc/init/isr) that was started when my wifi came up (start on net-device-up IFACE=wlan0). The program was always running (infinite for loop) but the interrupt wouldn’t actually be registered in the majority of the bootups. Every once and a while it would be but that was pretty rare. I got around it by delaying the registration 10 seconds. Kind of hacky but it got the job done. Not sure what was causing the failure. I never got any sort of message about a registration failure. I’m using raspbmc.
    Again, love the library just thought I’d dump my experience here.

    • I think someone else has mentioned this too – I’m wondering if there is something else in the startup scripts that might be interfereing in some way. More testing needed at some point…

      -Gordon

  38. Hi,

    Where can I find the isr.c program code? I’ve searched everywhere and can’t find it. I would like to see an example of the wiringPiISR() function used.

    THANKS!

      • Thanks Gordon,

        I already looked in the WiringPi Examples and GPIO Examples under the Raspberry Pi tab and I didn’t see it there. Where is the Examples directory?

        Thanks again,

        Kevin

          • oh I see! I haven’t downloaded WiringPi yet. I was looking for it on your website here under the Raspberry Pi drop down menu.

            Thanks so much for your time,

            Kevin

          • OK. I thought you had it as part of some other package and was using some GUI interface rather than web. There’s also a version on github which I don’t maintain, (someone else does) so I really wasn’t sure.

            -Gordon

  39. Hello, Gordon —

    Thank you for publishing this!

    I’m trying to get the Perl wrapper to work, and I notice that a number of functions described in this API aren’t declared in the wiringpi.pm package produced by the WiringPi-Perl build script. The specific function I long for is
    wiringPiISR(). Do you have any idea why this isn’t declared?

    — Eric

  40. In your waitForInterruptSys function you have a read occurring unconditionally after the call to poll().

    However – if you sent in a non-zero timeout, won’t it hang on the read call if the timeout occurs? Seems to me that the read should only be called if the return code from indicates that an interrupt occurred.

    Running into it because I was testing my timeout before triggering the interrupt. Advice?

  41. Hi Gordon,

    Regarding the wiringPiISR function. What happens when you register more than one ISR. For example, I was setting one for pin 3 and one for pin 4. But what seems to happen is that both get called no matter which pin generates the interrupt.

    Is this expected behavior?

    Ian

      • Don’t bother Gordon – it seems to be a problem with my setup – not sure how yet. Its not problem with your code.

  42. All the functions in the C version of wiringpi are they also included in the Ruby version?

  43. Hi Gordon,
    I’m having a small issue with the wiringPiISR function. I’m trying to use it with a different pin, besides pin 0. And the code doesn’t seem to be responding to certain pins.
    it works for pin 0, 1, and 6. I haven’t checked all of them, but the two I’m looking to use it for is pin 2 and 5. Do you know why this may be happening?

    Thanks

    • I’d double check your code.

      See this: http://unicorn.drogon.net/isr.c

      It launches 8 handlers for the first 8 pins – then you can

      sudo ./isr

      and in another terminal:

      gpio mode 0 up ; gpio mode 0 down
      gpio mode 2 up ; gpio mode 2 down

      etc.

      and it does what it’s supposed to do. (At least it does for me!)

      -Gordon

      • the only thing I changed in that code is the button pin number, and certain ones work and other ones, it just keeps saying “waiting..”

        • How are you triggering the interrupt? Have you tried the trick I use with the pull-up/down resistors?

          Run gpio exports once your program has setup the ISRs – just to check.

          -Gordon

  44. Hi Gordon and every one. Thanks for the library Gardon, and for everyones comments ! I’ve got a project with ISRs to the nearly working stage now.

    Like some others here, I’m also trying to get a Pi to count pulses from electricity meters using ISRs (open source project, so happy to collaborate with anyone else that’s doing this).

    I’m hoping to monitor up to six meters, though my immediate need is only for three or four.

    In https://projects.drogon.net/raspberry-pi/wiringpi/pins/terminology, I’m trying to call an ISR when any of GPIO0 though GPIO5 are pulled low (five separate ISRs).

    Before I run my C code, I’ve run GPIO commands of the form below to export the pins (no reported error)

    gpio unexportall
    gpio edge falling

    gpio edge falling

    I’ve tried using wiringPi pin numbers 0 through 5 for the above commands, but seeing that https://projects.drogon.net/raspberry-pi/wiringpi/the-gpio-utility/ says “Note: The pin numbers in the sys mode are always BCM-GPIO pin numbers”, I’ve also tried using pin numbers 17, 18, 27, 22, 23 and 24, per https://projects.drogon.net/raspberry-pi/wiringpi/pins/ – see my scripts at http://81.187.247.166:81/EdgeTrig1.sh and http://81.187.247.166:81/EdgeTrig2.sh

    Based on the wiringPi example, for each input, numbering the pins 0 though 5, my C++ code calls,

    pinMode( , INPUT );
    pullUpDnControl( , PUD_UP );
    wiringPiISR( , INT_EDGE_FALLING, &IsrChan );

    and the code then goes off to do something else. See http://81.187.247.166:81/ObemsPulseServer.cpp for the relevant section of code.

    Each time I fire this up, I find that between one and four of the channels work, and that the mapping of the physical input pin to the ISR is correct. Firing it up by rerunning the gpio shell commands and my compiled executable, I might for example see channels 0 and 2 on my first go, just channel 1 on my second, and channels 2, 4 and 5 on my third try.

    If I then invoke the compiled C code without rerunning the gpio commands, I might for example then see channels 1, 4 and 5 on a first try. If I then restart the executable maybe just channel 1, and if I restart it again, perhaps just channel 0. There doesn’t seem to much rhyme or reason to which ones work each time it starts.

    This unpredictability is driving me a bit nuts. Does anybody know how I can get all 6 ISRs to work reliably each time ? Hopefully I’m just doing something a bit daft which is easy to spot !

    Many thanks, J/.

    • Ok – this system really isn’t good for replying to long posts, but I’ll see what I can do (it’s really just for brief comments to the posts, not a proper forum – but lookout for a proper forum soon!)

      wiringPiISR() does not require you to use the gpio command to export the pins – it actually does all that for you.

      You don’t need pinMode() either, but depending on your circuit, pullUpDownControl() is OK.

      What you might be seeing is a timing issue with the wiringPiISR function recieving the correct pin number – there is a race condition that was identified recently. Try this: Each time you call wiringPiISR() put the line delay (100); after it to force a delay. I’ve fixed it in the wiringPi v2 code – if you want a beta of this to test, email me.

      -Gordon

      • Gordon wrote:

        >Ok – this system really isn’t good
        >for replying to long posts,

        Sorry !

        > but I’ll see what I can do

        Thank you.

        >lookout for a proper forum soon!)

        🙂 OK.

        >wiringPiISR() does not require you
        >to use the gpio command to export
        >the pins

        OK – don’t know where I got that idea.

        >You don’t need pinMode() either, but
        >depending on your circuit,
        >pullUpDownControl() is OK.

        We do need a pull up.

        >What you might be seeing is a timing
        >issue with the wiringPiISR function
        >recieving the correct pin number –

        OK.

        >there is a race condition that was
        >identified recently. Try this: Each
        >time you call wiringPiISR() put the
        >line delay (100); after it to force
        >a delay.

        Curse of the day job ! OK, I’ll try that tonight.

        > I’ve fixed it in the wiringPi v2
        >code – if you want a beta of this to
        >test, email me.

        OK, will do.

        Thanks, J/.

      • Brilliant Gordon ! Adding the delay(100) after each call that sets up an ISR has made it do exactly what I’d expect. So what’s causing the critical race ?

        Re beta testing v2, yes, delighted to. If you can email to (hiden) and tell me what to download etc I’ll set it up on one of the Pis here.

        Cheers, J/.

        • It’s to do with the way I was passing the pin number into the ISR – it was sometimes being overwritten by the next call to wiringPiISR before the first one had read and stored it.
          Will drop you an email shortly.

          -Gordon

    • You can implement what you want with the exisitng library – my issues is how much do I provide – ie. just how specialised do I make it, or keep it general purpose…

      Let me think about it all..

      -Gordon

      • I´ve just had a quick check at wiringPi´s source, and I can see all the functionality for what I need is already there – all is missing is some interfaces. I´ll give it a try.

        Thanks!

  45. Hi Gordon

    Thanks for the great library,
    I have encounter a weird scenario, when i leave multiple ISR running infinite loop,
    during idle, i realized one of the globalcounter increase dramatically without incoming pulse.
    Have you experience similar situation when leaving the ISR idle for too long(say a day)? Or maybe is a sensor problem? Hope you can enlighten me.

  46. Hi Gordon,

    Thanks for the library. It really makes my life easier.
    But I would like to ask if is there anyway to increase the number of PWM pins?
    1 pin is not enough for my project 🙁

    Thanks.

  47. Hi Gordon,

    at first many thanks for this awesome project!
    I was looking for a library that i can use with Mono / C#, so i thought i can create a small wrapper class – as it looks like no one has yet done this with wiringPi..
    I struggled around with some difficulties importing and utilizing your functions and as it seems there are two major problems which i could only solve by customizing your source code:
    1) The most functions like digitalWrite, digitalRead, etc… are exported as function pointers (delegates) in wiringPi.h. Unluckily it seems that delegates can’t be imported via the [DllImport] statement (whereas delegates can be mapped as a method parameter..). I didn’t find any solution to that, so i decided to add small wrapper functions in wiringPi.c whose only destination is to call your delegates. Then i added normal function exports to wiringPi.h. That worked and i can now successfully read and write GPIO pins from Mono / C#.
    2) Then i tried to use the wiringPiISR method to register an interrupt. As i mentioned under 1) passing a callback delegate is possible and the test runs fine – with one strange drawback: if the interrupt callback is called once or more, when the main C# program is completed and wants to exit, it doesn’t terminate – until i trigger the interrupt once more. I saw that you spawn threads for polling the interrupt flag and i think that there must be some mismatch or misbehavior between the mono (console) application threading and the native threading or with the mono garbage collector. I didn’t succeed to solve this issue, so i decided once again to modify your source code to my needs: i refactored the inner code of function wiringPiISR in two parts, one registerInterrupt function which does all the stuff except spawning the interruptHandler thread and one pollInterrupt function which spawns the interruptHandler thread. Then i exported the new functions in wiringPi.h. This way i can now first call registerInterrupt(pin, mode), then spawn my own polling thread from within managed C# and finally in my own interruptHandler routine call your waitForInterrupt function. And this does the magic..

    So i now post this comment to share my experience. Perhaps you want to make adjustments to your code to provide compatibility to Mono / C#. Please let me know if so and if i can help with providing my customized wiringPi version or the C# wrapper class..
    I really would like to build my wrapper class on a “solid” base and take benefit from future development of your library without having to customize it every time. 🙂

    Best regards,
    Hannes

    • I’m currently abroad, so can’t give you a proper/long reply. However wiringPi v2 doesn’t use function pointers for the core functions – it still needs it for the wiringPiISR function though. If you want a beta version of v2. then fetch it with

      wget -O- http://unicorn.drogon.net/wiringPi-2.6.tgz | tar xfB - ; cd wiringPi ; ./build

      and see what the differences are.

      -Gordon

      • Hi Gordon,

        thanks for the Beta hint. I downloaded and adapted my C# wrapper class.
        The good news is that – as you mentioned – the problem with the function pointers is gone and i can successfully map the functions as expected.
        The bad news is that the polling thread mechanism is even more incompatible than than before: after calling wiringPiISR i get a strange output “^[[44;1R” in my console window and from then on the app is somehow “broken” (although the callback function seems to be called successfully..).
        So it would really be nice to have the possibility to bypass your creation of a polling thread. A very easy solution to this would be to skip the final lines after clearing the pending interrupts if the callback function argument is NULL (which seems as a good thing either way because if this is the case, your callbackHandler is going into an exception..). This way one could use the function simply as an interrupt setup function and do the polling stuff oneself, like:
        wiringPiISR(myPin, INT_EDGE_FALLING, null);
        and then in an own (managed) thread:
        if (waitForInterrupt (myPin, -1) > 0)
        myOwnCallback();

        Would do you think?

        Greets,
        Hannes

        Btw: the new modular design for extensions looks very promising. I got my piFace today and will test this at the weekend..

        • I’ll have a look at what you need to see if it’s possible. Of-course you can always write your own 😉

          -Gordon

        • Hmm, there must be something wrong in the new wiringPiISR function.
          The weird console output and app behavior disappears if i insert a return 0; before then lines:
          if (sysFds [bcmGpioPin] != -1)
          close (sysFds [bcmGpioPin]) ;

          • Ah, ok. the lines mentioned are new in the beta..
            As it seems to me, the array sysFds may not be initialized at this point (except in Sys mode), so the file handle is != -1 but 0 and thus still not a valid file handle..
            The fix is to initialize the sysFds Array in wiringPiSetup to -1 for all 64 elements. I inserted the following at the end of wiringPiSetup:

            int pin;
            for (pin = 0; pin < 64; ++pin)
            sysFds[pin] = -1;

            And for the callback bypass i inserted the following before the line "isrFunctions[pin] = function;":

            if (function == 0)
            return 0;

            With this changes i can work with the beta and do further tests..

        • Hey Gordon,

          i’ve tested the PiFace with the current release of wiringPi and with the Beta. With the Beta version i have problems to read the inputs. A 0 is always returned. (Writing outputs seems to be ok..)
          I tried to locate the failure in your code but didn’t find any.. Could you test it and have a look?

          Thanks in advance..
          Hannes

          • Ah, nailed it! The pin and mask was not calculated correctly in devLib/piFace.c…
            Here is the fixed method:

            int digitalReadPiFace (struct wiringPiNodeStruct *node, int pin)
            {
            uint8_t mask, reg ;

            pin -= node->pinBase;

            if (pin < 8)
            {
            reg = MCP23x17_GPIOB ; // Input regsiter
            } else {
            pin -= 8;
            reg = MCP23x17_OLATA ; // Output latch regsiter
            }

            mask = 1 << (pin & 7);

            if ((readByte (reg) & mask) != 0)
            return HIGH ;
            else
            return LOW ;
            }

            ;))

          • That’s why it’s a Beta right now 😉

            However since that code release, I’ve re-written all the PiFace code. So keep your patch in your code for now – the new code is slightly different – it uses the mcp23s17 driver as it’s base, and just makes calls to digitalRead/Write using the mcp23s17 driver now.

            -Gordon

  48. hi gordon, thank you very much for your library!
    i need you help for Pilock and PiUnlock functions.
    if i need to lock and unlock my variable “scelta” how can i do it? thanks for your time 😀

    • The piLock() and puUnlock() functions are designed to work with just 4 built-in semaphores – intended as an “entry-level” mechanism to using mutex’s. If you want to use your own mutex variables, then you need to … use your own. So look at the source code for piLock and piUnlock to see how it’s done – it’s in the file called piThread.c

      -Gordon

  49. First, thank you so much for making wiringPi available to the world!

    Multiple interrupts don’t seem to work for me. I am using version 2.06.

    pinMode(8,INPUT);
    pinMode(9,INPUT);

    If I do this then only 9 would generate an interrupt on button push. 8 doesn’t.
    wiringPiISR (8, INT_EDGE_FALLING, &myInterrupt8) ;
    wiringPiISR (9, INT_EDGE_FALLING, &myInterrupt9) ;

    ————————

    If I do this then only 8 would generate an interrupt on button push. 9 doesn’t.

    wiringPiISR (9, INT_EDGE_FALLING, &myInterrupt9) ;
    wiringPiISR (8, INT_EDGE_FALLING, &myInterrupt8) ;

    Please help shedding some light here.

    Thanks,

    -Peter

    • I went back to gpio version: 1.12 and multiple interrupts worked fine. I need to go to 2.06 because I need to have microseconds resolution from delayMicroseconds. Would it be possible to have both multiple interrupts and microseconds resolution?

      Thanks,

      -Peter

      • i’ll check again, but it worked under v2 the last time I used it mysel – however 1.12 has microsecond accuracy in delayyMicroseconds – that code didn’t change from v1 to v2 …

        -Gordon

        • Hi Gordon,

          Thank you so much so for your quick reply. The exact same code works with version 1.12 for multiple ISRs, but does not work with version 2.06. I didn’t realize 1.12 also has microseconds accuracy. I should have checked :-).

          I greatly appreciate all of your work and effort. I teach kids basic programming and electronics. wiringPi just makes my teaching so much easier because it hides all the low level complexity which can discourages the kids very quickly.

          Regards,

          -Peter

          • Do a ‘git pull’ on it and try now. I’ve found some issues with an array which wasn’t initialised properly.

            Let me know if it’s now working vith v2.

            -Gordon

          • It’s working with v2 now.

            Thank you so much for fixing it so quick!

            -Peter

          • It’s working with v2 now.

            Thank you so much for fixing it so quickly.

            Regards,

            -Peter

  50. Hi,
    First of all thanks for the excellent work.
    i have only one question: when i use gpio -v he tell me that i have a revision 2 board.
    But when i use piBoardRev(void) he return to me 1.
    thanks for all.

    • I’m not seeing this myself:

      gordon @ dragonpi: cat rev.c

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

      int main (void)
      {
      printf (“This is a rev: %d Pi\n”, piBoardRev ()) ;
      }

      gordon @ dragonpi: gcc rev.c -lwiringPi
      gordon @ dragonpi: ./a.out
      This is a rev: 2 Pi
      gordon @ dragonpi: gpio -v
      gpio version: 2.07
      Copyright (c) 2012-2013 Gordon Henderson
      This is free software with ABSOLUTELY NO WARRANTY.
      For details type: gpio -warranty

      This Raspberry Pi is a revision 2 board.

      • sorry, my fault i’ve write piBoardRev without () and made unpredictable result… thanks very mutch for the answare and sorry for the time lost.
        bye

  51. Hi,

    This lib really seems to be what I need to get a little project I’m working on going. But I have been searching the examples and API description as to how to setup the SPI’s to be in slave mode, so that the connected SPI unit will run the clock etc. Is this supported, if yes, how do i set it up?

    Best regards Ole

  52. I have some troubles using the interrupts on the RPi. When i connect a 433.92Mhz receiver to a wiringPiISR interrupt (which also generates a lot of noiese), the (correct) interrupts are triggerd with some delay. Initially, no pulses from my remote control are received (just noise), but after a second or so, they start arriving. Even when i stop and start the program, it still receives the pulses for about 3 to 5 seconds. I know that this is an incorrect behavior because when i use a manual interrupt check with digitalRead or by using the lirc_rpi module, the values are immediately received and stopped after sending. Any clue how to solve this?

  53. Hello Gordon, Thank you for having knowledge in this area. With regard to your quote above … “With a newer kernel patched with the GPIO interrupt handling code, (ie. any kernel after about June 2012), you can now wait for an interrupt in your program. This frees up the processor to do other tasks while you’re waiting for that interrupt. The GPIO can be set to interrupt on a rising, falling or both edges of the incoming signal.” Now (June 2013) I am running latest kernel (Pidora) with modification to use new ISR- and DMA-driven SPI drivers. That is working nicely. Next I want to react to pushbutton interrupt on GPIO pin to avoid polling loop. Your message above appears to indicate I may be able to do this from user space now. I would prefer writing low-level code myself instead of linking with wiringPi, since it may interfere with the SPI solution I already have working well. Could you please provide some hints on how I can find means to use latest kernel’s programming interfaces to accomplish user-mode event handling triggered by gpio interrupt. Thank you.

  54. Gordon,
    Thanks for all of your work. I have been attempting to setup some interrupts for the past few hours. I’ve searched a few different pages on this site and a bunch of other sites, but still have found nothing that works or resembles my problem.

    This is a short relevant snippet from my program:
    45 if(wiringPiSetup() == -1)
    46 printf(“Unable to start wiringPi\n”);
    47
    48 delay(1000);
    49
    50 pinMode(A_LED, OUTPUT);
    51 pinMode(B_LED, OUTPUT);
    52 pinMode(BUT_LED, OUTPUT);
    53
    54 if(wiringPiISR(PIN_A, INT_EDGE_RISING, &incMenu) < 0 )
    55 {
    56 fprintf(stderr, "Could not setup ISR: %s\n", strerror(errno));
    57 return 1;
    58 }

    It compiles fine, but upon running the program (as root) I get this error immediately:
    wiringPiISR: execl failed: No such file or directory
    wiringPiISR: unable to open /sys/class/gpio/gpio17/value: No such file or directory

    I was able to write a "blink" program to make sure that I was able to access the pins, which I was able to do. Do you have any idea what could be causing this?

    Some other information:
    OS: arch linux
    RPi: model B Rev 2
    wiringpi: latest from repos (gpio v2.07)

    thanks in advance

    • sorry, i did not realize that the formatting would be stripped. I’ll make it a little nicer to read (also, PIN_A is wiringPi 0 or GPIO 17 as the error indicates):

      if(wiringPiSetup() == -1)
      {
      printf(“Unable to start wiringPin”);
      }

      delay(1000);

      pinMode(A_LED, OUTPUT);
      pinMode(B_LED, OUTPUT);
      pinMode(BUT_LED, OUTPUT);

      if(wiringPiISR(PIN_A, INT_EDGE_RISING, &incMenu) < 0 )
      {
      fprintf(stderr, "Could not setup ISR: %sn", strerror(errno));
      return 1;
      }

    • The key message is:

      wiringPiISR: execl failed: No such file or directory

      the ISR function requires the use of the gpio program, and if it can’t find that, then all bets are off. The gpio program must be installed in /usr/local/bin (for now). Do check that the gpio program is installed correctly.

      -Gordon

      • Thanks for the reply. It seems as though it gpio is installed in /usr/bin, which is strange because I installed wiringPi using pacman.
        After removing and reinstalling it (with pacman) it is still dropping gpio in /usr/bin.

        I copied it into /usr/local/bin and it seems to work ok (the program compiles and runs, not just exiting like it did before). Unfortunately I am not in front of my RPi right now, so I cannot trigger the interrupts or verify (I did this through ssh)

        • I suspect whoever put the pacman thing together changed the install locations without realising the issue ere. Just create a symbolic link from /usr/local/bin/

          -Gordon

  55. Hi Gordon

    How I can use “digitalWriteByte()”?
    Which are the eight GPIO pins written by this function?

    I simply want to use it to make a supercar effect(8 LEDs) and I would use a write byte command, so to use a shift.

    Thanks in advance

    • thw writeByte function takes 8 bits an apploys them to the 8 GPIO pins (ie. the ones not dual-purposed to the I2C, Serial and SPI interfaces).

      you might be easier to just use the digitalWrite() functions. See blink12.c in the examples directory for a sequencer example.

      -Gordon

  56. Hello Gordon,

    in the last days I tried to connect a button to the auxilliary GPIO P5 connector. The ISR should be called when the button is pushed. But nothing happened, no matter which gpio port I use. With the main GPIO connector P1 everything works great.

    Isn’t it possible to use ISRs with P5?

    Andreas

    • It should work… but it’s not something I’ve personally tested. You ought to be able to test it with the gpio command – e.g. in one window run

      gpio wfi 20 falling

      and in another right

      gpio mode 20 up
      gpio move 20 down

      which should trigger the interrupt – I’m not near a Pi right now so can’t test though.

      -Gordon

      • Thanks for your answer. I tried your commands.

        gpio8 and gpio9 isn’t working.
        gpio10 and gpio11 is working.

        But when I connect my button to gpio10 or gpio11 no interrupt is triggered.
        Hm I can’t find the failure.

  57. OK it’s working. I thought gpio name and pin are always the same, but on P5 it’s different.

    Thanks for your help

  58. Hello~

    If I want use WiringPI on Arch Linux for Raspberry PI,
    How should I do?
    I can not use apt-get on Arch Linux.

    Does there has source code i can download directly(tar ball?)?
    Thanks all.

    • I got the tar ball of WiringPI,
      But i can not build it on Arch Linux,
      Does anyone had ever done this?

      thanks.

  59. Hi Gordon,

    at first a lot of thanks for your great work! I’m using wiringPiISR to read out values from a sensor. It works fine in the case no classes are used. But putting wiringPiISR into the constructor of a class and passing the address of a member function as third parameter, my g++ compiler gives me following error:

    ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.

    A solution would be to use a static member function to call my class member interrupt routine, but for that purpose I have to pass it a parameter containing the this-pointer from the calling class. But in wiringPiISR it is not possible.

    How can I solve this problem?

    Thanks,
    Tom

  60. Hi Gorden,

    I working on ISR, I connect one of GPIo pins with an output of a motor’s encoder..and use ISR to count number of pulses in a second..

    I use the following code inspired from your isr-osc.c :

    static volatile int globalCounter=0 ;
    void myInterrupt (void) { ++globalCounter ; }
    int main (void)
    {
    int gotOne, pin ;
    int myCounter=0;
    int lastCounter=0;

    wiringPiSetup () ;

    if (wiringPiISR (5, INT_EDGE_FALLING, &myInterrupt) < 0)
    {
    fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ;
    return 1 ;
    }

    for (;;)
    {
    fflush (stdout) ;

    while (myCounter == globalCounter)
    delay (1000) ;

    printf (" Done. counter: %6d: %6d\n",
    globalCounter, myCounter – lastCounter) ;
    lastCounter = myCounter ;
    myCounter = globalCounter ;
    }

    what I expect is to give me number of times there was an edge-fall in a second.. but its not giving me consistent outputs..
    Also, when I change EDGE_FALLING to EDGE_BOTH parameter… the expected output should be double of the previous one… but instead its giving surprising outputs…

    Kindly point out the mistake I am making..

    Thanks a lot

    🙂

    • Nothing obvous wrong with it.

      You can test it by using the gpio command – e.g.

      gpio mode 5 up
      gpio mode 5 down

      each up/down transition ought to trigger an interrupt. (That’s enabling the internal pull-up then pull-down resistors)

      Other than that, my next step would be to hook a ‘scope to it to check for noise, etc. (and note that the maximum I got was in the region of 66K interrupts/sec. hopfully your encoder is producing less than that!)

      -Gordon

  61. Hi Gordon. First of all I am very Grateful for this powerfull library WiringPi.

    I am making a program and I use the pin 7 of my rasp as INPUT for an interrupt.
    I use the function wiringPiISR(7, INT_EDGE_RISE,&myInterrupt), but in some parts of the program I would like to disable the interrupts and enables them later.
    Can I do this? Wich way?.

    Best Regards.

  62. While playing with the wiringPiISR() function i had a look at the isr.c example.

    My experiences with 8-bit microcontrollers told me that access to 16- or 32-bit variables isn’t atomic. So in meantime i have to block interrupts that are modifying the same memory area.

    The ARM cpu seems to be 32 bit. So no special care must be taken while accessing int like elements concurrently in main() and ISR?

    Thank you!!
    Klaus

    • 32-bit read/writes should be autonomous on the ARM, so as long as you have one process writing and 1 (or more) reading you ought to be fine at that level. If you’re unsure, then you can use a mutex to guard accesses.

      -Gordon

      • thank you for you quick reply!

        I worry that a mutex in ISR may cause deadlocks? Is the ISR suspended while waiting in piLock()? Otherwise main() would not continue to free the mutex lock.

        • You only set the mutex when 2 processes are writing the same variable, or a process is reading it, and you only set it at the point when you’re updating the shared variable… e.g.

          In the ISR:

          lock (which waits)
          update variable
          release lock

          and in another process:

          set lock (which waits)
          read variable
          release lock

          So the opportunity for deadlock is eliminated – unless the thread crashes during the time the lock is set – in which case you have other issues to wory about.

          However, realistically, as 32-bit operations are atomic and carried out in a single cycle, as long as only one process is writing a variable (you can have many readers), then you shouldn’t need the locks.

          -Gordon

          • Ok, i have the same opinion about the fact that locks are unnecessarry in my special case.
            Apart from that the question remains wheather ISRs in general can be interrupted by normal threads (and main()).
            But since you expect no deadlock problems in your example, obviously they can :-).

            Thank you!
            Klaus

          • Do be aware that under Linux in user-land there is no true concept of an ISR – I’ve just called that as it’s an analogy. It’s really a Posix thread running concurrently with your main program (at a higher priority, usually). The thread blocks on reading the “file” and carries on when the “file” has something to read – which mimics the behaviour of an ISR in a microcontroller. (The file having data avalable is triggered by a real interrupt though, but as it has to go via the Linux kernel the response time is somewhat longer than on a typical microcontroller). However the net effect is more or less the same.

            The thread is effectively deschedulled until it’s woken up by the hardware interrupt, but if it wasn’t waiting on that, then it could be inetrrupted by another thread running at the same priority, but not one running at a lower priority.

            -Gordon

  63. Hi Gordon,

    i am relatively new to c++ and microcontroller programming. your library is a great help. i am trying to create a small logic analyzer for an rfm22b radio module. i connected the raw data (gpio2 on rfm22) to pin5 on the raspberry. but at the moment the isr method is registered the complete system hangs. if i disconnect the wire the system is responding again.

    i tried the gpio tool to trigger manually some highs and lows. and that worked without any problems. i also just read all gpio states via the gpio tool and can see that the pin is toggling between high and low (as expected)

    i am using wheezy 3.2.27+ #2 PREEMPT.

    void Logger::loop() {
    gettimeofday(&tv, &tz);
    __time_t timestamp_seconds = tv.tv_sec;
    startTime=timestamp_seconds;

    wiringPiISR(5, INT_EDGE_RISING, Logger::isr0);
    while (counter < maxCount) {
    delay(300);
    std::cout << "waiting for more samples. got already: " << counter <<"\n";
    }
    std::cout <handleInterrupt();
    }

    i read something about a bug when a pin is set to low. are there any requirements to have the isr method correctly working?

    Thank you

    Florian

    • I spent a year programming in c++ once… then forgot all about it..

      I’ve not seen anything about that bug you mention though.

      Is it possible the sending device is toggling the interrupt line faster than the Pi can respond? The upper level of frequency is about 66KHz.

      -Gordon

  64. thank you for your reply,

    i made some progress. the updaterate is about 10KHz. If i start the programm without connecting the pin and then afterwards connecting the pin it does work. very strange. hmm… maybe it is to fast at the beginning or something like that.

  65. you gave me the perfect hint!

    after a reset of the rmf module gpio2 exports the microcontroller frequency. and that is to much.
    first step was to ensure that the correct mode was setup before the interrupt was registered.
    the second step was: after finishing logging i had put in the following line
    system (“/usr/local/bin/gpio edge 24 none”) ;
    to deregister the interrupt properly.

    if i would not do that. i would get into trouble again after restarting the logger because the rfm would be resettet, the frequency would be to high and even if there would be no isr method registered, the raspberry would freeze. so here is a +1 for a method that deregisters interupt handlers.

    but for now i am happy and thank you for your hint!

  66. Hi Gordon,

    Thanks for publishing this great library.

    I have a question: do you know what’s the shortest pulse that would trigger an interrupt? In my app I don’t care much about the response time (no real time need), but I do care about missing an event.

    The signals I’m monitoring usually have pulses of around 1ms that I need to be 100% sure I will catch every time.

    Thanks for any help on this.

    Best regards,
    Awer

    • I’m fairly sure it’s all latched in hardware, so the shortest pulse detectable ought to be well under 1µS.

      My own experiments – connect an output pin to an input pin, and when the interrupt happens on the input pin, reverse the polarity of the output pin achieves approximately 66KHz – so the pulse widths were about 15µS wide.

      The latency is mostly due to the Linux kernel having to wake the sleeping process up. If you were doing this in the kernel then it would be much shorter.

      -Gordon

  67. Hi Gordon,

    My first questions : I m using a same program as ur isr.c to capture Interrupt caming from a wheel.
    When I turned it manualy everything works just perfect,but when I turn the motor its shows too much interrupt than reality (ex. it shows 47 instead of 10!)
    The second one : am willing to control four motors and therefor I need 4 PMW outputs is it possible if yes witch GPIO you recommand?

    Thanks for answring and for this great library and work !

    Regards.
    Walox

    • Sounds like it might be switch bounce to me. Or noise on the input line.

      you can use the softPwm code to speed control 4 motors.

      -Gordon

  68. Hi Gordon, Many thanks for the wiringPi library. I have been using it for a couple of years now through Python. I have now had reason to try to get it working through C++ and am having problems. Simplified, I have…

    #include
    void lightLED()
    {
    pinMode (1, OUTPUT);
    digitalWrite (1, HIGH);
    cout << digitalRead (1) < g++ -o myprog myprog.cpp -lwiringPi

    which seems to be successful. The prog runs but the digitalRead returns 0 and no lED lights. I have checked pins etc but anyway digitalRead should return high, should it not? I am thinking that I am missing something off my compile line or some other include is necessary. Or am I just being dumb?

    Any help would be gratefully received. Regards, TC

  69. sorry, garbled above…

    (grrrr, pasting code in posts again!)

    myprog.cpp +++++++++++
    chevron include is wiringPi.h

    void lightLED()
    {
    pinMode (1, OUTPUT);
    digitalWrite (1, HIGH);
    cout << digitalRead (1);
    }

    compiled using ++++++++++++++
    g++ -o myprog myprog.cpp -lwiringPi

    Thanks! TC

  70. Hi Gordon,

    I’ve naively embarked on an RPi project to report currents in my household breaker-box. The ADC0816 application notes hint that it needs a (500 kHz) clock pulse and I came across your code for generating that on the PWM GPIO pin. Am I on the right track?

    Thanks, and Merry Christmas.

    • That’s not the best ADC to interface to the Pi – it’s really designed to be directly interfaced directly to a microprocessor rather than via a GPIO interface. You’ll run out of Pins on the Pi connecting that one up.

      How many channels do you actually need? If only 4 or 8, then look at the mcp3004 or mcp3008 which interface to the SPI bus.

      -Gordon

      • Thanks for the quick response. I should have mentioned that I (will) have a 32 channel GPIO expander from AB Electronics to interface with the ADC0816. The ADC gets its analog inputs from 16 ACS712 current sensors.

        I’m puzzled by the application notes for the ADC which is why I asked you about the needs of its Clock pin. My understanding is that if I put the sensor number on the ADC address pins and put Start and ALE high and then low, wait at least 8 clock cycles then put OE high, the digital value of that sensor output will appear on the ADC data pins. AB Electronics has some example code that reads the I2C GPIO pins to get the data from their expander. Do I have this right?

        Thanks for your help with this.

        • Well yes, you can use the clock functions of wiringPi to generate that clock for you. I’d check the output with a ‘scope just to make sure it’s doing the right thing though. The rest is just code bashing – wiringPi supports that GPIO expander boards (it’s just a pair of mxp23017’s) but you’ll need to do some bit twiddling to assemble the 8 bits into a single byte (it doesn’t yet support a byte read function from off-board hardware)

          Good luck!

          -Gordon

  71. Once I’ve got the GPIO18 pin ticking away at the required frequency of about 500kHz, having configured it for hardware PWM with wiringPi, can I count pulses? I need to wait 10 cycles after I start the ADC, for the data to appear. Is there a pulse counting register I can read? Or maybe the code could sleep for some time, ~20us?

  72. Hi and thanks for wiringPi. I am using it with the hwiringPi wrapper for Lazarus. The library seems to compile fine, but when I use it in my program, it reports that it cannot link piHiPri. I note that piHiPri seems to be the only file which has a .c and a .o file, but no .h file. Is this right? I don’t know enough C to fix it, and have solved the problem for now by copying the code from piHiPri.c into wiringPi.c. It may not be the best solution, but at least I can compile my program and control the GPIO port.