Python не повторяет последовательные строки

Я пишу скрипт на Python, который будет показывать статус входных контактов gpio Raspberry Pi в веб-браузере. Этот скрипт предназначен только для внутреннего тестирования:

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)

Мой вывод безумно спамит экран номером, пока не выключится входной переключатель. Как я могу предотвратить немедленное повторение одной и той же последовательной строки? Спасибо!


person Skyler Spaeth    schedule 10.09.2015    source источник


Ответы (2)


Как насчет печати только тогда, когда состояния ввода действительно меняются? Что-то вроде этого (не проверено):

# 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

Итак, чтобы объяснить, что делает этот новый код цикла:

  • Сначала создается список old_input_states, содержащий три записи None. Это будет использоваться для запоминания последнего состояния трех GPIO.
  • Затем в начале цикла вызывается функция GPIO.input(n), где n равно 37, 32 и 29 для трех GPIO. Результирующий список input_states теперь содержит три состояния GPIO.
  • 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, i.e. 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.
    • Затем он обновляет old_input_states, чтобы он соответствовал input_states, поэтому в следующем цикле он будет проверять (и, возможно, печатать) снова, только если input_states изменился.

ИЗМЕНИТЬ

Обратите внимание, что код выведет все GPIO, которые в настоящее время имеют значение False в точке обнаружения изменения. Чтобы напечатать только те, которые идут от True до False, вы должны иметь возможность использовать следующий код для раздела, начинающегося с комментария # New loop:

# 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

ИЗМЕНИТЬ 2

Как указано в ОП, предпочтительный вывод в любом случае находится в форме списка. Кроме того, на входах переключателя к GPIO происходили некоторые дребезги, которые можно было бы улучшить с помощью вызовов time.sleep. Далее выход следует инвертировать. Окончательный код цикла while выглядит так:

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

Отказ от ответственности: для повышения надежности устранения дребезга коммутаторов я бы использовал другой код, но это выходит за рамки данного вопроса

person FriendFX    schedule 10.09.2015
comment
Как/где мне это реализовать? Я довольно новичок в питоне. - person Skyler Spaeth; 10.09.2015
comment
@SkylerSpaeth извините за неясность, это должно заменить ваш цикл while True. Я обновлю свой ответ. - person FriendFX; 10.09.2015
comment
Итак, когда я включаю 2 или 3 (не один) и выключаю его в течение примерно 3 секунд, он показывает Two, когда я его также выключаю. - person Skyler Spaeth; 10.09.2015
comment
@SkylerSpaeth код будет при каждом изменении печатать все состояния GPIO, которые в настоящее время равны False. Если это не то, что вам нужно, и вы видите только измененный GPIO, вам нужна слегка модифицированная версия. Я попытался добавить объяснение того, как должен работать код. Чтобы помочь вам лучше понять это, вы также можете добавить строку print input_states чуть выше строки for n, name. - person FriendFX; 10.09.2015
comment
Давайте продолжим это обсуждение в чате. - person Skyler Spaeth; 10.09.2015

Вы можете изменить свой код для работы с логикой типа «при изменении»:

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()

У меня нет доступа к вашим библиотекам, поэтому этот код не проверен, но должен быть логически правильным.

person Serdalis    schedule 10.09.2015
comment
Я получаю синтаксическую ошибку в строке, содержащей IOMonitor(32,…), но не в остальных. Любые идеи? - person Skyler Spaeth; 10.09.2015
comment
Извините, забыл поставить запятые! Ну вот. - person Serdalis; 10.09.2015
comment
Итак, теперь, когда я его запускаю, он просто работает без вывода в течение 1 секунды, а затем возвращается в окно терминала. - person Skyler Spaeth; 10.09.2015
comment
@SkylerSpaeth ммм, возможно, вы не используете это в основном модуле. Я удалю оператор if, что позволит ему работать. - person Serdalis; 10.09.2015