I'm writing a program that will run a timer until the user plugs a wire into two ports and presses a big red button. At home, my program works pretty well, but when many people are in the same room, they are able to stop the timer by just touching the ports. This is somewhat problematic and I don't know how to combat it.

In a nutshell, My GPIO pins are set up like this:

def pressBigButton(pin):
        self.paused = 1

self.switchPin = 4
GPIO.setup(self.switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

From what I understand, this should set the pin to HIGH voltage and should fall when the user presses the button. My hope was that this would eliminate the possibility of static electricity causing a spike in voltage, tripping the timer prematurely. In addition, I connected the terminals to the GND pin, but this doesn't seem to help.

simple diagram

I may have some of the symbols wrong. Apologies.

If you need the full code, i have it here.

import Tkinter as tk
from Tkinter import *
import RPi.GPIO as GPIO
import math
import time

class ExampleApp(tk.Tk):
    def __init__(self):        

        # make it cover the entire screen
        w, h = self.winfo_screenwidth(), self.winfo_screenheight()
        self.attributes("-fullscreen", True)
        self.geometry("%dx%d+0+0" % (w, h))

        self.label = tk.Label(self, text="", width=9, height=3, font=("Courier Bold", 160), fg='brown', bg='black')
        print "startTime", time.time()
        #self.total can be changed to alter the timer's length, but it should never be changed in runtime
        #Default = 3600
        self.total = 3600
        self.remaining = self.total
        #timerMode 1 = standard clock, 2 = percentage
        self.timerMode = 2
        self.paused = 1

        def pressSpace(event):
            if(self.paused == 0 and self.remaining > 0):
                self.paused = 1
                self.paused = 0

        def pressEsc(event):
            if(self.paused == 1):

        def pressBigButton(pin):
            self.paused = 1

        #bind spacebar to pause the timer
        self.bind("<space>", pressSpace)

        #bind Esc to kill the process
        self.bind("<Escape>", pressEsc)

        #initialize GPIO pin
        self.switchPin = 4
        GPIO.setup(self.switchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        self.pinStatus = GPIO.input(self.switchPin)

        self.setTime() #sets the initial clock before unpausing

    def mainLoop(self):        

        if self.remaining <= 0:
            #Time has expired. Players lose
            self.paused = 1
            self.label.configure(text="TIME!", font=("Courier Bold", 160), fg='#000000', bg='#FF0000')
            #There is still time on the clock. Check if player has flipped the switch to stop the timer
            if not(GPIO.input(self.switchPin)):
                self.paused = 1

            strTimer = self.setTime()
            self.label.configure(text= strTimer)
            if(self.paused == 0): #Check if the timer is toggled to pause
                self.remaining = self.remaining - 1
                self.after(1000, self.mainLoop)
                #time.sleep(1.0 - ((time.time() - self.startTime) % 1.0))

    def setColor(self):
        fremaining = (1.0*self.remaining)
        blueDown = self.twoDigitHex(255*(fremaining/self.total))
        redUp = self.twoDigitHex(255-(255*(fremaining/self.total)))
        color = "#" + redUp + "00" + blueDown

    def twoDigitHex(self, number):
        return '%02x' % number

    def setTime(self):
        if(self.timerMode == 1):
            #STANDARD CLOCK
            #creates a readout of constant length regardless of significant digits
            h = str(math.trunc(self.remaining/3600))
            remainder = (math.trunc(self.remaining % 3600))
            m = str(remainder / 60)
            s = str(remainder % 60)

            time = []
            index = 0
            for i in time:
                if (len(i)==1):#If a number is 1 digit, make it 2 digits
                    time[index] = ('0' + i)
                index += 1
            if(time[0] == '01'):
                return ('1:' + time[1] + ':' + time[2])
            elif(time[0] == '00' and time[1] != '00'):
                return (time[1] + ':' + time[2])
            elif(time[0]== '00' and time[1]== '00'):
                return (time[2])
                return (time[0] + ':' + time[1] + ':' + time[2])

        elif(self.timerMode == 2):
            #PERCENT CLOCK
            percent = (100*(self.remaining / (self.total*(1.0))))
            return(str('%.1f%%' % percent))

if __name__ == "__main__":
    app = ExampleApp()

tl;dr: GPIO.FALLING sometimes trips when users touch terminals A and B. I suspect static electricity. Please advise.

  • The question is vague. "user plugs a wire into two ports" WTF? the diagram seems to have nothing to do with the Pi header. – Milliways Dec 1 '15 at 9:04
  • The GPIO will be floating unless pulled low or high by default (the pull should be opposite to the switch on setting). Normally the internal pulls are sufficient to prevent static problems unless you have long wires. What pulls are you actually using? – joan Dec 1 '15 at 9:18
  • Sorry, I have a thick gauge wire attached to two 1/4-inch mono audio plugs (imgur.com/fmkwVF6). The user plugs each end into one of these ports (imgur.com/lHGz07F) which are each attached to a single wire A and B – user7567 Dec 1 '15 at 16:34
  • As for the diagram having nothing to do with the header, that may be a misunderstanding on my part, but I honestly don't understand what you mean. Pin 4 is set up with a pull up resistor, the program checks for a falling edge, and that falling edge triggers a function. The diagram is just how I have things set up right now. If you'd prefer a picture, this is what my circuit looks like imgur.com/z1Z5HuJ. The two white wires should each be attached to a female mono aux port, but I don't have those pieces with me right now. – user7567 Dec 1 '15 at 16:46
  • 1
    @user7567 Whatever you have stuck on the Pi it is not intended to be that way around. To me it seems like it should be removed, turned 180 degrees, and then be put back on. – joan Dec 1 '15 at 16:50

If it is A and B at the same time the high voltage should travel along the skin.

| improve this answer | |

Get rid of the external pull up resistor and use an internal pull up. It takes microamps to trigger an open input otherwise.

| improve this answer | |
  • Whilst the internal pull ups are between 30k and 100k, which is greater than the external pull up used by the OP, I believe that 10k, as used by the OP, should still be enough to avoid the effects of static. See GPIO pull up resistance. – Greenonline Mar 11 '16 at 3:01
  • Look at the schematic. The pull up is disconnected when the switch is open leaving a bare pin. I guess he could move the pull up to the other side of the switch, but internal pull ups are put in the chip by a designer that knows more than I do and they cost nothing. – PaulF8080 Mar 11 '16 at 3:17
  • Sorry, I wasn't particularly clear in my comment... I agree with you, that the internal pull ups are preferable (due to their higher resistance), I was just saying that a 10k external should still be enough. However, looking at the schematic, the pull up isn't disconnected when the switch is open - when the switch is open, the 10k pullup is pulling pin 4 up to 3V3. If the resistor is moved to the other side of the switch (the side closest to port B) it would no longer be a pullup. Regardless, the whole point is somewhat moot, as the real issue was that the legend was on the wrong way ;-) – Greenonline Mar 11 '16 at 4:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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