Skip to content

display brightness pwm 500hz frequency #6416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 6, 2022

Conversation

FoamyGuy
Copy link
Collaborator

decreasing the frequency of the PWM that drives the display brightness.

Resolves: #6236

I tested successfully on PyPortal Tiano, PyPortal (Standard), and Feather ESP32-S2 TFT.

With this change brightness of all levels 0.1 - 1.0 seems to work well on all 3 of those devices. (values below 0.4 don't work on the Titano under current main).

There is a small amount of extra noise generated by this change that is audible coming from the speaker while it's enabled. But it's quite faint. Even with an external speaker connected to the pyportals I had to move it very close to my ear to hear the new sound caused by this chage. It's there and detectable if you're listening for it. But I think unlikely that many people would notice if they are explicitly trying to listen for it. And I do think the ability to use the rest of the brightness range on the Titano (and any other device with the same PWM controller for brightness) is worth the trade off personally.

@CedarGroveStudios
Copy link

CedarGroveStudios commented May 21, 2022

I'll test the boards with integral audio: PyPortals, PyGamer, PyBadge, Clue, FunHouse.

So far I confirmed by ear and with the o'scope that the lower-frequency 500Hz PWM signal bleeds through on the Titano, but it's not significant in my opinion. The spectrum analyzer didn't show any significant additional signals above the existing 60Hz and on-board digital noise, measured on the input of the speaker amplifier.

(sounds like the musical note B4 ~493Hz)

@CedarGroveStudios
Copy link

CedarGroveStudios commented May 22, 2022

Here's a summary of board test results comparing the existing main distribution of CircuitPython with the newly modified test version. I performed two audio noise tests, one using a spectrum analyzer to characterize the overall noise and to measure the contribution of the PWM signal. The other test was more subjective and was conducted by holding the speaker very close to the ear. Ear buds were used in addition to the speaker when testing the PyGamer.

summary_2022-05-21

The 500Hz PWM signal bleedthrough was detectable with the ear on all boards that use DAC analog audio output except the PyGamer. The PyBadge audio noise was the most noticeable with the revised version -- was also noisy when running the existing distribution. The Clue and FunHouse boards use PWM audio rather than an analog input amplifier, so quiescent noise was not an issue. In most cases, the bleedthrough level was approximately -25dBv; the PyGamer was much lower, close to -35dBv. (Spectrum charts for all boards are available for the curious.)

The change completely fixed the Titano's brightness linearity issue and didn't change the display brightness characteristics of the other boards. All boards were able to visibly display white text and graphics with a low brightness setting of 0.01 (1%).

In my opinion, the improved brightness linearity of the PyPortal display is worth the slight addition to the existing quiescent audio noise. With the change, the brightness would be predictably close to other TFT displays. However, if the Titano displayio brightness PWM frequency setting could be built independently of the other boards, then only the Titano would exhibit the slight increase in audio noise.

@dhalbert
Copy link
Collaborator

However, if the Titano displayio brightness PWM frequency setting could be built independently of the other boards, then only the Titano would exhibit the slight increase in audio noise.

We could certainly customize per board by adding a setting value. I'm not sure I understand which values you recommend for which boards.

@CedarGroveStudios
Copy link

However, if the Titano displayio brightness PWM frequency setting could be built independently of the other boards, then only the Titano would exhibit the slight increase in audio noise.

We could certainly customize per board by adding a setting value. I'm not sure I understand which values you recommend for which boards.

Only the frequency of the PWM pin that drives the backlight controller needs to be set differently for the Titano build.

@dhalbert
Copy link
Collaborator

@CedarGroveStudios Thanks!

@FoamyGuy We could add yet another argument to the Display constructor. I don't think this should be compile-time only for the TItano, because someone could use a similar display as a non-builtin display, and would want the PWM frequency option.

The shared-module constructor argument list is getting kind of ridiculously long. Perhaps we should make a struct definition, with reasonable defaults, and pass the struct. This is a breaking change, but would result in more readable code.

In the Python world, at least there are default arguments, so many of the arguments do not need to be passed to the Python constructor. The same defaults would be set up when the struct was initialized.

@tannewt Do you have an opinion on this?

@CedarGroveStudios
Copy link

CedarGroveStudios commented May 22, 2022

The Titano audio input spectrum chart showing the overall noise with the 50kHz and 500Hz PWM signal contributions.

titano_summary_2022-05-21

@FoamyGuy
Copy link
Collaborator Author

I like the idea of it being a constructor argument so that it can be set as needed for each device / display. Refactoring the constructor to taking a DisplayConfiguration or DisplayOptions or something like that with all of the values contained in an object instead of the long list of arguments directly does seem like an improvement to me, but would require a fairly large amount of changes if I understand correctly. All display driver libraries and all built-in display initializations for any devices with them built-in. Definitely should await a new major release if we want to make that change I think.

@dhalbert
Copy link
Collaborator

I think we don't really need a DisplayConfiguration for the Python side, because of argument defaulting. But it would make things easier on the C side, because we wouldn't have to change all the calls every time we added another argument.

@CedarGroveStudios
Copy link

CedarGroveStudios commented May 22, 2022

A side distraction: As a workaround, is there a way to release a board.LITE pin for independent use?

@deshipu
Copy link

deshipu commented May 22, 2022

A side distraction: As a workaround, is there a way to release a board.LITE pin for independent use?

Release the displays, and re-initialize it without the backlight pin.

@dhalbert
Copy link
Collaborator

@FoamyGuy We could merge this as is, and do the harder work later of a settings struct to support custom PWM frequencies. I am not sure of the tradeoff of fixing the Titano problem vs making the other boards slightly noisier.

@FoamyGuy
Copy link
Collaborator Author

Okay, I'm up for whatever you all think is best. I think I have an idea of how to add the argument as a new argument for Display. I'm less familiar with the process of making the struct to refactor all of those arguments, but willing to give it a try and learn.

@FoamyGuy
Copy link
Collaborator Author

I have new commits coming that add this as an argument to the display construct function. I need to go through and update all of the devices with built-in display to utilize the new argument to get it ready. I have tested this approach on the Titano and it does seem to work as expected to allow that device the full range of brightness.

@FoamyGuy
Copy link
Collaborator Author

FoamyGuy commented Jun 4, 2022

Latest commits include the change to make this an argument in the display initializer and add it to all of the boards with built-in displays.

ESP32-S3 Feather TFT didn't exist when I made this branch I think so it was missed by my first sweep but fixed with latest commit after I noticed it's build failed.

I test builds from this PR for the following devices:
Macropad
PyPortal Titano (the only one using the a different value than previous)
Pimoroni Picosystem
PyGamer
ESP32-S2 Feather TFT

All devices initialized their displays correctly and setting brightness levels worked as expected.

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thanks. At some point I will look into putting the constructor parameters into a struct.

@dhalbert dhalbert merged commit 80ae142 into adafruit:main Jun 6, 2022
@CedarGroveStudios
Copy link

CedarGroveStudios commented Aug 29, 2022

Was the brightness control adjustment for the Titano fixed? It's still behaving the same with v7.3.3, not visible at 0.4 or lower.

@dhalbert
Copy link
Collaborator

@CedarGroveStudios This PR fixed it in main, not in 7.3.x, so the fix is in 8.0.0-beta.0 and later builds. Can you move to 8.0.0-something?

@CedarGroveStudios
Copy link

I've tried 8.0.0, but wasn't able to change board.DISPLAY.brightness from its default 1.0 setting. Let me try it again to make certain I wasn't doing something wrong.

@CedarGroveStudios
Copy link

Just confirmed that the brightness parameter value doesn't change or alter the display brightness in the REPL:

Press any key to enter the REPL. Use CTRL-D to reload.
�]0;🐍REPL | 8.0.0-beta.0\
Adafruit CircuitPython 8.0.0-beta.0 on 2022-08-18; Adafruit PyPortal Titano with samd51j20
>>> import board
>>> board.DISPLAY.brightness = 0.5
>>> board.DISPLAY.brightness
1.0
>>> ```

@dhalbert
Copy link
Collaborator

@CedarGroveStudios Another user reported the brightness bug in #6838.

@CedarGroveStudios
Copy link

Confirmed. The full range of brightness works properly with auto_refresh = False. I don't think the refresh setting made a difference before.

@CedarGroveStudios
Copy link

@dhalbert ref comment regarding shared TCC timer in #6894 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Displayio: PyPortal Titano backlight brightness setter is nonlinear
4 participants