12

This code does not turn the led on and off.

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

but when I print out the number in the loop it does work:

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

Any idea why that is?

  • 1
    see enwp.org/Heisenbug – cat Jun 5 '17 at 19:53
  • 2
    @cat Bingo, "Heisenbugs occur because common attempts to debug a program, such as inserting output statements" – tazboy Jun 5 '17 at 23:54
  • 1
    "This code does not turn the led on and off." - I beg to differ. – marcelm Jun 7 '17 at 16:32
22

Try to replace your print by a time.sleep(0.05). You may occur this strange behavior as GPIO.output is switched too quickly from HIGH to LOW to be set/detected/seen. Increase/reduce the sleep duration until the program works fine (increase) and fast enough (decrease).

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()
  • Yep. That makes sense. – tazboy Jun 5 '17 at 18:31
52

Unroll your loop to understand what's happening here:

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

turns into:

    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]

As you can see, setting the pin low follows (near to) immediately after turning it high. In effect your LED will stay at one state for most of the time (that is, what we can perceive with the naked eye).

Fix it like this (for a 50:50 duty cycle):

for number in range(0,10):
    GPIO.output(21,GPIO.LOW)
    time.sleep(1)
    GPIO.output(21,GPIO.HIGH)
    time.sleep(1)
  • Wow. That seems so obvious now. Thanks for showing me. – tazboy Jun 5 '17 at 18:31
  • 4
    This should be the accepted answer. It actually explains what happened – user67191 Jun 6 '17 at 17:43
  • 2
    It may also be worth noting that the reason print() causes the original code to work is because writing to the screen is an insanely slow process and is essentially acting as the sleep(1) you suggested. – Jacobm001 Jun 8 '17 at 16:43
  • Although this answer does a better job of breaking it down I chose the other answer because it was the first written solution to my problem. The overall voting will determine the better answer. – tazboy Jun 11 '17 at 15:19
  • 1
    @tazboy no need to feel yourself being pressured into any particular choice concerning the "accepted answer" – Ghanima Jun 11 '17 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.