Skip to content

EN05 issue with 4-gray 7.5" configuration #151

Description

@BWagener

I've tested around with the Seeed EN05 and 2-gray and 4-gray configurations on a 7.5" screen.

2-gray works flawlessly, 4-gray is washed out and definitely not working properly. I was able to isolate the EN05 being the problem by testing three EN05 (always the same result) against an EE04, each tested on two screens.

4-gray comparison Seeed EN05 vs Seeed EE04

EN05

note the washed out greys at the bottom, the QR code on the right-hand side of the screen and the logo in the top-right-hand corner

Image Image

EE04

note the clear greys and no washed out logo and QR code

Image

Let me know if there's more information I can provide or anything else I can test.

Activity

  1. davelee98 commented on Aug 26, 2026

    @davelee98
    Contributor

    Open question on this is whether the difference is from Ex04 vs Ex05 or due to ESP32 vs Nordic. Do you happen to have an EN04 on hand?

  2. BWagener commented on Aug 26, 2026

    @BWagener
    Author

    Unfortunately no, just the EE04

  3. jonasniesner commented on Aug 26, 2026

    @jonasniesner
    Member

    I have both to try. I fear though that this issue might not be easily solved because 4 Gray is not an "official" mode of that panel

  4. BWagener commented on Sep 26, 2026

    @BWagener
    Author

    I'm happy to report I have been able to find a workaround for this issue!

    The TLDR solution was to manually set the configuration panel_ic_type from the default 60 to either 21 or 22.

    For technical details and a possible bug discovered during my research read below:

    Slopped writeup

    EN05 (nRF52840) washed-out 4-gray on 7.5" panels — investigation writeup

    Firmware: OD 2.26.2 · bb_epaper pin: 5dccfbbf553a9b0fe2547cbc4e60138e1ff2fb43

    1. Problem

    With the opendisplay.org preset "7.5" Monochrome 4-gray (800×480)" (panel_ic_type 60 =
    0x003C → bb_epaper EP75_800x480_4GRAY_GEN2):

    • Seeed EE04 (ESP32-S3): clean 4-gray.
    • Seeed EN05 (nRF52840): washed out — white background renders light gray, the gray swatches
      are grainy/mottled, QR code and logo look speckled. Reproduced on three EN05 boards and two panels.
    • 2-gray (panel_ic_type 59, mono GEN2) is flawless on both boards.

    The question was whether this is a firmware or a hardware issue.

    2. Code analysis — is the firmware doing anything different on nRF?

    Everything between the config and the panel wires was compared for nRF vs ESP32:

    Area Finding
    Panel mapping mapEpd(60) → EP75_800x480_4GRAY_GEN2 on both targets.
    Init / refresh Same bb_epaper commit on every env. epd75_gray_init (PSR 0x1F, CDI, PON, booster 0x27 0x27 0x18 0x17, CCSET 0xE0=0x02, TSSET 0xE5=0x5F) and bbepRefresh() are target-independent.
    Session / power epdSessionAcquire, pwrmgm, waitforrefresh, bbepSleep — no nRF-specific branches on the panel path.
    Image data path Direct-write, pipe-write, zlib and streamGray4Bytes plane split are target-independent.
    Boot screen boot_screen.cpp has no nRF/ESP32 branches except FastEPD (not used here).
    bb_epaper I/O Only difference is SPI.transferBytes (ESP32) vs per-byte SPI.transfer (nRF) — same bytes on the wire.

    Two observations narrowed it further:

    1. The boot screen itself is washed out. It is rendered on-device, so BLE transfer, compression
      and py-opendisplay are ruled out.
    2. 2-gray is clean over the same SPI link. An SPI signal-integrity problem would corrupt
      plane data in mono too, so bit errors are ruled out.

    Conclusion from code: both MCUs send byte-identical command sequences to the panel.

    3. Hardware comparison (Seeed schematics)

    The 24-pin panel boost circuit differs materially between the boards:

    EE04 (SCH V1.2) Ex05 / EN05 (SCH V1.0)
    Boost inductor 10 µH, 2.35 A 47 µH, 570 mA (FNR4018S470MT)
    RESE (boost current sense) 0.47 Ω 2.2 Ω
    Boost MOSFET CJ2324 100 V 2 A SI1308EDL 30 V 1.4 A

    The EN05's boost stage has far less peak-current headroom. Mode 60 is not an official panel mode:
    it forces a fake temperature (TSSET = 0x5F, 95 °C) so the controller loads a different OTP
    waveform bank. Hypothesis: that waveform draws more than the EN05's boost can deliver, leaving
    the panel under-driven (gray whites, grainy mid-tones).

    4. Tests

    Test 1 — refresh duration (boot screen, 4-gray, panel_ic_type 60)

    Board Printed "Refresh took" Wall clock (EPD refresh: FULL → Refresh took)
    EN05 1.04 s 09.710 → 11.887 = 2.18 s
    EE04 1.01 s 04.686 → 06.852 = 2.17 s

    Identical within one poll step. Both controllers accept the forced temperature and run the same
    waveform for the same duration; the refresh is not cut short on the EN05. (Note: the printed value
    under-reports real time roughly 2×, because each waitforrefresh iteration is ~21 ms — delay(10)
    plus bbepIsBusy's own ~11 ms — but is counted as 10 ms.)

    Test 2 — alternative 7.5" 4-gray panel types (config-only), on both boards

    panel_ic_type bb_epaper type Waveform source EN05 result EE04 result
    60 (0x003C) EP75_800x480_4GRAY_GEN2 OTP bank via forced temp, default power regs washed out clean
    21 (0x0015) EP75_800x480_4GRAY register LUTs, explicit PWR 07 07 3F 3F 03, VDCS 0x12 clean grays, mid-grays swapped clean grays, mid-grays swapped
    22 (0x0016) EP75_800x480_4GRAY_V2 register LUTs, explicit PWR, VDCS 0x12 clean grays, correct order clean grays, correct order

    The EN05 hardware can drive the panel in 4-gray when the waveform is supplied from registers
    with explicit power settings, and types 21/22 behave the same on the EE04. The mid-gray swap on
    type 21 appears on both boards, confirming it is a mapping issue, not a hardware one. The problem is specific to the OTP forced-temperature mode (60)
    in combination with the EN05's weaker boost stage.

    The type-21 mid-gray swap

    epd75_old_gray_init (type 21) and epd75_old_gray_init2 (type 22) are identical except that
    the final pulse rows of the BW (0x22) and WB (0x23) LUTs are exchanged:

    BW (0x22) last row WB (0x23) last row
    type 21 99 11 04 06 06 (ends on 6 black frames → darker) 99 10 06 08 03 (ends on 3 → lighter)
    type 22 99 06 10 08 03 (lighter) 99 11 04 06 06 (darker)

    So the two stored mid-gray codes produce opposite gray levels on 21 vs 22. bb_epaper tags both
    with u8Colors_4gray, and both the firmware boot screen (kGray4StoredBase = {3,1,2,0}) and
    py-opendisplay (_GRAY4_CODES_BASE = (3,1,2,0)) follow that, which matches type 22 but is
    reversed for type 21. Type 21 needs the reversed table {3,2,1,0} (already used for
    0x0028/0x0048 as "V2").

    5. Conclusions

    1. Not a panel defect, and not an nRF firmware path bug. Firmware behaviour is identical on
      both MCUs; the difference is the EN05's boost circuit, exposed by the unofficial mode-60
      waveform.
    2. Workaround available now (config-only): use panel_ic_type: 22. It is verified clean
      with correct gray order on both the EN05 and the EE04.
    3. Mapping bug found: type 21 renders the two mid-grays swapped in both the firmware boot
      screen and py-opendisplay uploads.

    6. Changes / possible follow-ups

    Repo Change Status Commit
    Firmware src/boot_screen.cpp: add 0x0015 to bootGray4PanelUsesLutV2() - Link
    py-opendisplay display_palettes.py: add 0x0015: _GRAY4_CODES_V2 to _GRAY4_CODES_BY_PANEL - Link
    opendisplay.org Switch the 7.5" 4-gray preset (ep75-800x480-4gray) panelIcType from 60 to 22 recommended: 22 verified on EN05 and EE04 Link
    Firmware (optional) Investigate adding explicit PWR/VDCS to the mode-60 init for weak-boost boards only if 60 must keep working on EN05 -

    What I can't get to work with the EN05 and panel in question is partial, non-flashing refresh. I don't understand and haven't tested enough whether this is related to the ic_panel_type at all.

  5. davelee98 commented on Sep 26, 2026

    @davelee98
    Contributor

    Thanks. I came to a similar hypothesis that EN05 (and presumably also EE05) has an underpowered boost circuit. Interesting that an alternate set of LUT fixes this so easily.

    Note that partial refresh is only possible with black/white mode. Grayscale and partial are not possible at the same time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions