Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Areas of the screen not in the rendering area will become lighter in color. #297

Open
lanistor opened this issue Apr 14, 2024 · 30 comments
Open
Assignees
Labels
bug Something isn't working Waiting for feedback If it's in this state more than 2 months without feedback then the Issue/MR will be closed

Comments

@lanistor
Copy link

lanistor commented Apr 14, 2024

Areas of the screen that are not in the rendering area will become lighter in color.

For example, screen is 1024*758, rendering area {x: 550, y: 30, width: 474, height: 60} for several times, the area {x: 76, y: 90, width: 474, height: 668} black color will fade.
Like this:
截屏2024-04-15 01 43 46

No matter how I adjust the voltage, I can't fix this problem.
Is there a way to keep areas' color of the screen that are not in the rendering area unaffected?

Testing environment:

  • board: v5
  • screen: 060XD4
  • waveform: tested epdiy_ED060XC3 and epdiy_ED060SCT, same behavior.
  • UI library: lvgl
  • mode: MODE_DU, using epd_hl_update_area
  • esp idf: release 4.4

Demo code:

epd_poweron();
epd_hl_update_area(&hl, updateMode, temperature, first->area);
epd_poweroff();
@martinberlin
Copy link
Collaborator

My feedback w/Kindle paper white
https://youtu.be/HrZnDrv0QJ8?si=tgrA1ztUJoJH-S-3

@lanistor
Copy link
Author

My feedback w/Kindle paper white

Got it👍

@lanistor lanistor reopened this Apr 15, 2024
@lanistor
Copy link
Author

Areas of the screen that are not in the rendering area will become lighter in color.

For example, screen is 1024*758, rendering area {x: 550, y: 30, width: 474, height: 60} for several times, the area {x: 76, y: 90, width: 474, height: 668} black color will fade. Like this: 截屏2024-04-15 01 43 46

No matter how I adjust the voltage, I can't fix this problem. Is there a way to keep areas' color of the screen that are not in the rendering area unaffected?

Testing environment:

  • board: v5
  • screen: 060XD4
  • waveform: tested epdiy_ED060XC3 and epdiy_ED060SCT, same behavior.
  • UI library: lvgl
  • mode: MODE_DU, using epd_hl_update_area
  • esp idf: release 4.4

Demo code:

epd_poweron();
epd_hl_update_area(&hl, updateMode, temperature, first->area);
epd_poweroff();

@martinberlin Is there a way to avoid color changes in non-rendering areas?

I think if no voltage is applied to an area, its color should not change.

@martinberlin
Copy link
Collaborator

Can you please post some program to replicate this?
I know this happens mostly with SPI epapers. But still never saw it in parallel. It might be that display has some ghosts after partial refreshes, that's why e-readers make a full refresh every 10th or so page turn, but other than that it works good for me.
But it can be that with this particular eink and program does not work for you. At least you should make a repository and post test cases so we can replicate it

@lanistor
Copy link
Author

@martinberlin I found the problem, it was a problem with the code I rewrote.

I'm using below code to replace epd_hl_update_area():

epd_clear_area_cycles(area, 1, _clear_cycle_time);
epd_hl_update_area_directly(&hl, updateMode, temperature, area);

enum EpdDrawError epd_hl_update_area_directly(EpdiyHighlevelState* state,
                                              enum EpdDrawMode     mode,
                                              int                  temperature,
                                              EpdRect              area) {
  assert(state != NULL);
  // Not right to rotate here since this copies part of buffer directly

  bool previously_white = true;
  bool previously_black = false;

  memset(state->dirty_lines + area.y, 1, area.height);

  enum EpdDrawError err;
  if (previously_white) {
    err = epd_draw_base(epd_full_screen(), state->front_fb, area,
                        MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode,
                        temperature, state->dirty_lines, state->waveform);
  }

  for (int l = area.y; l < area.y + area.height; l++) {
    if (state->dirty_lines[l] > 0) {
      uint8_t* lfb = state->front_fb + EPD_WIDTH / 2 * l;  // to
      uint8_t* lbb = state->back_fb + EPD_WIDTH / 2 * l;  // from

      for (int x = area.x; x < area.x + area.width; x++) {
        if (x % 2) {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0xF0) | (*(lbb + x / 2) & 0x0F);
        } else {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0x0F) | (*(lbb + x / 2) & 0xF0);
        }
      }
    }
  }
  return err;
}

This method will clear afterimages and ensure faster rendering speed, but the problem is: the area rendered by this function, will become lighter in color, when other area rendering.

I wan't to rewrite epd_hl_update_area_directly, but not works, such as set state->difference_fb[l * EPD_WIDTH + x] = ((*(lfb + x / 2) & 0x0F) << 4) | (*(lbb + x / 2) & 0x0F); will not work.

Could you tell me the wrong of this function epd_hl_update_area_directly, and how to repair it?

@martinberlin
Copy link
Collaborator

Could you tell me the wrong of this function epd_hl_update_area_directly, and how to repair it?

I don’t really know since I never try to use this myself. I either use the high level library or I push the raw framebuffer and do a hl_update

@lanistor
Copy link
Author

Could you tell me the wrong of this function epd_hl_update_area_directly, and how to repair it?

I don’t really know since I never try to use this myself. I either use the high level library or I push the raw framebuffer and do a hl_update

It should be because of i don't known the rendering logic of epdiy clearly, i havn't got the side effect of this way.

@lanistor
Copy link
Author

lanistor commented Apr 18, 2024

@martinberlin I found the problem, it was a problem with the code I rewrote.

I'm using below code to replace epd_hl_update_area():

epd_clear_area_cycles(area, 1, _clear_cycle_time);
epd_hl_update_area_directly(&hl, updateMode, temperature, area);

enum EpdDrawError epd_hl_update_area_directly(EpdiyHighlevelState* state,
                                              enum EpdDrawMode     mode,
                                              int                  temperature,
                                              EpdRect              area) {
  assert(state != NULL);
  // Not right to rotate here since this copies part of buffer directly

  bool previously_white = true;
  bool previously_black = false;

  memset(state->dirty_lines + area.y, 1, area.height);

  enum EpdDrawError err;
  if (previously_white) {
    err = epd_draw_base(epd_full_screen(), state->front_fb, area,
                        MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode,
                        temperature, state->dirty_lines, state->waveform);
  }

  for (int l = area.y; l < area.y + area.height; l++) {
    if (state->dirty_lines[l] > 0) {
      uint8_t* lfb = state->front_fb + EPD_WIDTH / 2 * l;  // to
      uint8_t* lbb = state->back_fb + EPD_WIDTH / 2 * l;  // from

      for (int x = area.x; x < area.x + area.width; x++) {
        if (x % 2) {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0xF0) | (*(lbb + x / 2) & 0x0F);
        } else {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0x0F) | (*(lbb + x / 2) & 0xF0);
        }
      }
    }
  }
  return err;
}

This method will clear afterimages and ensure faster rendering speed, but the problem is: the area rendered by this function, will become lighter in color, when other area rendering.

I wan't to rewrite epd_hl_update_area_directly, but not works, such as set state->difference_fb[l * EPD_WIDTH + x] = ((*(lfb + x / 2) & 0x0F) << 4) | (*(lbb + x / 2) & 0x0F); will not work.

Could you tell me the wrong of this function epd_hl_update_area_directly, and how to repair it?

@vroland May you help me? I want to get the side effect of this rendering logic, and repair it.

@lanistor
Copy link
Author

@martinberlin I found the problem, it was a problem with the code I rewrote.
I'm using below code to replace epd_hl_update_area():

epd_clear_area_cycles(area, 1, _clear_cycle_time);
epd_hl_update_area_directly(&hl, updateMode, temperature, area);

enum EpdDrawError epd_hl_update_area_directly(EpdiyHighlevelState* state,
                                              enum EpdDrawMode     mode,
                                              int                  temperature,
                                              EpdRect              area) {
  assert(state != NULL);
  // Not right to rotate here since this copies part of buffer directly

  bool previously_white = true;
  bool previously_black = false;

  memset(state->dirty_lines + area.y, 1, area.height);

  enum EpdDrawError err;
  if (previously_white) {
    err = epd_draw_base(epd_full_screen(), state->front_fb, area,
                        MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode,
                        temperature, state->dirty_lines, state->waveform);
  }

  for (int l = area.y; l < area.y + area.height; l++) {
    if (state->dirty_lines[l] > 0) {
      uint8_t* lfb = state->front_fb + EPD_WIDTH / 2 * l;  // to
      uint8_t* lbb = state->back_fb + EPD_WIDTH / 2 * l;  // from

      for (int x = area.x; x < area.x + area.width; x++) {
        if (x % 2) {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0xF0) | (*(lbb + x / 2) & 0x0F);
        } else {
          *(lbb + x / 2) = (*(lfb + x / 2) & 0x0F) | (*(lbb + x / 2) & 0xF0);
        }
      }
    }
  }
  return err;
}

This method will clear afterimages and ensure faster rendering speed, but the problem is: the area rendered by this function, will become lighter in color, when other area rendering.
I wan't to rewrite epd_hl_update_area_directly, but not works, such as set state->difference_fb[l * EPD_WIDTH + x] = ((*(lfb + x / 2) & 0x0F) << 4) | (*(lbb + x / 2) & 0x0F); will not work.
Could you tell me the wrong of this function epd_hl_update_area_directly, and how to repair it?

@vroland May you help me? I want to get the side effect of this rendering logic, and repair it.

It seems the problem of epd_clear_area_cycles.

@vroland
Copy link
Owner

vroland commented Apr 18, 2024

Do you have an image / video of the area that gets lighter? Because to me that sounds a lot like improperly calibrated VCOM. Additionally, you could try if using the ED047TC2 waveform changes anything.

Also, why are you using your own epd_hl_update_area_directly instead of epd_hl_update_area?

@lanistor
Copy link
Author

Do you have an image / video of the area that gets lighter? Because to me that sounds a lot like improperly calibrated VCOM. Additionally, you could try if using the ED047TC2 waveform changes anything.

Also, why are you using your own epd_hl_update_area_directly instead of epd_hl_update_area?

  1. I tried ED047TC2, has same behavior.
  2. I adjusted vcom to a suitable value, so it shouldn't be a problem with vcom.
  3. I use epd_clear_area_cycles + epd_hl_update_area_directly to eliminate afterimages, it will rendering black -> white -> content image, this will clear the afterimage,epd_hl_update_area cannot do this.

And, i tried not using epd_clear_area_cycles + epd_hl_update_area_directly, instead using rendering black -> white -> content image, with epd_hl_update_area , this problem disappears, so i think it may be epd_clear_area_cycles

@martinberlin
Copy link
Collaborator

Please answer this one:

Also, why are you using your own epd_hl_update_area_directly instead of epd_hl_update_area?

I also would like to understand what is the reason to use your own high level update area instead of the one that is already built in

@lanistor
Copy link
Author

Please answer this one:

Also, why are you using your own epd_hl_update_area_directly instead of epd_hl_update_area?

I also would like to understand what is the reason to use your own high level update area instead of the one that is already built in

This way can eliminate afterimages (epd_clear_area_cycles + epd_hl_update_area_directly), while epd_hl_update_area cannot.

@vroland
Copy link
Owner

vroland commented Apr 22, 2024

Can you show a video of both methods? I don't really see why they would behave different, so seeing the outcome would help.

@martinberlin martinberlin added the Waiting for feedback If it's in this state more than 2 months without feedback then the Issue/MR will be closed label Apr 25, 2024
@lanistor
Copy link
Author

Can you show a video of both methods? I don't really see why they would behave different, so seeing the outcome would help.

Before

IMG_9951

After

IMG_9953

Video

https://github.com/lanistor/assets/blob/master/epaper/060XD4_out_paint_area.mp4

@lanistor
Copy link
Author

Can you show a video of both methods? I don't really see why they would behave different, so seeing the outcome would help.

Before

IMG_9951

After

IMG_9953

Video

https://github.com/lanistor/assets/blob/master/epaper/060XD4_out_paint_area.mp4

@vroland Is this helpful for resolving the problem?

@vroland
Copy link
Owner

vroland commented Apr 29, 2024

That makes it more clear, thanks. Curious, I don't really know why that is. I'll mark it as a bug for now and try to reproduce it some time. Do you have a minimal example for reproducing the problem handy?

@vroland vroland added the bug Something isn't working label Apr 29, 2024
@lanistor
Copy link
Author

That makes it more clear, thanks. Curious, I don't really know why that is. I'll mark it as a bug for now and try to reproduce it some time. Do you have a minimal example for reproducing the problem handy?

I made a minimal example : https://github.com/lanistor/epaper-tester

I can reproduct problem with ED060XD4, but cannot reproduct with XC3, XCH, do you have a ED060XD4?

@vroland
Copy link
Owner

vroland commented Apr 30, 2024

Argh, I think I only have an XC3... But I can try my luck.

@martinberlin
Copy link
Collaborator

martinberlin commented Apr 30, 2024

I will check because Lanistor sent me 2 XD4 and still have one around so if I find it I can send it to you in next package 📦
Just checked so far have a 060XCD

@lanistor
Copy link
Author

lanistor commented May 1, 2024

I will check because Lanistor sent me 2 XD4 and still have one around so if I find it I can send it to you in next package 📦 Just checked so far have a 060XCD

As i remembered, i sent you 2 XCD, not XD4. I could send XD4 to @vroland .

@lanistor
Copy link
Author

lanistor commented May 1, 2024

Argh, I think I only have an XC3... But I can try my luck.

@vroland Could you give me your address? I could send you 2 XD4. Here is my email: [email protected].

@lanistor
Copy link
Author

lanistor commented May 9, 2024

Hi, @vroland, @martinberlin,

I found another very interesting performance that will help solve this problem: when the circuit board is powered on again, it will slowly display the last rendered content.
2024-05-10 00 39 19 (1)

Here is a video of my experiment:
https://github.com/lanistor/assets/blob/master/epaper/060XCD_2024-05-10.mp4

The test code for video recording is here https://github.com/lanistor/epaper-tester/tree/test/case-2, the branch is test/case-2.

And here is my experimental using case:

  1. Turn on the power and a black background will appear on the entire screen.
  2. Render the block a few times at the top, then a few times at the bottom
  3. Disconnect the power and then turn it on again. When rendering the top block, the shape of the block will appear at the bottom.
  4. Repeat the above steps, but turn the power off after 3 minutes and then turn it on again. At this time, the shape of the bottom block will fade; if you turn the power on again after 5 minutes, the shape of the bottom block will be almost invisible.
  5. If delay 2000ms between epd_clear_area_cycles and epd_hl_update_area_directly, the problem almost disappeared. The longer the time, the better the effect.
  epd_poweron();
  epd_clear_area_cycles(area, 1, _clear_cycle_time);
  vTaskDelay(pdMS_TO_TICKS(2000));
  epd_hl_update_area_directly(&hl, updateMode, temperature, area);
  epd_poweroff();
  1. I tested the brand new XCD and XCH and both had this problem; on the second-hand XD4, this problem will be more serious.

This is really a very strange behavior. The only explanation I can think of is: the electrode on the back of the screen has a weak capacitance, which stores a small amount of electricity. When the screen is powered on, these weak currents will cause the displacement of the particles. Because the second-hand screen (XD4) has been used for a long time, the capacitance will increase, causing the particle displacement to increase.

I found the problem, but I don't know how to solve it. This problem is really interesting, and it's beyond my knowledge. May you find out the way to resolve this problem?


Another test case

If call epd_push_pixels to push white color instead of calling epd_clear_area_cycles, the old area will became darker than expected. If count of white and count of black are not equal, it will aggravate the problem, but the behavior is opposite (the color becomes darker or lighter).

  // for (int i = 0; i < 10; i++) {
  //   epd_push_pixels(area, _clear_cycle_time, 0);
  // }
  for (int i = 0; i < 10; i++) {
    epd_push_pixels(area, _clear_cycle_time, 1);
  }

Test behavior: (this case branch: test/case-3 ).
IMG_0007

@vroland
Copy link
Owner

vroland commented May 10, 2024

Interesting, looks like this particular display model is very sensitive to residual charge / charge buildup. Maybe if we could dump the on-chip waveform we can fix this? Or we have to experiment with the waveforms we have. But this would be my guess that with the waveforms we have there is some imbalanced charge buildup.

@lanistor
Copy link
Author

Interesting, looks like this particular display model is very sensitive to residual charge / charge buildup. Maybe if we could dump the on-chip waveform we can fix this? Or we have to experiment with the waveforms we have. But this would be my guess that with the waveforms we have there is some imbalanced charge buildup.

I got the knowledge here: #226 (comment) .

@vroland
Copy link
Owner

vroland commented May 16, 2024

@lanistor I got your displays today, now I'm going to try replicating it when I have the time :) I already tried the display with a V7 board, there it didn't behave so different, but I'll try to reproduce it with a V5 board when I have the opportunity.

@vroland
Copy link
Owner

vroland commented May 16, 2024

I tried to compile your example repo and I get an error with idf 4.4.5:

/home/vroland/dev/misc/epaper-tester/components/lvgl_epaper_drivers/lvgl_helpers.c: In function 'lvgl_driver_init':
/home/vroland/dev/misc/epaper-tester/components/lvgl_epaper_drivers/lvgl_helpers.h:48:25: error: 'LV_HOR_RES_MAX' undeclared (first use in this function); did you mean 'LV_HOR_RES'?

Any particular version of the dependencies I need?

@martinberlin
Copy link
Collaborator

Probably a different version of LVGL but here I packed a way to get all in a single git clone call:

https://github.com/martinberlin/lv_port_esp32-epaper/wiki/LVGL-9.0

LV_HOR_RES_MAX & LV_HOR_VER_MAX correspond if I remember well to display Width and Height.

@lanistor
Copy link
Author

lanistor commented May 19, 2024

I tried to compile your example repo and I get an error with idf 4.4.5:

/home/vroland/dev/misc/epaper-tester/components/lvgl_epaper_drivers/lvgl_helpers.c: In function 'lvgl_driver_init':
/home/vroland/dev/misc/epaper-tester/components/lvgl_epaper_drivers/lvgl_helpers.h:48:25: error: 'LV_HOR_RES_MAX' undeclared (first use in this function); did you mean 'LV_HOR_RES'?

Any particular version of the dependencies I need?

@vroland Have you changed the version of lvgl? The default version is v8.3, and it doesn't need the LV_HOR_RES_MAX .

If using the following code to start project, it won't need LV_HOR_RES_MAX, and i can start it correctly on a new folder:

git clone [email protected]:lanistor/epaper-tester.git
cd epaper-tester
git submodule update --init --recursive

idf.py build

And idf 4.4 is OK.

@vroland
Copy link
Owner

vroland commented May 25, 2024

Ok, now it compiles but the screen doesn't update. Maybe I'll have to try with a different board when I have the chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Waiting for feedback If it's in this state more than 2 months without feedback then the Issue/MR will be closed
Projects
None yet
Development

No branches or pull requests

3 participants