Skip to content

feat(oled): Implement brightness control and auto-power save for bread-compact-wifi#1659

Open
parkghost wants to merge 2 commits into78:mainfrom
parkghost:feature/oled-brightness-power-control
Open

feat(oled): Implement brightness control and auto-power save for bread-compact-wifi#1659
parkghost wants to merge 2 commits into78:mainfrom
parkghost:feature/oled-brightness-power-control

Conversation

@parkghost
Copy link

@parkghost parkghost commented Jan 15, 2026

Description

This PR implements comprehensive power management and brightness control for OLED displays, specifically targeting the bread-compact-wifi board.

Key Features:

  1. Hardware Power Control: Implemented SetPowerSaveMode in OledDisplay to use esp_lcd_panel_disp_on_off for true hardware sleep/wake.
  2. Brightness/Contrast Control:
    • Added SetContrast using command 0x81.
    • Implemented OledBacklight adapter to map brightness (0-100) to contrast (0-255).
    • Smart Threshold: Setting brightness <= 5% turns off the display power completely; > 5% turns it on and sets contrast.
  3. Auto Power Save:
    • Integrated PowerSaveTimer in CompactWifiBoard.
    • Automatically turns off the screen after 60 seconds of inactivity.
    • Wakes up on Button (Boot, Touch, Volume) events or Voice activity.
  4. MCP Integration: Exposed OledBacklight via GetBacklight, enabling the standard self.screen.set_brightness tool for voice control (e.g., "Turn off screen", "Set brightness to 50").

Testing

  • Validated on bread-compact-wifi-128x64.
  • Verified voice commands for brightness and screen on/off.
  • Verified auto-sleep timeout.

Related Issue

- **OledDisplay**:
  - Add hardware power control in `SetPowerSaveMode`.
  - Add `SetContrast` using SSD1306/SH1106 command 0x81.
  - Implement `OledBacklight` adapter class to map brightness to contrast.
  - Default brightness set to 50% to match hardware reset state.
  - Logic: Brightness <= 5% turns off display power; > 5% turns on and sets contrast.

- **CompactWifiBoard**:
  - Integrate `PowerSaveTimer` for 60-second idle auto-sleep.
  - Override `GetBacklight` to expose `OledBacklight` to MCP tools.
  - Add wake-up triggers to Boot, Touch, and Volume buttons.
  - Sync system power save level with display timer.
@78
Copy link
Owner

78 commented Feb 2, 2026

This feature should be optional.

Auto-off screens should not be mandatory for all OLED board types.

@parkghost
Copy link
Author

I understand this is an optional feature. Is there an easy way to configure whether it is enabled or disabled, or does this currently require maintaining a custom Xiaozhi branch?

@78
Copy link
Owner

78 commented Feb 2, 2026

Check this file: https://github.com/78/xiaozhi-esp32/blob/main/main/Kconfig.projbuild

You can open the menuconfig in the root directory of the project with the following command:

# idf.py menuconfig

- Add CONFIG_OLED_AUTO_POWER_SAVE Kconfig option (default off) for bread-compact-wifi to make screen auto-off optional
- Make Backlight::SetBrightness virtual to allow OledBacklight to skip the PWM gradual transition, applying brightness changes immediately
@parkghost parkghost force-pushed the feature/oled-brightness-power-control branch from efaa093 to 2c03282 Compare February 6, 2026 18:59
@78
Copy link
Owner

78 commented Feb 7, 2026

Hi. Why not just override SetBrightnessImpl in OledBacklight to call SetContrast?

@parkghost
Copy link
Author

Thanks for the suggestion. The reason I overrode SetBrightness instead of only SetBrightnessImpl is related to the transition timer in the base class.

The base Backlight::SetBrightness starts a periodic timer that steps brightness by 1 every 5ms, calling SetBrightnessImpl on each tick. This works great for PWM-based LCD backlights where the hardware produces a visually smooth fade. However, for OLED displays, each step sends an I2C 0x81 contrast command — the result doesn't look like a smooth transition but rather feels like input lag (up to 500ms).

I overrode SetBrightness to bypass the transition and apply the contrast instantly, but I realize this duplicates base class logic and requires making SetBrightness virtual.

Do you have any suggestions? I'd be happy to make corrections.

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.

2 participants