简体   繁体   English

使用GPIO和Python在Raspberry Pi上进行LED控制

[英]LED control on Raspberry Pi by GPIO with Python

I am using momentary switches wired to GPIO pins on a Raspberry Pi to control 4 LEDs. 我正在使用连接到Raspberry Pi上GPIO引脚的瞬时开关来控制4个LED。 I have five buttons wired up. 我连接了五个按钮。 The first 4 buttons when pressed toggle the state of a connected LED from on to off or off to on depending on the current state. 按下前四个按钮时,根据当前状态,将连接的LED的状态从打开切换为关闭或从关闭切换为打开。 The fifth button turns on all 4 LEDs or turns off all 4 LEDs based on the on/off state of GPIO 18. I also have an extra LED wired to GPIO pin 18, this simply turns on or off based on the state of pin 18. The idea of this project is to be able to independently control the LEDs and have a master control button as well. 第五个按钮根据GPIO 18的打开/关闭状态来打开所有4个LED或关闭所有4个LED。我还有一个额外的LED线连接到GPIO引脚18,这只是根据引脚18的状态打开或关闭。该项目的想法是能够独立控制LED并具有一个主控制按钮。 The LED attached to pin 18 is a monitoring LED, it should be on if ANY of the 4 LEDs is on and it should only be off if all 4 of the LEDs are off simultaneously. 连接到引脚18的LED是监视LED,如果4个LED中的任何一个都点亮,则该LED应当点亮;并且,如果同时关闭所有4个LED,则该LED应当熄灭。 This is all based on python scripts that monitor for button presses and act accordingly. 这些都是基于python脚本来监控按钮按下情况并采取相应措施的。

The code I've written to control all LEDs at once looks like this: 我编写的用于立即控制所有LED的代码如下所示:

import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False)

GPIO.setmode(GPIO.BCM)

GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

chan_list = (4,17,22,27)

GPIO.setup(chan_list,GPIO.OUT)

GPIO.output(chan_list,0)

GPIO.setup(18,GPIO.OUT)

GPIO.output(18,0)

while True:
    input_state = GPIO.input(26)
    if input_state == False:
         chan_list = (4,17,22,27)
         GPIO.output(18, not GPIO.input(18))
         time.sleep(0.1)
         GPIO.output(chan_list, GPIO.input(18))
         time.sleep(0.4)

This code appears to operate perfectly. 该代码似乎运行正常。 As you can see it toggles the current state of pin 18 and then applies that state to pins 4,17,22 and 27 which are the pins the LEDs are connected to. 如您所见,它会切换引脚18的当前状态,然后将该状态应用于与LED相连的引脚4,17,22和27。

The code I've written to control the individual LEDs is a bit more complicated and it looks like this: 我编写的用于控制各个LED的代码有点复杂,看起来像这样:

import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False)

GPIO.setmode(GPIO.BCM)

GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(4,GPIO.OUT)
GPIO.output(4,0)

GPIO.setup(17,GPIO.OUT)

GPIO.setup(22,GPIO.OUT)

GPIO.setup(27,GPIO.OUT)

GPIO.setup(18,GPIO.OUT)

while True:
    input_state = GPIO.input(5)
    if input_state == False:
        if GPIO.output(17,0) == False:
            GPIO.output(4, not GPIO.input(4))
        elif GPIO.output(22,0) == False:
            GPIO.output(4, not GPIO.input(4))
        elif GPIO.output(27,0) == False:
            GPIO.output(4, not GPIO.input(4))
        else:
            GPIO.output(4, not GPIO.input(4))
            time.sleep(0.1)
            GPIO.output(18, GPIO.input(4))
            time.sleep(0.4)

There are 4 versions of this with the pins adjusted, one version for each LED, This version uses pin 5 as an input to detect button presses and pin 4 as an output to activate the LED. 共有4个版本,其中的引脚已调整,每个LED都有一个版本。此版本使用引脚5作为输入来检测按钮按下情况,并使用引脚4作为输出来激活LED。 What I want is to do is this: 我想做的是这样的:

When pressed (if LED1 is off) 按下时(如果LED1熄灭)

- Toggle LED1 on, also toggle pin 18 on to activate the indicator light.
- Take no further action.

When pressed (if LED1 is on) 按下时(如果LED1点亮)

- Check if pin 17 is on or off; 
    - If pin 17 is on toggle LED1 off and take no further action. 
    - If pin 17 is off check if pin 22 is on or off; 
        - If pin 22 is on toggle LED1 off and take no further action. 
        - If pin 22 is off check if pin 27 is on or off; 
            - If pin 27 is on toggle LED1 off and take no further action. 
            - If pin 27 is off toggle LED1 off then set pin 18 to the current status of pin 4 (LED1).

However, what is actually happening is this: 但是,实际上是这样的:

When pressed (if LED1 is off) 按下时(如果LED1熄灭)

- Turns off all of the other 3 LEDs then toggles LED1 on and toggles pin 18 on.

When pressed (if LED1 is off) 按下时(如果LED1熄灭)

- Turns off all LEDs and toggles pin 18 off.

I can not for the life of me figure this out. 我无法为我的一生解决这个问题。 Your help is hugely appreciated. 非常感谢您的帮助。

PS Pardon my ignorance, I started learning python yesterday and have no prior programming experience at all. PS对不起,我的无知,我昨天开始学习python,并且完全没有编程经验。 I'm sure it's something simple but I can't seem to solve it. 我敢肯定这很简单,但似乎无法解决。

Sounds like you have 3 logical blocks: 听起来您有3个逻辑块:

  1. Individual LED control 独立LED控制
  2. Master LED control 主LED控制
  3. Monitor-LED indicator control Monitor-LED指示灯控制

Decouple your code into functions, let's name them checkIndividualButton , checkMasterButton and updateMonitorLed , one for each logical block, and call them from your main loop 将您的代码解耦为函数,我们将其命名为checkIndividualButtoncheckMasterButtonupdateMonitorLed ,每个逻辑块一个,然后从主循环调用它们

import RPi.GPIO as GPIO
import time

# our 3 functions will go here, yet to be written

# setup pins here
all_leds = [???,???,???,???]

GPIO.setup blah blah blah

while True:
    checkIndividualButton(button_pin=17, led_pin=4)  # assuming button wired to pin 17 controls LED on pin 4
    checkIndividualButton(????, ????) # fill this in
    checkIndividualButton(????, ????) # fill this in
    checkIndividualButton(????, ????) # fill this in

    checkMasterButton(master_button_pin=26, monitor_led_pin=18, all_leds) # notice reference to all_leds which we setup above

    updateMonitorLed(all_leds, monitor_led_pin=18)

Now all you have to do is implement individual functions, each doing Just One Job(TM): 现在,您要做的就是实现各个功能,每个功能都只执行一个Job(TM):

def checkIndividualButton(button_pin, led_pin):
    is_pressed = GPIO.input(button_pin)
    if is_pressed:
        GPIO.output(led_pin, not GPIO.input(led_pin))

def checkMasterButton(master_button_pin, monitor_led_pin, all_led_pins):
    is_pressed = GPIO.input(master_button_pin)
    if is_pressed:
        GPIO.output(monitor_led_pin, not GPIO.input(monitor_led_pin))
        time.sleep(0.1)
        GPIO.output(all_led_pins, GPIO.input(monitor_led_pin))
        time.sleep(0.4)

def updateMonitorLed(all_leds_pins, monitor_led_pin):
    is_any_led_on = False
    for led_pin in all_leds_pins:
        if GPIO.input(led_pin):
            is_any_led_on = True
    GPIO.output(monitor_led_pin, is_any_led_on)
    time.sleep(0.1)

Paste this block of functions into the right place in your main program. 将此功能块粘贴到主程序中的正确位置。

DISCLAIMER: I have not tested this. 免责声明:我尚未对此进行测试。 There are ways to optimize and cleanup the code further, happy to guide you in comments if you'd like. 有多种方法可以进一步优化和清理代码,如果愿意,可以在注释中为您提供指导。

Thank you @pbkhrv for an incredibly helpful answer. 谢谢@pbkhrv提供了非常有用的答案。 I learned a lot from it and managed to get a piece of code that works perfectly for my needs. 我从中学到了很多,并且设法获得了一段完全适合我需要的代码。

In the end I have 2 python scripts running, one which changes the pin status on the press of a button: 最后,我运行了2个python脚本,其中一个可以通过按一个按钮来更改引脚状态:

import RPi.GPIO as GPIO
import webiopi
import time

GPIO.setwarnings(False)

GPIO.setmode(GPIO.BCM)

chan_list = (4,17,22,27)

GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(4,GPIO.OUT)
GPIO.output(4,0)

GPIO.setup(17,GPIO.OUT)
GPIO.output(17,0)

GPIO.setup(22,GPIO.OUT)
GPIO.output(22,0)

GPIO.setup(27,GPIO.OUT)
GPIO.output(27,0)

GPIO.setup(18,GPIO.OUT)
GPIO.output(18,0)

while True:
#This portion is pin 4 control from physical switches
    if GPIO.input(5) == False:
        GPIO.output(4, not GPIO.input(4))
        time.sleep(0.3)

#This portion is pin 17 control from physical switches
    if GPIO.input(6) == False:
        GPIO.output(17, not GPIO.input(17))
        time.sleep(0.3)

#This portion is pin 22 control from physical switches
    if GPIO.input(19) == False:
        GPIO.output(22, not GPIO.input(22))
        time.sleep(0.3)

#This portion is pin 27 control from physical switches
    if GPIO.input(13) == False:
        GPIO.output(27, not GPIO.input(27))
        time.sleep(0.3)

#This portion is pins 4,17,22,27 as one control from physical switches. Toggles all on/off
# based on the current state of pin 18.
    if GPIO.input(26) == False:
        chan_list = (4,17,22,27)
        GPIO.output(18, not GPIO.input(18))
       # time.sleep(0.01)
        GPIO.output(chan_list, GPIO.input(18))
        time.sleep(0.3)

and this which looks after the indicator LED: 这将照亮指示灯LED:

import webiopi
import time

GPIO = webiopi.GPIO

GPIO.setup(4,GPIO.OUT)
GPIO.output(4,0)

GPIO.setup(17,GPIO.OUT)
GPIO.output(17,0)

GPIO.setup(22,GPIO.OUT)
GPIO.output(22,0)

GPIO.setup(27,GPIO.OUT)
GPIO.output(27,0)

GPIO.setup(18,GPIO.OUT)
GPIO.output(18,0)

# loop function is repeatedly called by WebIOPi 
while True:
#Block to control pin 18 state by pin 4 state
    if (GPIO.digitalRead(4) == GPIO.HIGH):
        #webiopi.sleep(0.1)
        GPIO.digitalWrite(18, GPIO.HIGH)

    if (GPIO.digitalRead(4) == GPIO.LOW):
        webiopi.sleep(0.01)
        if (GPIO.digitalRead(17) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(22) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(27) == GPIO.HIGH):
            webiopi.sleep(0.01)
        else: 
            GPIO.digitalWrite(18, GPIO.LOW)
            webiopi.sleep(0.01)

#Block to control pin 18 state by pin 17 state
    if (GPIO.digitalRead(17) == GPIO.HIGH):
        #webiopi.sleep(0.1)
        GPIO.digitalWrite(18, GPIO.HIGH)

    if (GPIO.digitalRead(17) == GPIO.LOW):
        webiopi.sleep(0.01)
        if (GPIO.digitalRead(4) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(22) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(27) == GPIO.HIGH):
            webiopi.sleep(0.01)
        else:
            GPIO.digitalWrite(18, GPIO.LOW)
            webiopi.sleep(0.01)

#Block to control pin 18 state by pin 22 state
    if (GPIO.digitalRead(22) == GPIO.HIGH):
        #webiopi.sleep(0.1)
        GPIO.digitalWrite(18, GPIO.HIGH)

    if (GPIO.digitalRead(22) == GPIO.LOW):
        webiopi.sleep(0.01)
        if (GPIO.digitalRead(4) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(17) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(27) == GPIO.HIGH):
            webiopi.sleep(0.01)
        else:
            GPIO.digitalWrite(18, GPIO.LOW)
            webiopi.sleep(0.01)

#Block to control pin 18 state by pin 27 state
    if (GPIO.digitalRead(27) == GPIO.HIGH):
        #webiopi.sleep(0.1)
        GPIO.digitalWrite(18, GPIO.HIGH)

    if (GPIO.digitalRead(27) == GPIO.LOW):
        webiopi.sleep(0.01)
        if (GPIO.digitalRead(4) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(17) == GPIO.HIGH):
            webiopi.sleep(0.01)
        elif (GPIO.digitalRead(22) == GPIO.HIGH):
            webiopi.sleep(0.01)
        else:
            GPIO.digitalWrite(18, GPIO.LOW)
            webiopi.sleep(0.01)

These two python scripts launch at the boot of the raspberry pi as well as webiopi which gives me a web UI that can control the LEDs as well. 这两个python脚本在raspberry pi和webiopi的启动时启动,这给了我一个可以控制LED的Web UI。

These 3 things together give me exactly what I was after and a web interface that live updates the button for each LED based on it's current HIGH or LOW status. 这三件事共同给了我确切的信息,并且一个网络界面根据其当前的HIGH或LOW状态实时更新每个LED的按钮。

This has been a proof of concept, THE LEDs will shortly be replaced by relays which will turn on or off connected sets of speakers in different rooms of my house, Raspberry Pi multiroom audio controller. 这已经证明了这一点,这些LED不久将被继电器取代,这些继电器将打开或关闭我家不同房间(Raspberry Pi多房间音频控制器)中已连接的扬声器组。 The raspberry pi will also be the source of the audio to the connected zones with airplay and bluetooth streaming. 覆盆子pi还将通过airplay和蓝牙流传输成为连接区域的音频源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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