3

I set up a simple curcuit and tried a pullup and a pulldown scenario, but both lead to a lot of "false positives". Currently I ended up with the circuit you can see in the image. I have no button attached, but jumpingwires i connect and disconnect to a breadboard. Even when I don't connect it there is a level increase.

enter image description here

This is the code I used for the setting:

import RPi.GPIO as GPIO
import time
AmountMotionsDetected = 0
PIRinPin = 17

def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PIRinPin, GPIO.IN, GPIO.PUD_DOWN) #  Set pin to be an input pin and set initial value to be pulled low (off)
    GPIO.add_event_detect(PIRinPin, GPIO.RISING, callback = MotionDetectedCallback, bouncetime = 300)


def MotionDetectedCallback(channel):

    global AmountMotionsDetected
    print ("We have {} motions detected ".format(str(AmountMotionsDetected)))
    AmountMotionsDetected = AmountMotionsDetected + 1

def endprogram():
    GPIO.cleanup()


if __name__ == '__main__':

    setup_gpio()

    try:
        while True:
            button_state = GPIO.input(PIRinPin)
            if button_state == GPIO.HIGH:
                print ("HIGH")
            else:
                print ("LOW")
            time.sleep(1)

    except KeyboardInterrupt:
        print ('keyboard interrupt detected')
        endprogram()

Here is a photo of the setup (I use the orange jumoing wire to simulate the switch)

enter image description here

Update 2: I found a hint why there might be a problem. Therefor I had to modify the script a little bit as you can see above. When I now run the script and connect/disconnect the jumping wire periodically, I see that sometimes (but not always) there is false "rising" detection when I disconnect the wire. This seems to be a common issue since 2014?

If that's true, that function would be useless.

Wolfgang
  • 39
  • 1
  • 5

6 Answers6

4

There are numerous errors in the script.

  1. time module is not imported
  2. PIRinPin is not defined.
  3. AmountMotionsDetected is not defined, set as a global, or incremented.

Once those errors are corrected the script works properly.

Therefore you have connected to the wrong GPIO or you are using very long wires.

WoJ
  • 543
  • 2
  • 6
  • 15
joan
  • 71,852
  • 5
  • 76
  • 108
3

I would start by debugging this on the command line using gpio. gpio readall can tell you if the pin gets configured correctly, and whether it changes the state. See if the pin changes state when you pull it to 3.3V / GND via a resistor. When that works, get back to your code and see how it behaves. Once it works, switch to an internal pulldown.

Dmitry Grigoryev
  • 28,277
  • 6
  • 54
  • 147
2

Your problem seems to be related to "electrical bounce" which is caused by electrons arching from one wire to another as your contact wires (or switch contacts) come close together. Basically, your computer reads multiple "contacts" before your subroutine has a chance to finish executing.

The way to get around this is by stopping the loop that waits for a positive contact before the subroutine starts and the restarting that same loop once all of your commands have been executed.

I code in a different language for different hardware but the concept is the same. this is only to show the concept. In pseudo code it would look like something like this:

_global waitForButtonContact = true;
While(waitForButtonContact){
   buttonIsPressed = gpioCheckButton();
   If(buttonIsPressed){
       doSomething();
   }
}

Function doSomething (){
     //Do stuff here
     waitForButtonContact = true;
     Return;
}

Function gpioCheckButton(){
    if(//weDetectedTheButtonWasPressed){
       waitForButtonContact = false;
       Return true;
    }
Else{
      Return false;
   }

}

goldilocks
  • 60,325
  • 17
  • 117
  • 234
Marco
  • 21
  • 1
0

@Marko was pointing me in the right direction. I updated my question and added some links to my research about this issue and came up with the following workaround:

if not GPIO.input(PIRinPin) == GPIO.HIGH:
    return

The complete code looks as follows:

import RPi.GPIO as GPIO
import time
AmountMotionsDetected = 0
PIRinPin = 17

def setup_gpio():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PIRinPin, GPIO.IN, GPIO.PUD_DOWN) #  Set pin to be an input pin and set initial value to be pulled low (off)
    GPIO.add_event_detect(PIRinPin, GPIO.RISING, callback = MotionDetectedCallback, bouncetime = 300)


def MotionDetectedCallback(channel):
    global AmountMotionsDetected
    if not GPIO.input(PIRinPin) == GPIO.HIGH:
        return

    AmountMotionsDetected = AmountMotionsDetected + 1
    print ("We have {} motions detected ".format(str(AmountMotionsDetected)))

def endprogram():
    GPIO.cleanup()


if __name__ == '__main__':

    setup_gpio()

    try:
        while True:
            time.sleep(1)

    except KeyboardInterrupt:
        print ('keyboard interrupt detected')
        endprogram()

Maybe someone comes across this issue in future, and can give me a correct solution - for me this basically means that the interrupt processing is very buggy...

Wolfgang
  • 39
  • 1
  • 5
0

Been in the electronics 30 years, never saw a so poorly designed input circuit. First thing first, never bring vcc (regardless it is 3.3 or 5v) to a input jumper ! Your jumper should be between ground and input. With a pullup, and use a 10khoms pullup not 220R !

Also debounce input reading algorithm goes like this (low level) 1. Read state 2. Compare previous state 3. No change ? Reset counter to whatever 4. Change ? Memorise new state, decrement counter 5. Only when counter reach 0 (reading it n times SAME state) then proceed with piece of code

-1

Your pull up connection is wrong in the image you can see the correct connectionenter image description here