Цикл не работает, если я не использую «печать»

11

Этот код не включает и не выключает светодиод.

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

но когда я печатаю число в цикле, оно работает:

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

Есть идеи, почему это так?

tazboy
источник
1
см. enwp.org/Heisenbug
кот
2
@cat Bingo, «Гейзенбагс возникает из-за частых попыток отладки программы, таких как вставка выходных операторов»
tazboy
1
«Этот код не включает и не выключает светодиод». - Позволю себе не согласиться.
marcelm

Ответы:

22

Попробуйте заменить ваш printна time.sleep(0.05). Такое странное поведение может возникнуть, когда GPIO.output слишком быстро переключается с ВЫСОКОГО на НИЗКОЕ, чтобы быть установленным / обнаруженным / видимым. Увеличивайте / уменьшайте продолжительность сна, пока программа не будет работать нормально (увеличение) и достаточно быстро (уменьшение).

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
источник
Ага. В этом есть смысл.
tazboy
51

Разверните ваш цикл, чтобы понять, что здесь происходит:

for number in range(0,10):
    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)
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    # [and so on]

Как вы можете видеть, установка штифта на низкий уровень следует (почти) сразу после его поворота на высокий уровень. Фактически ваш светодиод будет оставаться в одном состоянии большую часть времени (то есть то, что мы можем воспринимать невооруженным глазом).

Исправьте это так (для рабочего цикла 50:50):

for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    time.sleep(1)
Ганима
источник
Вау. Это кажется таким очевидным сейчас. Спасибо, что показали мне.
tazboy
4
Это должен быть принятый ответ. Это на самом деле объясняет, что произошло
2
Также стоит отметить, что причина, print()по которой исходный код работает, заключается в том, что запись на экран является безумно медленным процессом и, по сути, действует так, как sleep(1)вы предлагали.
Jacobm001
Хотя этот ответ лучше разобрать, я выбрал другой, потому что это было первое письменное решение моей проблемы. Общее голосование определит лучший ответ.
tazboy
1
@tazboy, нет необходимости чувствовать, что тебя заставляют делать какой-то конкретный выбор относительно «принятого ответа»
Ганима