Skip to content

fix: backlight on CrowPanel Advance 4.3/5.0/7.0 V1.2+ hardware (STC8H1K28 MCU) - #307

Open
ElBartoCompany wants to merge 3 commits into
meshtastic:masterfrom
ElBartoCompany:devin/1776797980-crowpanel-adv-7-v12-backlight
Open

fix: backlight on CrowPanel Advance 4.3/5.0/7.0 V1.2+ hardware (STC8H1K28 MCU)#307
ElBartoCompany wants to merge 3 commits into
meshtastic:masterfrom
ElBartoCompany:devin/1776797980-crowpanel-adv-7-v12-backlight

Conversation

@ElBartoCompany

@ElBartoCompany ElBartoCompany commented Apr 21, 2026

Copy link
Copy Markdown

Summary

LGFX_ELECROW70 only knew how to drive the TCA9534 I/O expander at I²C 0x18, which is present on CrowPanel Advance 4.3"/5.0"/7.0" V1.0/V1.1 boards. Starting with hardware revision V1.2 (and including V1.3 / V1.4 currently shipping in the wild) Elecrow replaced the TCA9534 with an STC8H1K28 microcontroller at I²C 0x30 that now gates the backlight, buzzer, speaker and touch-controller enable. With the old driver, V1.2+ boards would initialise the RGB panel correctly but the backlight would never be turned on — the screen was only visible under a flashlight (matches the report in meshtastic/firmware#7126 for the 7" board).

Protocol (from Elecrow's CrowPanel-Advance-7-HMI-ESP32-S3 reference repo):

  • 0 → backlight max (V1.3+ scale, also valid on V1.2 as a no-op which leaves the panel dark)
  • 245 → backlight off
  • 246/247 → buzzer on/off
  • 248/249 → speaker on/off
  • 250 → activate touch controller

The MCU needs a wake sequence on cold boot (pulse GPIO1 low for ~120 ms, write 250, write 0) — a plain I²C probe doesn't work because the STC8H1K28 is still coming up and NACKs every early transmission.

What this PR does

  • Probe the TCA9534 at 0x18 at init_impl() time to classify the hardware revision.
    • Present → original V1.0/V1.1 TCA9534 code path, unchanged.
    • Absent → assume V1.2+ and run Elecrow's reference wake sequence (write 250 → pulse GPIO1 LOW 120 ms → write 0), repeated 5 times to cover the window during which the MCU is still booting.
  • Move sleep/wakeup to the MCU path (245 = off, 0 = max) on V1.2+ boards; keep TCA9534 sleep/wakeup for V1.0/V1.1.
  • Add a small writeMcu() helper and named constants for the single-byte commands.

Validated on real CrowPanel Advance 7.0" V1.4 hardware running elecrow-adv1-43-50-70-tft: backlight now comes up at full brightness on cold boot, and the device stays stable afterwards.

Review & Testing Checklist for Human

Risk: yellow — small, targeted change confined to LGFX_ELECROW70.h, but it changes the init order slightly and I've only been able to verify on V1.4 hardware.

  • Verify a V1.0 or V1.1 CrowPanel Advance 4.3/5.0/7.0 (TCA9534-based) still boots with backlight on, and sleep/wakeup still work.
  • Verify on a V1.2, V1.3, or V1.4 board (STC8H1K28-based, MCU at 0x30) that backlight comes up on cold boot and stays on during normal use.
  • Double-check that the MCU wake sequence is not interfering with anything else Meshtastic does on Wire early during boot (the I2C scan runs before screen->setup() so Wire is already begun on SDA=15/SCL=16 by the time init_impl runs on this variant).
  • Consider whether the 5-iteration wake loop (~1.1 s worst case) is acceptable in the boot path, or if it should be reduced / gated behind a new define.

Suggested test plan: flash elecrow-adv1-43-50-70-tft on both an older TCA9534-based unit and a newer STC8H1K28-based unit, cold boot each, and confirm visible backlight + normal LVGL UI on both.

Notes

  • Fixes the backlight half of [Bug]: backlight CrowPanel Advance 7.0-HMI ESP32 AI Display firmware#7126 for the 7" V1.x boards. The 2.4"/3.5" variants and the adv2-* envs are not affected by this change.
  • A companion PR against meshtastic/firmware will bump the device-ui pin so the fix reaches users without requiring a local rebuild.
  • The 250 (activate touch) command is issued unconditionally on V1.2+; on boards where touch was already awake this is a no-op, and without it the GT911 touch controller remains unpowered on cold boot.

Summary by CodeRabbit

  • New Features

    • Added automatic hardware-revision detection for CrowPanel displays.
    • Added support for V1.2 and newer boards, including improved wake-up, touch activation, GPIO control, and backlight handling.
  • Bug Fixes

    • Preserved sleep and wake compatibility for V1.0 and V1.1 boards.
    • Ensured display power management uses the appropriate control method for each hardware revision.

devin-ai-integration Bot and others added 2 commits April 21, 2026 19:16
The V1.2 hardware revision of the CrowPanel Advance 7-inch (and the
4.3/5.0 siblings sharing this LGFX driver) replaced the TCA9534 I/O
expander with an STC8H1K28 microcontroller at I2C 0x30 that now gates
the backlight, buzzer, speaker and touch enable. The existing driver
only programmed the TCA9534 at 0x18, so boards from V1.2 onward (incl.
the V1.3 'latest' revision and V1.4 units currently in the wild) boot
with the backlight off — the panel initialises correctly but is only
visible under a flashlight. See meshtastic/firmware#7126.

Probe I2C 0x30 at init_impl() time and, when the MCU is present,
follow Elecrow's reference sequence (pulse GPIO1 low, write 250 to
activate touch, write 0 for max backlight) instead of the TCA9534
path. Sleep/wakeup on V1.2+ hardware now toggle backlight via the
same MCU (write 245 to disable, write 0 to re-enable). V1.0/V1.1
boards with the TCA9534 at 0x18 continue to use the original code
path unchanged.

Co-Authored-By: mirko sacchi <sacchimirko44@gmail.com>
Probing I2C 0x30 directly is unreliable on cold boot — the MCU hasn't
finished coming up yet and NACKs every probe attempt, which caused
the driver to fall through to the TCA9534 path and leave the backlight
disabled on V1.4 hardware after a power cycle (though it worked after
a soft reset because the MCU retained state from the previous run).

Discriminate hardware revisions via the TCA9534 at 0x18 instead — it's
always passive and always ACKs on V1.0/V1.1. If the TCA9534 is absent
we assume V1.2+ and execute Elecrow's reference wake sequence
unconditionally (write 250, pulse GPIO1 low for 120 ms, write 0 for
max brightness), repeated 5 times so a single NACK during MCU boot
doesn't leave us dark.

Co-Authored-By: mirko sacchi <sacchimirko44@gmail.com>
@CLAassistant

CLAassistant commented Apr 21, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ mverch67
❌ devin-ai-integration[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Congratulations for your first pull request

@ElBartoCompany ElBartoCompany changed the title Fix backlight on CrowPanel Advance 4.3"/5.0"/7.0" V1.2+ hardware fix: backlight on CrowPanel Advance 4.3/5.0/7.0 V1.2+ hardware (STC8H1K28 MCU) Apr 21, 2026
@mverch67

mverch67 commented Apr 22, 2026

Copy link
Copy Markdown
Collaborator
  1. Does it still work on V1.1 boards?
  2. How do you distinguish V1.2 from V1.3 and from V1.4 boards?
  3. Does the display brightness slider work as expected?

@hexfet100

Copy link
Copy Markdown
  1. Does it still work on V1.1 boards?

  2. How do you distinguish V1.2 from V1.3 and from V1.4 boards?

  3. Does the display brightness slider work as expected?

I don't have a ver 1.1 in 7" only a 3.5 ver 1.0. My board is silkscreened DIS02170A 7" hdw ver 1.4. I do not have a brightness slider.

@mverch67

Copy link
Copy Markdown
Collaborator

I don't have a ver 1.1 in 7" only a 3.5 ver 1.0. My board is silkscreened DIS02170A 7" hdw ver 1.4. I do not have a brightness slider.

yeah, that's all correct. Ver 1.0 does not have means to change display brightness because that's what has been added in later hardware versions only.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The display driver detects Elecrow board revisions during initialization. It uses the STC8H1K28 control path for V1.2+ boards and the TCA9534 GPIO path for V1.0/V1.1 boards during initialization, sleep, and wake.

Changes

Elecrow hardware revision support

Layer / File(s) Summary
Revision detection and initialization
include/graphics/LGFX/LGFX_ELECROW70.h
The driver defines hardware addresses and command values. init_impl probes 0x18, then initializes either the TCA9534 GPIO path or the STC8H1K28 wake, touch, and backlight sequence.
Sleep and wake control
include/graphics/LGFX/LGFX_ELECROW70.h
Sleep and wake use MCU backlight commands for MCU-based boards. Legacy boards continue to use the TCA9534 backlight pin. A private MCU byte-write helper tracks MCU hardware selection.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant init_impl
  participant TCA9534
  participant STC8H1K28
  init_impl->>TCA9534: Probe address 0x18
  alt TCA9534 detected
    init_impl->>TCA9534: Configure GPIO and backlight
  else STC8H1K28 board
    init_impl->>STC8H1K28: Send wake and touch activation
    init_impl->>STC8H1K28: Send repeated backlight commands
  end
Loading

Poem

I’m a rabbit beside the display,
Two board paths now know the way.
TCA9534 keeps the old lights bright,
STC8H1K28 wakes the new ones right.
Sleep and wake now follow each board’s cue.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: backlight support for CrowPanel Advance hardware using the STC8H1K28 MCU.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
include/graphics/LGFX/LGFX_ELECROW70.h (1)

53-69: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider an early exit from the wake loop once the MCU acknowledges.

The loop always runs all 5 iterations (~1.1s total: delay(120) + delay(100) + delay(20) per iteration), even after the MCU responds successfully on an earlier iteration. writeMcu()'s return status is discarded, so there is no way to stop early. The PR description itself calls out this wake-loop duration as a point worth reviewer consideration.

Track the Wire.endTransmission() result and break out of the loop once a write succeeds, to avoid the fixed ~1.1s delay on every boot once the MCU is confirmed awake.

♻️ Proposed early-exit refactor
-            for (int attempt = 0; attempt < 5; ++attempt) {
-                writeMcu(CROW_MCU_TOUCH_ACTIVATE);
-                pinMode(1, OUTPUT);
-                digitalWrite(1, LOW);
-                delay(120);
-                pinMode(1, INPUT);
-                delay(100);
-                writeMcu(CROW_MCU_BL_MAX);
-                delay(20);
-            }
+            for (int attempt = 0; attempt < 5; ++attempt) {
+                Wire.beginTransmission(CROW_MCU_I2C_ADDR);
+                Wire.write(CROW_MCU_TOUCH_ACTIVATE);
+                bool ok = (Wire.endTransmission() == 0);
+                pinMode(1, OUTPUT);
+                digitalWrite(1, LOW);
+                delay(120);
+                pinMode(1, INPUT);
+                delay(100);
+                writeMcu(CROW_MCU_BL_MAX);
+                delay(20);
+                if (ok) {
+                    break;
+                }
+            }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/graphics/LGFX/LGFX_ELECROW70.h` around lines 53 - 69, Update the wake
loop in the hasMcu initialization path to use the success status from writeMcu
for each MCU command, and break once the MCU acknowledges successfully. Preserve
the existing retry sequence and GPIO pulse behavior when writes fail, while
avoiding remaining iterations and delays after a successful acknowledgment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@include/graphics/LGFX/LGFX_ELECROW70.h`:
- Around line 53-69: Update the wake loop in the hasMcu initialization path to
use the success status from writeMcu for each MCU command, and break once the
MCU acknowledges successfully. Preserve the existing retry sequence and GPIO
pulse behavior when writes fail, while avoiding remaining iterations and delays
after a successful acknowledgment.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 57d06fef-47e7-4243-ae8a-0ede6301ce64

📥 Commits

Reviewing files that changed from the base of the PR and between 95483d8 and aa4932c.

📒 Files selected for processing (1)
  • include/graphics/LGFX/LGFX_ELECROW70.h

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.

4 participants