#bb_paper inclusion in ESPHome

267 messages · Page 1 of 1 (latest)

steep quarry
#

Hey @tropic musk I have made a thread here for your work implementing your epaper library into ESPHome.
Let us know how its going and if you have any questions here

#

cc @pseudo fossil

tropic musk
#

thanks

tropic musk
pseudo fossil
#

Do you have a log? Is the code on gh?

tropic musk
#

The namespace/class/codegen step is completely opaque to me and it's generating strange results

#
src/main.cpp: In function 'void setup()':
src/main.cpp:603:55: error: invalid new-expression of abstract class type 'esphome::epaper::BB_EPaperBase'
  603 |   epaper_bb_epaperbase_id = new epaper::BB_EPaperBase();
      |                                                       ^
In file included from src/esphome.h:18,
                 from src/main.cpp:3:
src/esphome/components/bb_epaper/bb_epaperbase.h:11:7: note:   because the following virtual functions are pure within 'esphome::epaper::BB_EPaperBase':
   11 | class BB_EPaperBase : public display::DisplayBuffer,
      |       ^~~~~~~~~~~~~
#

my display.py:


BB_EPaperBase = epaper_ns.class_(
    "BB_EPaperBase", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer
)

CONFIG_SCHEMA = cv.Schema(
    display.FULL_DISPLAY_SCHEMA.extend(
        {
            cv.GenerateID(): cv.declare_id(BB_EPaperBase),
...
#

relevant part

#

I can create a new repo with just my component

#

I don't understand how the class name nesting gets so twisted up by codegen

#

I normally work in C, so this C++ syntax is quite confusing

#

it looks like something wrong with the way I'm extending the Display class

pseudo fossil
#

Or are any of those in the header but not implemented in the cpp?

raven isle
#

I assume you have classes for each display?

tropic musk
tropic musk
#

I thought it would be relatively simple to write a wrapper class over bb_epaper

#

I had to write some new features such as I/O through function pointers to get the I/O to work in ESPHome

#

I don't know how to "gen" the code to make this simple

#

I don't need components or subclasses

raven isle
#

I wondered how well this was going to integrate when I first heard about it...

tropic musk
#

should be quite straightforward if not for the class twist-up

#

I'll create a public repo for the code, hang on

tropic musk
raven isle
#

It's quite direct. It's the to_code that generates it.

tropic musk
#

right, but Python->C++ syntax makes no sense

#

if it's just the missing virtual functions, then that should be easy to solve

raven isle
#

var = cg.new_Pvariable(config[CONF_ID]) creates a new variable with the class defined in CONF_ID, so BB_EPaperBase in this case.

#

You can see the generated code in main.cpp.

tropic musk
#

none of that syntax makes sense to me. What kind of programmer would work in that world ?

raven isle
#

I don't see any issues with it... 🤷‍♂️

tropic musk
#

so you're a Python programmer?

raven isle
#

yes, and whatever other languages 🙂

tropic musk
#

I never work in Python, and don't get into the weeds of C++, so it doesn't make sense to me

raven isle
#

esphome gets into deep details of both.

tropic musk
#

I'm less interested in becoming an expert in this subject and more interested in just getting this simple project working

#

my time is very limited and the frustration increases exponentially the more time I have to dedicate to this

pseudo fossil
#

Are all the virtuals implemented? If your code is on GH it will be helpful.

tropic musk
#

see link above

#

I'm adding the virtual functions now

pseudo fossil
#

If pure virtuals are not implemented you will get that error when it tries to create the object in main.cpp

tropic musk
#

fixing now...

#

I'm looking at the ST7789 implementation and it doesn't have a couple of the virtual functions that my build is complaining are missing

#

Thanks @pseudo fossil & @raven isle most errors are resolved now. I'll let you know if I have any more questions.

tropic musk
#

Hi @raven isle closer, but still not working

#

my code all compiles without errors, but the display component is never called

#
  - platform: bb_epaper
    id: waveshare_esp32s3
    cs_pin: GPIO11
    dc_pin: GPIO10
    busy_pin: GPIO8
    reset_pin: GPIO9
    model: ep154_200x200
    lambda: |-
        it.print(0, 0, id(Roboto_10), "Hello World!");

#

I added logging to the main methods and they never get printed

#

Am I missing something obvious?

#

(WiFi succeeds)

#
[13:09:39.476][I][safe_mode:054]: Boot seems successful; resetting boot loop counter
pseudo fossil
tropic musk
#

I'm using USB

#

I added logging to all main methods

#

nothing ever prints

#

initial log:

INFO Successfully uploaded program.
INFO Starting log output from /dev/cu.usbmodem113201 with baud rate 115200
[13:03:39.425][I][app:084]: Running through setup()
[13:03:39.426][V][app:085]: Sorting components by setup priority
[13:03:39.427][V][component:201]: Setup wifi
[13:03:39.444][C][wifi:373]: Starting
pseudo fossil
#

Code in gh is up to date?

tropic musk
#

not yet; I'll poke through the main.cpp to see if I can figure out the issue

steep quarry
tropic musk
tropic musk
#

hi @raven isle I've made a lot of progress with the bb_epaper component, but there are still some issues to resolve.

#

The initialization and update methods seem to be working, but my yaml lamba doesn't result in any fill or pixel function calls

#
  - platform: bb_epaper
    update_interval: 30s
    id: waveshare_esp32s3
    cs_pin: GPIO11
    dc_pin: GPIO10
    busy_pin: GPIO8
    reset_pin: GPIO9
    model: ep154_200x200
    lambda: |-
       it.fill(id(Color::BLACK));
       it.print(20, 60, id(medium), "This is a test");
#

it compiles and runs without any errors. I put log print statements in the fill() and draw_absolute_pixel_internal() methods, but they're never called.

pseudo fossil
#

Is your code up to date in gh?

tropic musk
#

can you think of a reason that the fill and pixel methods wouldn't get called?

#

possible C++ override syntax issue?

#

I'll push the component source; hang on

#

ok @raven isle newest component code is here:

pseudo fossil
#

Very hard to debug something without seeing the code. Can always create a dev branch and push to that

tropic musk
tropic musk
#

right now I'm getting successful updates, but the display is blank

tropic musk
#

the call to update() from ESPHome is succeeding with my library

pseudo fossil
#

do_update_ is some method from the display component, you inherit from DisplayBuffer which inherits from Display

tropic musk
#

still don't follow you. It's not a problem with update

pseudo fossil
#

Seems like you should be calling it but I havent done much display stuff

tropic musk
#

trailing underscore in the name indicates it's private to that repo and not an override method

pseudo fossil
#

It is protected. You inherited from display so that is part of your class

#

I am pretty sure that calls the lambda

#

Without it nothing will get rendered

tropic musk
#

I think you have it backwards

pseudo fossil
#

Did you try it?

tropic musk
#

that method is protected because of the extra layers of hierarchy of that library

#

no need - update is getting called and succeeding in my library

#

update gets called every 30s as it should

#

that's not the issue

pseudo fossil
#

Yes I know. Add this to your update function

tropic musk
#

makes no sense because the fill and pixel functions are never called

#

they would need to be called BEFORE the update

#

even if it happens once

#

if you look in the waveshare display driver there is no update_() method

#

ok, I'll try

tropic musk
#

I see - hang on

pseudo fossil
tropic musk
#

ah - thanks for being patient

#

compiling...

#

makes sense - it allows the display component to skip a redraw if necessary

#

thanks @pseudo fossil - working now 🙂

tropic musk
#

Now that it appears to be working, the bigger question is how we should present it to the users.

#

In it's current form, you specific the SPI connection and the panel type.

#

But... I've created a much simpler way for IoT devices with built in displays. For example, the Elecrow CrowPanel devices can be used with just a single line of code:
epaper.begin(EPD_CROWPANEL29);

#

The configuration is contained within bb_epaper, so the user doesn't have to fumble with GPIO connections

#

It currently supports 14 products like that

#

what do you think @raven isle @pseudo fossil ? I currently access SPI directly, but I could probably adapt it to use the ESPHome SPI component. Maybe I can create a second component for use with these products or a generic one for everything else.

tropic musk
#

one last question...

#

to enable either the iot device name or raw panel, I need SPI to be optional for the display component. Is that possible?

#

@raven isle

#

when I use the iot device name, all hardware initialization and communication is handled by my library

#

I would like the user to not have to define the SPI bus

#

or will that require a new ESPHome component?

raven isle
#

I think that's going to be a problem.

tropic musk
#

I got it working

#
  - platform: bb_epaper_iot
    update_interval: 60s
    id: test_epd
    model: EPD_CROWPANEL29
    lambda: |-
       it.fill(id(Color::BLACK));
       it.print(0, 0, id(medium), "bb_epaper test");
       it.printf(0, 80, id(medium), "one line config!");
raven isle
#

I mean I think it will be a problem getting it accepted.

tropic musk
#

Hey @raven isle how do you like no-flicker e-paper for ESPHome? 🙂

#

I'm experimenting with a default update type of partial updates with a fast update every 16 updates to eliminate any possible ghosting

tropic musk
#

@steep quarry I need some feedback on these decision. Should I expose the refresh type (full, fast, partial) or just do the least flickery way all the time?

#

(see youtube video above)

tropic musk
#

Hi @raven isle I'm working on supporting color e-paper displays and noticed something odd. The Display class call to get_display_type() isn't called (I put a log print statement in it). Is this not really needed?

#

I'm thinking that I should just do a best match of the requested color.

pseudo fossil
tropic musk
#

sorry, I don't follow you

#

for normal display usage will it get called?

pseudo fossil
#

I believe if you do something like this it will be called:

  display:
    - platform: xxx
      show_test_card: true
tropic musk
#

ok

tropic musk
final vault
#

nice! what board is that?

tropic musk
steep quarry
#

Hey @tropic musk Is the work in a state where it could be opened as a PR so we can see it with the ESPHome codebase?

tropic musk
#

I'm rewriting my bb_temperature library to work with the ESPHome I2C component and then I'll add my bb_captouch (pretty much covers all common capacitive touch screens)

#

I would appreciate any and all feedback on the bb_epaper work so far.

#

It already is a major step up from the waveshare library because it allows you to more easily choose the type of panel and the update mode

#

I created a second component (bb_epaper_iot) that simplifies things further for supported ESP32+EPD products like the ones from Waveshare. However, it currently uses the Arduino or ESP-IDF SPI library directly instead of using the one in ESPHome.

steep quarry
tropic musk
#

Yes and no ☺️. Are they written differently?

#

@steep quarry

raven isle
#

Exactly the same as the built-in ones.

steep quarry
#

Just wasnt sure given:

easy to manually copy into the /components folder to test

tropic musk
#

I'll redo the file structure to work as an external component

tropic musk
#

@steep quarry I'm finally sitting down to work on making my component conform to the ESPHome coding standards. I've got clang-format and clang-tidy installed, but I'm not sure if I'm using them correctly. I tried running the scripts (clang-format and clang-tidy). Both give errors

#

The clang-format script says that I may not have it installed in the environment. It is installed, yet shows this when I pass --version as the only parameter:

zsh: /Users/laurencebank/Projects/esphome/venv/bin/clang-format: bad interpreter: /Users/laurencebank/Projects/esphome/venv/bin/python3: no such file or directory
clang-format version 22.1.3
#

Running the clang-tidy script gives these errors:

  File "/Users/laurencebank/Projects/esphome/esphome/components/bb_epaper/../../../script/clang-tidy", line 357, in <module>
    sys.exit(main())
  File "/Users/laurencebank/Projects/esphome/esphome/components/bb_epaper/../../../script/clang-tidy", line 285, in main
    idedata = load_idedata(args.environment)
  File "/Users/laurencebank/Projects/esphome/script/helpers.py", line 546, in load_idedata
    stdout = subprocess.check_output(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 505, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'pio'
#

hmm - I just set up a new machine and it's missing some things. Let me work on this a bit more...

pseudo fossil
#

script/clang-tidy --all-headers --environment esp32-arduino-tidy and script/clang-tidy --all-headers --environment esp32-idf-tidy --grep USE_ESP_IDF

#

have to do source venv/bin/activate first

tropic musk
#

I did activate, but something else is broken

#

just running esphome from the command line gives this:

#

(venv) laurencebank@4a:5f:88:47:24:de esphome % esphome
zsh: /Users/laurencebank/Projects/esphome/venv/bin/esphome: bad interpreter: /Users/laurencebank/Projects/esphome/venv/bin/python3: no such file or directory
usage: esphome [-h] [-v] [-q] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[-s key value] [--mdns-address-cache MDNS_ADDRESS_CACHE]
[--dns-address-cache DNS_ADDRESS_CACHE] [--testing-mode]
[--version]
command ...

#

bad interpreter?

#

hang on, new machine problems - let me create a new venv

pseudo fossil
#
script/setup
source venv/bin/activate
script/clang-tidy --all-headers --environment esp32-arduino-tidy
script/clang-tidy --all-headers --environment esp32-idf-tidy --grep USE_ESP_IDF
tropic musk
#

it was that the new machine's python3 was in a different spot, but I had restored the esphome repo from the old machine

#

new python weirdness

#

(venv) laurencebank@4a:5f:88:47:24:de esphome % script/setup
Using Python 3.9.6 environment at: venv
Checked 2 packages in 11ms
Using Python 3.9.6 environment at: venv
× No solution found when resolving dependencies:
╰─▶ Because only esphome[dev]==2026.1.0.dev0 is available and the current
Python version (3.9.6) does not satisfy Python>=3.11.0,<3.14, we can
conclude that all versions of esphome[dev] cannot be used.
And because you require esphome[dev], we can conclude that your
requirements are unsatisfiable.

pseudo fossil
#

Yeah 3.9 is too old need >=3.11

tropic musk
#

strange, brew installed 3.14

#

how do I get the brew version to be seen in the esphome environment?

pseudo fossil
#

I have never used brew

#

Why not do it natively?

tropic musk
#

natively how?

pseudo fossil
#

Clone the repo and just run the setup script?

tropic musk
#

what repo?

pseudo fossil
#

The esphome repo

tropic musk
#

that has no bearing on the python3 problem

pseudo fossil
#

I dont know what brew has to do with this but I have never used it.

tropic musk
#

homebrew has python3 3.14 installed, but the system still references python 3.9.6

#

I need to fix the path order

#

@pseudo fossil thanks for your help. I had to switch the path order of zsh for it to find the correct Python version. Now things are working.

tropic musk
#

@pseudo fossil closer... still getting errors from the clang-tidy script and parameters you provided:

#

Total cpp files to check: 1
Added all-include header file, new total: 2
Final files to process:
    /Users/laurencebank/Projects/esphome/.temp/all-include.cpp
    bb_epaperbase.cpp
Loading IDE data for environment 'esp32-arduino-tidy'...
NotPlatformIOProjectError: Not a PlatformIO project. `platformio.ini` file has not been found in current working directory (/Users/laurencebank/Projects/esphome/esphome/components/bb_epaper). To initialize new project please use `platformio project init` command
pseudo fossil
#

run it from the root dir

tropic musk
#

This back and forth makes me think this would be a good topic to add to the developer documentation. I couldn't find any useful info there.

pseudo fossil
#

You cant run it on a single component, run it in the root esphome folder (I gave the commands above)

#

Most people just submit a PR and have CI run it

#
script/setup
source venv/bin/activate
script/clang-tidy --all-headers --environment esp32-arduino-tidy
script/clang-tidy --all-headers --environment esp32-idf-tidy --grep USE_ESP_IDF
tropic musk
#

So you're saying to just use the error info from trying to create a PR to make the edits instead of letting clang-tidy do them for me?

pseudo fossil
#

You will need to fix those errors first

tropic musk
#
  File "/Users/laurencebank/Projects/esphome/script/clang-tidy", line 357, in <module>
    sys.exit(main())
             ~~~~^^
  File "/Users/laurencebank/Projects/esphome/script/clang-tidy", line 285, in main
    idedata = load_idedata(args.environment)
  File "/Users/laurencebank/Projects/esphome/script/helpers.py", line 546, in load_idedata
    stdout = subprocess.check_output(
        ["pio", "run", "-t", "idedata", "-e", environment]
    )
  File "/opt/homebrew/Cellar/[email protected]/3.14.4/Frameworks/Python.framework/Versions/3.14/lib/python3.14/subprocess.py", line 473, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
           ~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
               **kwargs).stdout
               ^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.14.4/Frameworks/Python.framework/Versions/3.14/lib/python3.14/subprocess.py", line 578, in run
    raise CalledProcessError(retcode, process.args,
                             output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['pio', 'run', '-t', 'idedata', '-e', 'esp32-arduino-tidy']' returned non-zero exit status 1.
#

ah - new error: Loading IDE data for environment 'esp32-arduino-tidy'...
ERROR: Python version must be between 3.10 and 3.13.

#

The current version of Python on Homebrew is 3.14 and this seems to cause a problem for the script

pseudo fossil
#

3.14 works unless you are on an old version

tropic musk
#

old version of what?

pseudo fossil
#

Or havent run the setup script recently

#

ESPHome

tropic musk
#

I just did a git pull to get the latest. How can I tell

#

?

#

New machine - I just installed epshome

pseudo fossil
#

I ran it today on 3.14 and it was fine

tropic musk
#

This experience reinforces my belief that depending on Python for these tools creates a huge time expense for everyone 🙁

pseudo fossil
#

Submit a draft pr it will run it

tropic musk
#

I'd like to understand this roadblock

pseudo fossil
#

Homebrew seems to mess things up, python is fine

tropic musk
#

I'm using a newly installed esphome and the repo is up to date

#

I would assume the inverse

#

Python is always having trouble with version conflicts - it's a feature

pseudo fossil
#

We have so many issues where people are using homebrew and can't build

tropic musk
#

what's the "golden" OS to use for ESPHome? Linux?

pseudo fossil
#

That is what I use. No brew. Just python

tropic musk
#

homebrew is a package manager like apt, nothing to do with interfering in use of the tools

pseudo fossil
#

Well people try to install ESPHome with it. It messes with the paths.

tropic musk
#

I don't want to create extra work for you. It shouldn't take so much effort just to run clang-tidy

#

I can try this on my Linux laptop

pseudo fossil
#

I gave the commands above. I tested them and they work.

tropic musk
#

That's not helpful. If it's only designed for Linux, then ok.

pseudo fossil
#

I don't have a mac to try it on

tropic musk
#

Does anyone test it on MacOS or Windows?

pseudo fossil
#

I know Nick runs on a mac, maybe Clyde does too. But most people just get CI to run it

#

Almost no one runs it locally

tropic musk
#

the build system has worked fine so far on MacOS, it just seems to be an issue with running the clang-tidy script

#

when you say "get CI to run it", can you elaborate?

pseudo fossil
#

By creating a PR

tropic musk
#

my last try creating a PR went south. Lots of errors and a rejection. How is the work flow supposed to go?

pseudo fossil
#

Yes there is a pre commit check before you can create one.

tropic musk
#

right

pseudo fossil
#

You have to fix those before you create a PR

tropic musk
#

telling me "code rejected for formatting error" isn't actionable

pseudo fossil
#

Can you paste the full error. Normally it is very clear

#

Or it auto fixes the style and can just add the changes and try again

tropic musk
#

how can I enable "auto fix"?

pseudo fossil
#

It normally does that

tropic musk
#

I tried to push to a new branch and it got rejected there with no option to fix anything

pseudo fossil
#

Paste the full error message

#

And command

#

Did you fork the repo or just clone it?

tropic musk
#

I tried cloning, creating a new branch and that's where I got rejected

#

so I forked it and the code is sitting in my fork

pseudo fossil
#

Ok good

#

You can't create a PR from your fork?

tropic musk
#

let me try

pseudo fossil
#

You are not an ESPHome maintainer so don't have permissions to create a branch in the actual repo. Have to create one in your fork and create a PR there

tropic musk
#

I need to reset everything, I have different code in the fork

#

creating a new branch on my fork is giving some formatting errors

#
ruff (legacy alias)......................................................Failed
- hook id: ruff
- files were modified by this hook

Found 2 errors (2 fixed, 0 remaining).

ruff format..............................................................Passed
flake8...................................................................Passed
don't commit to branch...................................................Passed
fix end of files.........................................................Passed
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook

Fixing esphome/components/bb_epaper/bb_epaperbase.cpp

pyupgrade................................................................Passed
yamllint.............................................(no files to check)Skipped
clang-format.............................................................Failed
- hook id: clang-format
- files were modified by this hook
pylint...................................................................Passed
Update clang-tidy hash...............................(no files to check)Skipped
#

looks like it tried to fix them

pseudo fossil
#

That looks good

tropic musk
#

branch created

pseudo fossil
#

Perfect, can now create a PR

#

Will have an option there (if you recently pushed) or under your fork

tropic musk
#

the PR was using the wrong branch. Not sure how to make it work now

pseudo fossil
#

It looked fine to me

#

Merging into dev from bitbank2:bb_epaper

tropic musk
#

no, that PR picked up my bb_temp component

#

let me start from a clean fork

#

It's complaining that there's no codeowners in init.py, but there is ??