Цикл не працює, якщо я не використовую "print"


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

Будь-яка ідея, чому це так?


1
дивіться enwp.org/Heisenbug
кіт

2
@cat Bingo, "Heisenbugs трапляються через поширені спроби налагодження програми, наприклад, вставлення вихідних операторів"
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()

Так. Що має сенс.
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 не потрібно відчувати себе тиском на якийсь конкретний вибір щодо "прийнятої відповіді"
Ghanima
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.