adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.11k stars 1.22k forks source link

Flickering when adjusting board.DISPLAY.brightness #1796

Closed dhalbert closed 5 years ago

dhalbert commented 5 years ago

This test program should smoothly increase the brightness, but there's prounounced flickering as the brightness increases. Flickering is visible both on PyPortal and Hallowing:

import time
import board
import displayio

while True:
    # Fade up the backlight
    for b in range(101):
        board.DISPLAY.brightness = b / 100
        time.sleep(0.1)
makermelissa commented 5 years ago

This is related to pulseio PWMOut on the backlight pin. From what I can tell, this pin is a TCC type and looking at pulseio in the common_hal, it appears to be disabling double buffering before setting the duty cycle and then reenabling it. I'm not sure if there's a problem in there, but it gets even more interesting if you change the time.sleep to 1. You can observe that right after the brightness is set, there's kind of a ramp-up that takes like a half second and I think this ramp-up is creating the flickering effect. I'm not that familiar with the intricacies of the tcc pins and pwm. Perhaps this is something @tannewt would have a better idea about.

dhalbert commented 5 years ago

It turns out this is Display.auto_brightness fighting with manual .brightness setting. The PWM stuff is fine. .auto_brightness was changing the brightness out from under the manual setting. There is some bug: the brightness should not be adjustable if .auto_brightness is True.

makermelissa commented 5 years ago

Or possibly set .auto_brightness to false if brightness is set manually.

dhalbert commented 5 years ago

@makermelissa That sounds like a good idea: we'll discuss.

tannewt commented 5 years ago

Ah! That makes sense. Good find @dhalbert

dhalbert commented 5 years ago

@tannewt the pyportal, pybadge, and the hallowing all start with auto_brightness True. The doc in Display.c says

The brightness of the display as a float. 0.0 is off and 1.0 is full brightness. When auto_brightness is True this value will change automatically and setting it will have no effect. To control the brightness, auto_brightness must be false.

The above isn't actually true: there's no check for .auto_brightness when setting .brightness. I like @makermelissa 's suggestion.

Should all these boards all be .auto_brightness True on Display creation? I thought only the pyportal had a sensor for this, but maybe that wasn't the idea. What was the intention of auto_brightness?

auto_brightness is also set in reset_displays().

tannewt commented 5 years ago

Oops. :-)

Ya, they should be auto_brightness = True by default so that you can see what is on the display. Maybe it's worth having it as (yet another) kwarg to Display so it doesn't flash on init. The light sensor isn't actually used yet. (All three do have one.)

auto_brightness is meant to hand off brightness between user code and the VM. We can't use just brightness because we may want to read back the auto value before transitioning to manual control.

dhalbert commented 5 years ago

:smile: OK, I'll make a PR in the morning to reconcile all this, and update the doc.