0

i want to program in C a simple sequential control with the raspberry. The current task is: If a button is pressed, something (e.g. a LED) shall be switched on for 5 seconds and then go off itself. But if the button is pressed within the 5s window the LED should shut off immmediatley.

Because I need to do this for about 10 buttons, while also doing other stuff, my first idea was to create a thread for each waiting. This seems fairly easy for the 5second waiting part. But how do I achieve the stopping on the next press of the button?

So far the code is roughly as follows:

#include "wiringPi.h"

#define BUTTON_PIN    15
#define OUTPUT_PIN    7

void buttonInterrupt(void){
    // do some anti jitter

    if (buttonPressedFirstTime){
        piThreadCreate(waitingThread);
    }

    if (buttonPressedSecondTime){
        // do what???
    }
}

PI_THREAD (waitingThread){
    digitalWrite(OUTPUT_PIN,HIGH);
    delay(5000);
    digitalWrite(OUTPUT_PIN_LOW);
    return 0;
}

int main(Void){
    wiringPiSetup();
    pinMode(BUTTON_PIN,INPUT);
    pinMode(OUTPUT_PIN,OUTPUT);

    wiringPiISR(BUTTON_PIN,INT_EDGE_RISING,buttonInterrupt);

    while(1){
        //do other regular stuff
    }

    return 0;
}

But how do I handle the second press of the button?

I also plan to get away from the wiriingPi pthread interface. I will use pthread myself, because this enables me to provide arguments to the started thread. So I could start the thread with the PIN it should use as argument.

But interrupting the thread on the second press of the button and switching the corresponding pin off is not solved, yet. I was thinking of maybe using libev, replacing the delay by a ev_timer. But I am not sure, whether I could skip the rest of the timer on the second button press.

So do you have an idea how to achieve this very simple sequential control? Thank you in advance.

Gunter
  • 101
  • 2

1 Answers1

1

Yikes, another busy loop for buttons.

This is not the way to deal with them. Button events can be responded to as hardware interrupts. You do not need threads although depending on what else you are doing you may like to use them. I think the best practice it to first consider a single threaded, event based model before you go with the more complex and clumsy multi-threaded one, which often does not solve the "problems" people think it is required to solve.

This is not to say multi-threading is bad, just it is overused.

I also plan to get away from the wiriingPi pthread interface.

You not need a pi specific library such as WiringPi to deal with buttons and LEDs, except to the extent that you want to do slick PWM effects with the latter. I've written an introduction to using the sysfs interface programmatically; although the example is in perl, the original documentation it refers to is for C. It is complete and easily understood if you are familiar with the poll(2) or select(2) system call interfaces.

If you are not familiar with poll() or select() you should be. This is a fundamental feature of the language required for many programming tasks. It is certainly more fundamental than the POSIX threads extension.

As described with reference to the perl example in that other question, the basic idea is you have an infinite loop centered on poll or select which are passive waits. They literally put the process to sleep until one of the things they are listening for happens, then the process is woken up and can deal with the event. You do not need libev or anything other than standard C for this. This is how system daemons and application servers work. It is probably the most widely used programming model of all time.

I mentioned that you cannot do fancy PWM effects with an LED (because the generic sysfs interface does not include hardware PWM), however, you can obviously turn them on or off. You can do simple software PWM well enough to dim an LED, although this would require a separate thread. In this case I would instead recommend WiringPi, pigpio, or libbcm2835 to control the LED, and hardware PWM will again get you out of the extra thread. Note however that the number of hardware PWM channels is limited.

But if what you want to do is wait for buttons and turn LEDs on and off, it is fairly simple to do with standard C in a single thread.

goldilocks
  • 60,325
  • 17
  • 117
  • 234