Pętla nie działa, chyba że użyję „print”

11

Ten kod nie włącza ani nie wyłącza diody LED.

import  RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(21,GPIO.OUT)
for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
GPIO.cleanup()

ale kiedy wydrukuję liczbę w pętli, działa:

import  RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(21,GPIO.OUT)
for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    print(number)
GPIO.cleanup()

Masz pomysł, dlaczego tak jest?

tazboy
źródło
1
patrz enwp.org/Heisenbug
cat
2
@cat Bingo, „Heisenbugs występują, ponieważ typowe próby debugowania programu, takie jak wstawianie instrukcji wyjściowych”
tazboy
1
„Ten kod nie włącza i nie wyłącza diody LED”. - Pozwolę sobie być innego zdania.
marcelm

Odpowiedzi:

22

Spróbuj zastąpić swój printprzez time.sleep(0.05). Może wystąpić takie dziwne zachowanie, ponieważ GPIO.output jest zbyt szybko przełączane z WYSOKIEGO na NISKI, aby go ustawić / wykryć / zobaczyć. Zwiększ / zmniejsz czas trwania snu, aż program będzie działał poprawnie (zwiększ) i wystarczająco szybko (zmniejsz).

import  RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(21,GPIO.OUT)
for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    time.sleep(0.05)
GPIO.cleanup()
Technico.top
źródło
Tak. To ma sens.
tazboy
51

Rozwiń pętlę, aby zrozumieć, co się tutaj dzieje:

for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)

zamienia się w:

    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    # [and so on]

Jak widać, ustawienie niskiego pinu następuje (blisko) natychmiast po jego podniesieniu. W efekcie Twoja dioda LED pozostanie w jednym stanie przez większość czasu (czyli to, co możemy zobaczyć gołym okiem).

Napraw to w następujący sposób (dla cyklu pracy 50:50):

for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    time.sleep(1)
Ghanima
źródło
Łał. To wydaje się teraz takie oczywiste. Dzięki za pokazanie mi.
tazboy
4
To powinna być zaakceptowana odpowiedź. To właściwie wyjaśnia, co się stało
2
Warto również zauważyć, że powodem, dla print()którego oryginalny kod działa, jest to, że pisanie na ekranie jest niezwykle powolnym procesem i zasadniczo działa tak, jak sleep(1)sugerowałeś.
Jacobm001
Chociaż ta odpowiedź lepiej się rozbija, wybrałem inną odpowiedź, ponieważ było to pierwsze pisemne rozwiązanie mojego problemu. Ogólne głosowanie określi lepszą odpowiedź.
tazboy
1
@tazboy nie musisz czuć się zmuszany do jakiegokolwiek konkretnego wyboru dotyczącego „zaakceptowanej odpowiedzi”
Ghanima