loes7815
Posts: 38
Joined: Thu Jan 28, 2016 3:15 pm

push buttons interrupts

Fri Apr 29, 2016 1:03 pm

Hi!

My previous problem is solved, but I got another issue.
I would like to use pushbuttons to write a number in a file, like button 1 is 1, button 2 is 2 etc.
I've used interrupts to do this, and it works.
However, python is now printing like 1000 times the same value with the same time stamp in the csv file every 60 seconds.
How can I fix it?

The code:

Code: Select all

import RPi.GPIO as GPIO  
from time import gmtime, strftime
import csv, os, glob, time, datetime, numpy
GPIO.setmode(GPIO.BCM)  
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)  
button = []
button_mean = 0
def my_callback(channel):  
    button.insert(0,1)
    print "button is 1"  
    print button
  
def my_callback2(channel):  
    button.insert(0,2)
    print "button is 2"  
    print button

  
GPIO.add_event_detect(17, GPIO.FALLING, callback=my_callback, bouncetime=300)  
  
GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2, bouncetime=300)  
  
try:  
   print "Press button 3 to quit "  
   while True:
      elapsed = (int(time.time())%60)
      if elapsed == 59:
         if len(button) > 0 :
            button_mean = numpy.mean(button)
            with open("button.csv", "a") as csvfile:
               out = csv.writer(csvfile, delimiter=",",
                     quotechar='|',quoting=csv.QUOTE_MINIMAL)
               date = datetime.datetime.now()
               out.writerow([date.strftime("%Y"),date.strftime("%m"),date.strftime("%d"),date.strftime("%H"),date.strftime("%M"),date.strftime("%S"), button_mean])
            print button
            button = []
         else:
            with open("button.csv", "a") as csvfile:
               out = csv.writer(csvfile, delimiter=",",
                     quotechar='|',quoting=csv.QUOTE_MINIMAL)
               date = datetime.datetime.now()
               out.writerow([date.strftime("%Y"),date.strftime("%m"),date.strftime("%d"),date.strftime("%H"),date.strftime("%M"),date.strftime("%S"), button_mean])
            print button
            button = []
   GPIO.wait_for_edge(24, GPIO.RISING)  
   print "Finished" 

except KeyboardInterrupt:  
   GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
GPIO.cleanup()           # clean up GPIO on normal exit

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: push buttons interrupts

Fri Apr 29, 2016 1:10 pm

Attaching a push-button to an interrupt is not a good idea; because of contact bounce it can trigger hundreds (or thousands) of interrupt signals... also, the interrupt mechanism needs to know rising edge or falling edge and it can't keep that straight with contact bounce. You can use bounce conditioning to reduce the problem; but, its still going to be there because the interrupt mechanism is so sensitive. You need to use a latch (or maybe the LM3900) to provide the interrupt signal from the push-button (or whatever).
marcus
:ugeek:

loes7815
Posts: 38
Joined: Thu Jan 28, 2016 3:15 pm

Re: push buttons interrupts

Fri Apr 29, 2016 1:18 pm

MarkHaysHarris777 wrote:Attaching a push-button to an interrupt is not a good idea; because of contact bounce it can trigger hundreds (or thousands) of interrupt signals... also, the interrupt mechanism needs to know rising edge or falling edge and it can't keep that straight with contact bounce. You can use bounce conditioning to reduce the problem; but, its still going to be there because the interrupt mechanism is so sensitive. You need to use a latch (or maybe the LM3900) to provide the interrupt signal from the push-button (or whatever).
I thought I solved this with the code:

Code: Select all

GPIO.add_event_detect(17, GPIO.FALLING, callback=my_callback, bouncetime=300)  
  
GPIO.add_event_detect(23, GPIO.FALLING, callback=my_callback2, bouncetime=300)  
What would you suggest to use instead of interrupts?

DirkS
Posts: 9838
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: push buttons interrupts

Fri Apr 29, 2016 1:38 pm

MarkHaysHarris777 wrote:Attaching a push-button to an interrupt is not a good idea; because of contact bounce it can trigger hundreds (or thousands) of interrupt signals... also, the interrupt mechanism needs to know rising edge or falling edge and it can't keep that straight with contact bounce. You can use bounce conditioning to reduce the problem; but, its still going to be there because the interrupt mechanism is so sensitive. You need to use a latch (or maybe the LM3900) to provide the interrupt signal from the push-button (or whatever).
Did you actually have a look at the code or did you just react to the words 'button' and 'interrupt'?

DirkS
Posts: 9838
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: push buttons interrupts

Fri Apr 29, 2016 1:42 pm

loes7815 wrote:However, python is now printing like 1000 times the same value with the same time stamp in the csv file every 60 seconds.
Do you also get repeated print messages from the callback function (like 'button is 1')?

loes7815
Posts: 38
Joined: Thu Jan 28, 2016 3:15 pm

Re: push buttons interrupts

Fri Apr 29, 2016 1:56 pm

DirkS wrote:
loes7815 wrote:However, python is now printing like 1000 times the same value with the same time stamp in the csv file every 60 seconds.
Do you also get repeated print messages from the callback function (like 'button is 1')?
When I push a button I get:

Code: Select all

button is 1
[1]
Button is 2
[2,1]
etc.
So it seems to go right.

But after 60 seconds I get:

Code: Select all

[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
I think the code is writing something to the file every second?
This is (a part of) what I get in my csv file:

Code: Select all

2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,52,59,1.6666666666666667
2016,04,29,15,52,59,1.5
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667
2016,04,29,15,53,09,1.6666666666666667

DirkS
Posts: 9838
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: push buttons interrupts

Fri Apr 29, 2016 3:03 pm

So debouncing doesn't seem to be the problem.

I think I found the culprit though:

Code: Select all

      elapsed = (int(time.time())%60)
      if elapsed == 59:
If the rest of the loop takes less than a second then the if statement is true more than once.
Since you clear 'button' the first time in 'if len(button) > 0' it will go into the 'else' part and still output to the csv.
This code is a simplified version of your script, it should clarify what's actually happening:

Code: Select all

from time import gmtime, strftime, sleep
import time, datetime
button=[1]

try:
   print "Press button 3 to quit "
   while True:
      elapsed = (int(time.time())%60)
      print elapsed
      if elapsed == 59:
        if len(button) > 0:
            print 'button > 0'
            button = []
        else:
            print 'button = 0'
      sleep(0.1)
except:
You need to change the way how you keep track of elapsed time.
Something like this should work:

Code: Select all

from time import gmtime, strftime, sleep
import time, datetime
button=[1]

starttime = time.time()
try:
   print "Press button 3 to quit "
   while True:
      currenttime = time.time()
      elapsed = currenttime - starttime
      # print elapsed
      if elapsed >= 60:
        starttime = currenttime   # reset start time
        if len(button) > 0:
            print 'button > 0'
            button = []
        else:
            print 'button = 0'
      sleep(0.1)
except:
    pass

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: push buttons interrupts

Fri Apr 29, 2016 3:10 pm

MarkHaysHarris777 wrote:Attaching a push-button to an interrupt is not a good idea;
this is a clearly duplicated topic (and i'll report this to mods), but this answer is wonderful :lol:

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: push buttons interrupts

Fri Apr 29, 2016 10:10 pm

DirkS wrote:
MarkHaysHarris777 wrote:Attaching a push-button to an interrupt is not a good idea; because of contact bounce ...
Did you actually have a look at the code or did you just react to the words 'button' and 'interrupt'?
Well, both actually; if you must know. I have been involved (personally, and in association) with this issue (attaching a push button to an interrupt) more times than I want to count. I stand by my assertion that its a bad idea just out of principle. I always try to educate if I can, regardless of an immediate issue, if relevant and if I think it can help someone understand the underlying principles. The very best way to build an interrupt driven keyboard (push buttons) is to have the keyboard (all of the buttons) drive a latch in combination with a device similar to the LM3900 to provide the interrupt. The interrupt handler then polls the keyboard and resets the latch(s). I have built several of these; and I have built several other kinds of interrupt driven systems (I'm an expert and I have some actual experience that can be helpful). I try.

:geek:
marcus
:ugeek:

Emma_Jir
Posts: 19
Joined: Wed Nov 29, 2017 11:13 am

Re: push buttons interrupts

Thu Dec 21, 2017 6:34 pm

MarkHaysHarris777 wrote:
Fri Apr 29, 2016 1:10 pm
Attaching a push-button to an interrupt is not a good idea; because of contact bounce it can trigger hundreds (or thousands) of interrupt signals... also, the interrupt mechanism needs to know rising edge or falling edge and it can't keep that straight with contact bounce. You can use bounce conditioning to reduce the problem; but, its still going to be there because the interrupt mechanism is so sensitive. You need to use a latch (or maybe the LM3900) to provide the interrupt signal from the push-button (or whatever).
Sorry for OT: Does this apply to every model, e.g. small 4-pole clickbuttons too?

Return to “Troubleshooting”