简体   繁体   中英

Python Don't Repeat Consecutive Lines

I am writing a python script, that will show the status of a raspberry pi's gpio input pins in a web browser. This script is just for the backend testing:

import RPi.GPIO as GPIO
import time
import os
os.system('clear')

GPIO.setmode(GPIO.BOARD)

GPIO.setup(29, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(32, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(37, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    input_state = GPIO.input(37)
    if input_state == False:
        print('One')
        time.sleep(0.2)
    input_state = GPIO.input(32)
    if input_state == False:
        print('Two')
        time.sleep(0.2)
    input_state = GPIO.input(29)
    if input_state == False:
        print('Three')
        time.sleep(.02)

My output crazily spams the screen with the number until the input switch is turned off. How can I prevent the same consecutive line from repeating immediately? Thanks!

You could modify your code to work with an 'on change' type logic:

import RPi.GPIO as GPIO
import time
import os
os.system('clear')

GPIO.setmode(GPIO.BOARD)

# allows you to rename the io ports
io_names = [ 'One', 'Two', 'Three' ]

class IOMonitor():
    def __init__( self, num , io, pud ):
        self.num = num

        GPIO.setup(self.num, io, pull_up_down=pud)
        self.last_state = GPIO.input(self.num)

    def poll( self ):
        # detect current state
        current_state = GPIO.input(self.num)
        # compare with old state
        if( current_state != self.last_state ):
            # set new last state
            self.last_state = current_state 
            # print name of io that changed
            print( io_names[self.num] )


ioMonitors = [
    IOMonitor(29, GPIO.IN, GPIO.PUD_UP),
    IOMonitor(32, GPIO.IN, GPIO.PUD_UP),
    IOMonitor(37, GPIO.IN, GPIO.PUD_UP)
    ]


def main():
    while True:
        for io in ioMonitors:
            io.poll()
            time.sleep(0.2)

main()

I don't have access to your libraries so this code is untested but should be logically correct.

How about printing only when the input states actually change? Something like this (untested):

# Your code to initialise everything:
import RPi.GPIO as GPIO
import time
import os
os.system('clear')

GPIO.setmode(GPIO.BOARD)

GPIO.setup(29, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(32, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(37, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# New loop keeping track of the previous ("old") input states:
old_input_states = [None] * 3
while True:
    input_states = [GPIO.input(n) for n in (37, 32, 29)]
    if input_states != old_input_states:
        for n, name in enumerate(['One', 'Two', 'Three']):
            if input_states[n] == False:
                print name
        old_input_states = input_states

So to explain what this new loop code is doing:

  • First, a list old_input_states is created which contains three None entries. This will be used to remember the last state of the three GPIOs.
  • Then at the beginning of the loop, the GPIO.input(n) function is called, for n being 37, 32 and 29 for the three GPIOs. The resulting list input_states now contains the three GPIO states.
  • Then this list is compared against the old_input_states list and if they differ, it will do the following:
    • For each name in 'One' , 'Two' and 'Three' (which are enumerated by n , ie for 'One' it is 0, 1 for 'Two' and 2 for 'Three' ), it checks the value of that input_states[n] to see if it is False and if it is, it prints the name which should match the corresponding GPIO.
    • Then it updates old_input_states to match input_states so in the next loop, it will only check (and potentially print) again if the input_states changed.

EDIT

Note that the code will output all GPIOs which are currently False at the point where a change is detected. To only print the ones going from True to False , you should be able to use the following code for the section starting with the # New loop comment:

# New loop keeping track of the previous ("old") input states:
old_input_states = [None] * 3
while True:
    input_states = [GPIO.input(n) for n in (37, 32, 29)]
    for n, name in enumerate(['One', 'Two', 'Three']):
        if input_states[n] != old_input_states[n] and input_states[n] == False:
            print name
    old_input_states = input_states

EDIT 2

As indicated by the OP, the preferred output is in list-form anyway. Also there appeared to be some bouncing happening on the switch inputs to the GPIOs, which could be improved by using the time.sleep calls. Further, the output should be inverted. The final code of the while loop looks like this:

old_input_states = [None] * 3
while True:
    input_states = [GPIO.input(n) for n in (37, 32, 29)]
    if input_states != old_input_states:
        inverted_input_states = [1 - i for i in input_states]
        print inverted_input_states
        time.sleep(0.2)
    old_input_states = input_states

Disclaimer: For better debouncing reliability of switches I'd use different code, but that is beyond the scope of this question

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM