Python GPIO触发带按钮的LED

时间:2015-09-24 18:08:44

标签: python button raspberry-pi gpio led

我正在尝试控制Raspberry Pi上的LED。

当我按下按钮时,我希望LED点亮,并保持该状态直到我再次按下按钮。

我已经实现了下面的代码,它运行得很好。但是,当我按下按钮或按住按钮不够快时,我遇到了问题。

import RPi.GPIO as GPIO
from time import sleep

inpin = 16
outpin = 20

GPIO.setmode(GPIO.BCM)
counter = 0
GPIO.setup(outpin, GPIO.OUT)
GPIO.setup(inpin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
        while True:

                if GPIO.input(inpin):
                        if counter == 0:
                                print "port is low"
                                GPIO.output(outpin, 0)
                                counter = 0

                        else:
                                print "port is high"
                                GPIO.output(outpin, 1)
                                counter = 1
                else:
                        if counter == 1:
                                print "port is low"
                                GPIO.output(outpin, 0)
                                counter = 0
                        else:
                                print "port is high"
                                GPIO.output(outpin, 1)
                                counter = 1
                sleep(0.1)

finally:
        GPIO.cleanup()

实施方式" TessellatingHeckler"建议作品完美。 即使有多个输入和输出,它也可以完美运行。 重要的是" elif"循环以保证快速变化的状态。 这是工作代码:

import RPi.GPIO as GPIO
from time import sleep



GPIO.setmode(GPIO.BCM)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(27, GPIO.OUT)


btn1_button = 'up'
btn1_light = 'off'

btn2_button = 'up'
btn2_button = 'off'



def LED1(output):
    GPIO.output(20, output)

def LED2(output):
    GPIO.output(27, output)

while True:


######################## BUTTON 1 ########################
    if (btn1_button == 'up' and btn1_light == 'off'):
            if not  GPIO.input(16):
            print "LED1 ON"
            LED1(1)         
            btn1_button = 'down'
            btn1_light = 'on'


    elif (btn1_button == 'down' and btn1_light == 'on'):
            if GPIO.input(16):
            btn1_button = 'up'


    elif (btn1_button == 'up' and btn1_light == 'on'):
            if not GPIO.input(16):
            print "LED1 OFF"
            LED1(0)
            btn1_button = 'down'
            btn1_light = 'off'


    elif (btn1_button == 'down' and btn1_light == 'off'):
            if GPIO.input(16):
            btn1_button = 'up'

###########################################################

####################### BUTTON 2 ##########################
    if (btn2_button == 'up' and btn2_light == 'off'):
                if not  GPIO.input(17):
                        print "LED2 ON"
                        LED2(1)
                        btn2_button = 'down'
                        btn2_light = 'on'

    elif (btn2_button == 'down' and btn2_light == 'on'):
                if GPIO.input(17):
                        btn2_button = 'up'


    elif (btn2_button == 'up' and btn2_light == 'on'):
                if not GPIO.input(17):
                        print "LED2 OFF"
                        LED2(0)
                        btn2_button = 'down'
                        btn2_light = 'off'


    elif (btn2_button == 'down' and btn2_light == 'off'):
                if GPIO.input(17):
                        btn2_button = 'up'
    sleep(0.1)
###########################################################

GPIO.cleanup()

2 个答案:

答案 0 :(得分:3)

你用文字写了这个计划:

  • 按下按钮,指示灯亮起
  • 按下按钮,指示灯熄灭

但你在代码中写的更像是:

  • 每秒10x,
    • 如果按钮已启动,则不执行任何操作
    • 如果按下按钮,则切换灯光

这是完全不同的。按住按钮超过1/10秒,它开始变得怪异。我的评论意味着你的代码遍历循环并且每次尝试更新所有内容时;您正在跟踪最后一次循环发生的事情,这意味着您无法保留任何超过一个循环持续时间的内容。相反,你需要将循环与状态跟踪分开,这样状态可以一遍又一遍地保持不变,只让狗在按钮改变时吃饼干。

它是驱动系统状态的按钮,而不是时间的流逝。系统可以处于4种可能的状态,如下所示:

(Button=Up, Light=Off) <----------------
        |                               |
        | Button pushed down            |
        \/                              |
(Button=Down, Light=/On/)               |
        |                               |
        | Button released               |
        \/                              |
(Button=Up, Light=On)                   |
        |                               |
        | Button pushed down            |
        \/                              |
(Button=Down, Light=/Off/)              |
        |                              / \
        | Button released               |
        |                               |
         -------------------------------

如果您明确地对这些状态进行编码并按照顺序进行操作,那么让按钮成为唯一允许您从一个按钮到另一个按钮的按钮......按住按钮太长时间,您可能无法获得任何奇怪的行为。我希望。您当前的代码从(Button = Down,Light = On)跳转到(Button = Down,Light = Off)并再次返回。

我的代码未经测试,我不完全确定按下和释放按钮时GPIO.input()的走向。我认为大部分时间都是0 / False,按下按钮时为1 / True。

import RPi.GPIO as GPIO
from time import sleep

inpin = 16
outpin = 20

GPIO.setmode(GPIO.BCM)
GPIO.setup(outpin, GPIO.OUT)
GPIO.setup(inpin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

button='up'
light='off'

while True:

    if (button=='up'   and   light=='off'):
        # wait for button press before changing anything
        if not GPIO.input(inpin):
            GPIO.output(outpin, 1)
            button='down'; 
            light='on'

    elif (button=='down' and   light=='on'):
        # stay in this state until button released
        if GPIO.input(inpin):
            button='up'

    elif (button=='up'   and   light=='on'):
        if not GPIO.input(inpin):
            GPIO.output(outpin, 0)
            button='down'
            light='off'

    elif (button=='down' and   light=='off'):
        if GPIO.input(inpin):
            button='up'
    sleep(0.1)

因此,buttonlight会跟踪系统的状态。每次循环时,只有if块中的一个匹配,并且在获得按钮更改之前它几乎不会执行任何操作,从而使状态更改为下一个。

第一次通过,第一个块匹配,它检查按下按钮。它一直这样做。

按下按钮,现在第一个模块点亮LED并更新状态。

现在,每次循环,(button=='down' and light=='on')都匹配。它处于状态2,并且只要按下按钮就会保持该状态。每次循环都会查找按钮释放,这是唯一可以触发任何状态更改的东西。

答案 1 :(得分:0)

请尝试以下操作,这可以消除启动时的“启动指示灯”问题:

import RPi.GPIO as GPIO
from time import sleep

inpin = 11
outpin = 7

GPIO.setmode(GPIO.BOARD)
GPIO.setup(outpin, GPIO.OUT)
GPIO.setup(inpin, GPIO.IN)

x=0
y=0

try:

   while True:

     if (x==0   and   y==0):
           # wait for button press before changing anything
          if GPIO.input(inpin) == 0:
                 GPIO.output(outpin, 0)
                 x=0 
                 y=1
                 print("led off")

     elif (x==0  and   y==1):
           # stay in this state until button released
          if GPIO.input(inpin) == 1:
             x = 1

     elif (x==1   and   y==1):
          if GPIO.input(inpin) == 0:
                 GPIO.output(outpin, 1)
                 x=1
                 y=0
                 print("led on")

     elif (x==1 and   y==0):
          if GPIO.input(inpin) == 1:
             x=0
     sleep(0.1)


except KeyboardInterrupt:
          GPIO.output(outpin, 0)
          GPIO.cleanup()