epd_display icon indicating copy to clipboard operation
epd_display copied to clipboard

Support for epd3in7

Open aaronr8684 opened this issue 2 years ago • 10 comments

I have a 3.7 HAT screen and would love to add support. Would you prefer a modified version of the standard Waveshare py file (modify the actual functions) or an inline interface file that can handle the function calls between the two?

In short, I would love to get this working with my 3.7 screen and am willing to do the work to make that happen. I'm just looking for a preferred direction (if you have one).

aaronr8684 avatar Feb 06 '22 05:02 aaronr8684

@aaronr8684 That's a good question. This sounds great.

What's involved in modifying the 3.7" epd driver? I'm trying to avoid maintaining and patching waveshare's epd libraries if I can avoid it.

Right now I pull in the waveshare repo and add it to the project with a few patches. Tell me more about what you think would be the most sustainable so it's easy to keep pulling in the WaveShare Repo on demand.

txoof avatar Feb 06 '22 21:02 txoof

@txoof I still need to test this to confirm, but I think the incompatibility lies in a few minor differences that are unique to the 3.7 library (and a few others). I believe adding a few default values to the extra "mode" property of the init() and Clear() functions and creating a simple display() function that calls the display_1Gray() function should be all that's required. It would obviously decrease the available functionality of the screen, but it would work as a simple black/white screen with your project. Maybe adding grey-scale and color support can be a future feature I can work on ;)

As far as the actual fix and after looking through your epdlib library, I think the most compatible short-term fix would be to create an if statement in the _load_non_hd method on line 448 of your Screen class to handle the few non-standard screens prior to looking for the waveshare files and import a subclass created in your project of those few incompatible screens that could use the standard calls that your library expects and provide defaults to the extra properties or function naming differences that aren't in most of the other screen drivers. That would prevent you needing to make changes to the waveshare code every time they provide an update to the library and you could continue to pull the repo as you are now. I'm open to alternative fixes if you can think of a better approach.

Long term, I think a more elegant solution would be to submit a pull request to the official waveshare library to include default values in the few functions that use non-standard properties or function names. However, based on the response time of some of the other issues and PRs in their library, I think it could be a while before those changes are accepted.

Let me know what you think.

aaronr8684 avatar Feb 06 '22 22:02 aaronr8684

@txoof So I was able to get the screen working with the following changes to the epd3in7.py file.

Line 141: Add a default value for mode of '0' in the init method. Mode 0 is the greyscale full-refresh mode of the screen. You can still treat it as a 2 value screen, but it forces the full update between plugin changes.

Line 239-262: Pass the functionality for the getbuffer method to the getbuffer_4Gray method

Line 301: Add a display method that calls the display_4Gray method

Line 409: Add default values for the mode ('0') and color ('0xFF'). The color property isn't actually being used, but I've noticed in other drivers that the color is used in the send_data method on line 420, so I made that change, but in practice, this change has no effect on the result.

So now that I have the screen working, I'm going to move these changes into an external file. If that works as expected, we can look at how you'd like to integrate the changes into your project and what changes in logic are needed in the epdlib classes to support that change.

aaronr8684 avatar Feb 07 '22 17:02 aaronr8684

Here's what I came up with:

import logging
from . import epd3in7

# Copy consts and class over
EPD_WIDTH       = epd3in7.EPD_WIDTH
EPD_HEIGHT      = epd3in7.EPD_HEIGHT

GRAY1  = epd3in7.GRAY1
GRAY2  = epd3in7.GRAY2
GRAY3  = epd3in7.GRAY3
GRAY4  = epd3in7.GRAY4

EPD = epd3in7.EPD 

logging.debug("Overloading epd3in7.py methods for epdlib compatibility")
# Save old methods for calling later
original_init = EPD.init
original_Clear = EPD.Clear

# Redefine methods for epdlib compatibility
def init(self, mode=0):
    original_init(self, mode)

def getbuffer(self, image):
    return self.getbuffer_4Gray(image)

def display(self, image):
    self.display_4Gray(image)

def Clear(self, color=0xFF, mode=0):
    original_Clear(self, color, mode)  

# Overload or add methods to original class
EPD.init = init
EPD.getbuffer = getbuffer
EPD.display = display
EPD.Clear = Clear
logging.debug("Overloading epd3in7.py completed")

I put it in a file named epd3in7patch.py in the waveshare_epd directory and set the "display_type" variable in paperpi.ini to the new filename. Seems to work great.

aaronr8684 avatar Feb 07 '22 21:02 aaronr8684

@aaronr8684

That's great news!

I'm wondering how to get this into the paperpi/waveshare_epd directory whenever it's updated. Right now there's a script that pulls down the waveshare repo and fixes up some incompatibility issues in other modules.

I see a few options:

  • store epd3in7patch.py somewhere outside of the waveshare directory (maybe patches?) and then add a line to update_waveshare.sh script that copies it in.
    • the dirtiest, but definitely the easiest solution and follows the pattern of how I handle the other weird modules
  • move this into library and find some way of patching this on the fly
    • I'm not even sure where to begin with this
  • work this back into epdlib so it's a little more flexible for handling different paths for waveshare modules
    • this sounds like a lot of effort, but will probably be the cleanest later on

What do you think? I favor working this into epdlib, but I don't really have the time to do that now.

txoof avatar Feb 08 '22 19:02 txoof

@txoof

So I wonder if the best solution now would be to add a patched list in epdlib's Screen class (in the _load_non_hd() method) around line 445. That could have a list (really just the 3.7" and 1.02" screens) that would check for a patch file in this library. We could put the patched files in a folder called something like "epd_patches" at the same level as the waveshare folder, but not in it (to avoid update issues). That would get the screen(s) working out of the box for now with relatively little effort.

Then more effort could be put into adding official support through a PR in the official drivers on Waveshare's GitHub or, maybe a better solution, adding the Omni EPD module into your epdlib module. That would add additional compatible screens (Inky) to your project and probably make it easier to add greyscale and color support moving forward.

For right now, I can submit the two PRs (one per repo) if you want to take a look at that option. It should only be a few lines of code per PR. I'll test the changes in the py files on my devices and then move the code over the ipynb files for the PRs.

aaronr8684 avatar Feb 09 '22 02:02 aaronr8684

As the other guy that owns a epd3in7 I appreciate the effort (even if I can barely follow along what's going on). If you need someone to test something . . I am available.

ZubaZ21 avatar Feb 22 '22 23:02 ZubaZ21

Thanks for the offer. I will definitely take you up on that. Right now, I'm working on bringing in a 3rd party library that abstracts the display handling which should allow for more display support in the future (including the 3.7" and the Inky screens from Pimoroni) and more advanced modes like grey scale and color.

Do you have any other screens or just the one? Are you running them on a Pi or something else?

aaronr8684 avatar Feb 22 '22 23:02 aaronr8684

@aaronr8684 I also have a 7.5inch e-Paper HAT V2 (running VSMP+)

ZubaZ21 avatar Feb 22 '22 23:02 ZubaZ21

Hi New user I have a 3in7 HAT I was wondering if this ever got fixed and if there is a resolution?

stumpey121 avatar Oct 14 '22 21:10 stumpey121

No solutions for the 3.7. We kind of stalled out on development for this. I don't have a 3.7" to test with.

@aaronr8684 have you made any progress?

txoof avatar Oct 17 '22 19:10 txoof

Yea I don't think I got to a stable point in the code with this and my job changed quite a bit and has kept me pretty busy from side projects. I have been meaning to pick this back up and work on it a bit. Maybe I can take a look at it over the next few weeks.

@stumpey121 If you are at all familiar with python, I would recommend the work-around that I was able to figure out above. That will get you up and running pretty quickly. It's really not that bad of a fix.

Work-around:

Here's what I came up with:

import logging
from . import epd3in7

# Copy consts and class over
EPD_WIDTH       = epd3in7.EPD_WIDTH
EPD_HEIGHT      = epd3in7.EPD_HEIGHT

GRAY1  = epd3in7.GRAY1
GRAY2  = epd3in7.GRAY2
GRAY3  = epd3in7.GRAY3
GRAY4  = epd3in7.GRAY4

EPD = epd3in7.EPD 

logging.debug("Overloading epd3in7.py methods for epdlib compatibility")
# Save old methods for calling later
original_init = EPD.init
original_Clear = EPD.Clear

# Redefine methods for epdlib compatibility
def init(self, mode=0):
    original_init(self, mode)

def getbuffer(self, image):
    return self.getbuffer_4Gray(image)

def display(self, image):
    self.display_4Gray(image)

def Clear(self, color=0xFF, mode=0):
    original_Clear(self, color, mode)  

# Overload or add methods to original class
EPD.init = init
EPD.getbuffer = getbuffer
EPD.display = display
EPD.Clear = Clear
logging.debug("Overloading epd3in7.py completed")

I put it in a file named epd3in7patch.py in the waveshare_epd directory and set the "display_type" variable in paperpi.ini to the new filename. Seems to work great.

aaronr8684 avatar Oct 17 '22 20:10 aaronr8684

Hi I stalled out and took the easy root and swopped out for a 2in7 :)

But I do have a pi zero in the spares box so i will fire that up and try the fix :)

Thanks for coming back

Steve

stumpey121 avatar Oct 17 '22 20:10 stumpey121