# Inky Frame 7.3 burn-in

**URL:** <https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574>\
**Category:** Support\
**Created:** [March 30, 2024, 2:04pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574 "2024-03-30T14:04:11Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [March 30, 2024, 2:04pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/1 "2024-03-30T14:04:11Z")

</div>

(I know e-ink fatigue isn’t mechanically the same as phosphor burn-in, but it’s a useful term for the effect.)

I have an Inky Frame 7.3 that’s been running as an image frame with overlaid date and approximate time (and some sensor graphs, [actually a whole thin-client setup](https://github.com/LionsPhil/inkyframe)), refreshing every ten minutes, for a few months. So that should be a few tens of thousands of refreshes.

This is a particularly drastic photo where it cleared to plain red with some white text because it was showing an error screen while the server it fetches images from was down:

 ![A time (blurred) and clear Saturday 2024-03-30 date as dark artefacting on what should be a plain red background](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/4/4f96c9f932973f3dc82754220b24a0c2558b5cbc.jpeg)

It’s not normally that obvious, and it shakes out a bit if you do lots of manual clear-to-colors, but it’s definitely becoming subtly noticable. I’ve not had much luck finding actual hard specification data on these panels, but I was expecting more like millions of refrshes lifespan from what I’d gleaned—i.e. I wouldn’t be seeing this problem for _years_.

What I _have_ noticed is the way the Inky refreshes the panel is not how I thought e-ink panel refreshes were supposed to work. To pinch a graphic from a completely unrelated bug report elsewhere:

 ![Illustration of e-ink four-stage refresh: from previous image 1, the stages are: inverse of 1 (compensate); a blank color (white); inverse of the new image 2; the new image 2](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/9/9bec71f6a72a28970d436c493187a6984337f48e.png)

The idea as I understand it that e-ink “afterburn” artefacts are a result of the ink in the cells not being pulled back to rest position and residual charges needing to be cancelled out, so first you need to “undo” the first image back to a blank slate. But what the Inky seems to do is draw the inverse of the _new_ framebuffer contents, then flash its way inverting fullscreens to taupe, then draw the new image.

I’m saying “the Inky” instead of PicoGraphics, because it seems the refresh dance is really a single SPIO command once the graphics buffer is filled: [pimoroni-pico/drivers/inky73/inky73.cpp at main · pimoroni/pimoroni-pico · GitHub](https://github.com/pimoroni/pimoroni-pico/blob/main/drivers/inky73/inky73.cpp#L182) (I assume the python version wraps the C++)

```c++
command(DRF, {0}); // start display refresh

```

I went digging for what _might_ be the right panel to try to find an answer, and _if_ I got it right that it’s [https://www.good-display.com/product/442.html](https://www.good-display.com/product/442.html) , looking at their ESP32 sample code, they define this fuction (slightly reformatted for brevity):

```c
void PIC_display(const unsigned char* picData) {
  unsigned int i,j,k;
  unsigned char temp1,temp2;
  unsigned char data_H,data_L,data;
  
   //Acep_color(White); //Each refresh must be cleaned first   
  EPD_W21_WriteCMD(0x10);        
  for(i=0;i<480;i++) { 
    k=0;
    for(j=0;j<800/2;j++) {    
      /* snip converting pixels into data nibbles for forum post brevity */
      EPD_W21_WriteDATA(data);
    }
  } 
  
   //Refresh
    EPD_W21_WriteCMD(0x12); //DISPLAY REFRESH   
    EPD_W21_WriteDATA(0x00);
    delay(1); //!!!The delay here is necessary, 200uS at least!!!     
    lcd_chkstatus(); //waiting for the electronic paper IC to release the idle signal
}

```

So it’s doing the same thing of sending the new image data before the refresh command…but what I don’t is why `//Acep_color(White); //Each refresh must be cleaned first` is commented out. If it wasn’t, that function would do pretty much the same as this one, but where `data` is always plain white, before moving on to _then_ sending the actual image data and doing a second refresh. (Reformatted again slightly:)

```c
void Acep_color(unsigned char color) {
  unsigned int i,j;
  EPD_W21_WriteCMD(0x10);        
  for(i=0;i<480;i++) {
    for(j=0;j<800/2;j++) {
      EPD_W21_WriteDATA(color);
    }
  }
  
  //Refresh
  EPD_W21_WriteCMD(0x12); //DISPLAY REFRESH   
  EPD_W21_WriteDATA(0x00);
  delay(1); //!!!The delay here is necessary, 200uS at least!!!     
  lcd_chkstatus(); //waiting for the electronic paper IC to release the idle signal
}

```

(PicoGraphics also doesn’t do the delay marked with `!!!exclamation marks!!!` before busy-waiting as in this sample code, but I assume all that would cause is an early-return while the panel was still working and the risk of sending it more commands while busy—which doesn’t seem to be happening.)

So in summary:

- What is the **expected refresh-cycle lifespan** of the e-ink panel? Is repainting every 10 minutes simply too aggressive?
- Is the PicoGraphics library refreshing the panel properly? **Should it be clearing to blank, or with a negative of the _existing_ image, first?**
  - If not, would it help to work around this for now by doing a two-stage manual clear, first to a negative image (or plain taupe?), `display.update()`, then to the target image, `display.update()`? At the cost of twice the refresh duration. (Inverting the current PG framebuffer contents in Python may be tricky…)

Thanks!

---

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [March 30, 2024, 2:22pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/2 "2024-03-30T14:22:05Z")

</div>

(When I say “not usually that bad”, this is after some color clears, a couple of days ago:

 ![PXL_20240327_220733236](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/c/c20368ce6d9b820e5c0cb9757d7a835408d51f17.jpeg)  
there’s still visible artefacting from where dates have been there, but it’s more in the “this is the beginnings of a problem” stage than a “my panel is ruined” one.)

---

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [March 31, 2024, 12:17am UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/3 "2024-03-31T00:17:05Z")

</div>

Ok, I [implemented clear-to-taupe-first](https://github.com/LionsPhil/inkyframe/commit/3db3dbd56a9975aa42164619d6f6b945c6b9f82b#diff-5923a33e7b2790c73a2df582c48913ae23b4e389fda00350c2d952e323b8f1f2R488-R492), and it looks like the controller itself is doing the negation of the existing image during the flip phase…that’s consistent with seeing the new image _before_ the plain-taupe phase when doing a single `display.update()`.

Can’t tell if a problem that grew over months is solved yet, but I just caused another beautiful red screen tooling around with the server again, and after a day of double-refreshes it is looking a lot, lot better:

 ![Another beautiful solid-red error screen, now without visible burnt-in date](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/0/0625c691eca97e4ac4b27002467d5924cc1e147a.jpeg)

---

<div class="post-metadata">

**Author:** ![bablokb](https://avatars.discourse-cdn.com/v4/letter/b/ee59a6/32.png) [@bablokb](https://forums.pimoroni.com/u/bablokb)\
**Post date:** [March 31, 2024, 5:33am UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/4 "2024-03-31T05:33:25Z")

</div>

The CircuitPython driver has a specific “clear-the-screen” internal function. I think they send a full white image, do a full refresh and then send the real data. This really slows down updates, but maybe this helps?

---

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [April 2, 2024, 1:58am UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/5 "2024-04-02T01:58:30Z")

</div>

That sounds a lot like what I’m currently doing (clear to taupe, refresh, draw the image, refresh).

Which is still not quite right, because that second refresh does a negative of the target image, _then taupe again_, then a the negative of the image and its final draw. The last two steps are correct, but it’s trying to clear taupe to taupe via the framebuffer contents which are not yet on the screen, which is both unnecessary and wrong (as I understand all of this). :/

---

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [April 14, 2024, 3:41pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/6 "2024-04-14T15:41:08Z")

</div>

I took some recordings of the two update mechanisms, moving from a natural photo scene to synthetic test image with big color blocks (both with overlay), so you can see the transition clearly. (The pause on a plain taupe screen in the middle is the pico doing image decoding.)

**Single-update,** just writing a new image then making a single `update()` call:

[![](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/d/d12d3f3679eea1c6ae53e6852b9f5fdca09fd2fb.jpeg "Inky Frame update: single update") ](https://www.youtube.com/watch?v=NrfZaIO-dH4)

This is what the guides/examples seem to do. But I’m not convinced it’s correct that the display is showing a negative of the synthetic image _before_ it’s cleared to blank—it should be flashing to negatives of the photo scene, right? Which is no longer in PicoGraphics’ memory, and possibly this single-buffer is the root problem.

**Double-update,** which is a taupe\* fill, `update()`, image plot, and then `update()` again:

[![](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/e/eee5231fee5b5f4d0b9b85cce13d25e3d952ec6f.jpeg "Inky Frame update: double update") ](https://www.youtube.com/watch?v=AlhJ8cGuG5c)

This is what I’m using now, and it seems to be a bit healthier at the cost of another 40 second cycle, but it’s still not quite right. After the manual clear, at about 40 seconds, the second `update()` is beginning with attempting to “undo” the new synthetic image that is not yet present, reaches it _own_ clear state around the one minute mark, and _then_ starts the process of flashing negative images of it actually pull the ink into its final state. So it’s both taking longer than it needs to, and possibly not quite keeping charges balanced.

It really looks like `update()` needs to know both the previous and new framebuffer contents, but I’m not sure what the fix is here, because this seems right down in the controller from code spelunking (which is why this is a support forum thread, not a GitHub PR…).

(\* I’ve since switched out white for taupe, given the borders go full white during a clear too.)

---

<div class="post-metadata">

**Author:** ![LionsPhil](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/lionsphil/32/10729_2.png) [@LionsPhil](https://forums.pimoroni.com/u/LionsPhil)\
**Post date:** [August 4, 2024, 3:32pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/7 "2024-08-04T15:32:24Z")

</div>

So apparently from talking to someone who did their PhD research around e-ink displays, the weird update regieme is probably intended and is “pre-imaging” for the new screen contents.

What I _have_ discovered months later is that **this only seems to build up on USB power.** When running from the battery connector, it has now run for months without the double-refresh mitigation without problem; but if I put it back on USB within a dozen refreshes or so it’s starting to get “burn in”.

(Thankfully this also seems to mean it isn’t permanent damage.)

I can only assume there’s some quirk of the Pico staying on all the time (it doesn’t sleep on USB like it does on battery) which is doing ~ something ~ with the panel [controller] too. Go figure. Since the “normal” setup Pimoroni shows for these is running off the battery pack with only USB for initial programming, I suspect that’s why they’ve not encountered this.

Unfortunately I don’t think it’s physically possible to force the board to power off while on USB, but what you can do is splice a USB plug and a JST together. :P

---

<div class="post-metadata">

**Author:** ![bablokb](https://avatars.discourse-cdn.com/v4/letter/b/ee59a6/32.png) [@bablokb](https://forums.pimoroni.com/u/bablokb)\
**Post date:** [August 5, 2024, 4:14pm UTC](https://forums.pimoroni.com/t/inky-frame-7-3-burn-in/24574/8 "2024-08-05T16:14:55Z")

</div>

> [@LionsPhil](#):
>
> Unfortunately I don’t think it’s physically possible to force the board to power off while on USB

Yes it is (if “the board” is the Pico-W). You have to pull the 3V3\_EN pin low. I am actually doing that with a Pico attached to an Inky-Impression (via pico-to-pi adapter).

Pulling the 3V3\_EN low is no option with the InkyFrame. The cable solution is simpler.
