I recently bought a PIR Motion Sensor and wrote a java program which prints in the console whenever movement is detected. I connected the pins properly, and the signal to GPIO_17 according to the BCM numbering scheme. Here's my code:

import com.pi4j.io.gpio.*;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;

public class Main {

    public static void main(String[] args) {

        GpioFactory.setDefaultProvider(new RaspiGpioProvider(RaspiPinNumberingScheme.BROADCOM_PIN_NUMBERING));
        GpioController gpio = GpioFactory.getInstance();
        GpioPinDigitalInput motionDetector = gpio.provisionDigitalInputPin(RaspiBcmPin.GPIO_17, "motionDetector", PinPullResistance.PULL_DOWN);

        System.out.println("Motiondetector started.");

        motionDetector.addListener(new GpioPinListenerDigital() {

            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                System.out.println("State changed");


        while(true) {

            try {
            } catch (Exception e) {




This code should print the text "State changed" in the console whenever I move my hand in front of it, but for some reason nothing happens. But when I add this code to the while loop,


It does print high every 50 milliseconds whenever I move my hand and low when nothing moves. So for some reason the event doesn't trigger. Can anybody tell me why this happens, and how I can solve it?

2 Answers 2


I had the same problem. Somewhere I read that the BCM numbering schema is buggy concerning the event handling. You have to take the WiringPi Numbering Schema, then it works!

Your temporary solution is polling while the event handling here depends on interrupts.


I found a temporary solution which works just fine too, although I'd still like to know why the listener doesn't work.

boolean state = false; //false means low voltage, true means high voltage
boolean previousState = false;

while(true) { 

        if(motionDetector.getState().isHigh()) {
            //high voltage detected, meaning state = true
            state = true;
        } else {
            //low voltage detected, meaning state = false
            state = false;

        if(state != previousState) {
        //when state is not equal to previous state, it means the state has changed, either from low to high or high to low.
            if(!previousState) {       
                //Previous state is false, meaning voltage was low. This means the voltage went from low to high, meaning motion was detected.
            } else {
                //Previous state was true, meaning voltage was high. This means the voltage went from high to low, so the motion has stopped. 
            previousState = state;
            //sets previous state to current state and the loop starts over


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.