Go Down

Topic: Waveshare e-paper displays with SPI (Read 125711 times) previous topic - next topic

i670684

Thank you.  I moved the setup and loop to the bottom of the file and it compiled ok, though still with a lot of warnings.  I'm now happily working through the examples to explore. 

dave

ZinggJM

Do you know if mirroring is possible?
Yes, after a one day break from those strange posts, I remember again.

GxEPD2 has a method

Code: [Select]
    bool mirror(bool m)


which makes subsequent drawPixel() mirror pixel on the x-axis, when set true (for buffered drawing).

You could have spotted this in the example.
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

teep

Hello,

I am trying to make a Waveshare 4.2inch e-paper module (black / white / red) work with my Arduino MKR 1010 Wifi but did not succeed so far.

Did anybody make it work?

I'm a bit lost with the available libraries (https://github.com/ZinggJM). In the Arduino library manager there seems to be only GxEPD2. Which one do you recommend for the Arduino MKR1010 WiFi?

I tried all three of them, but they all result in an error like this:

Code: [Select]
/Users/tim/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld: GxEPD2_32_U8G2_Fonts_Example.ino.elf section `.bss' will not fit in region `RAM'
/Users/tim/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld: region RAM overflowed with stack
/Users/tim/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/../lib/gcc/arm-none-eabi/4.8.3/../../../../arm-none-eabi/bin/ld: region `RAM' overflowed by 408 bytes
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino MKR WiFi 1010.


Is this panel simply too big, or would it make no difference with a smaller one?

Thanks in advance!

ZinggJM

Hello teep,

easiest is to use GxEPD2.

In GxEPD2_Example you have the file GxEPD2_boards_added.h. In this file you select the display for MKR1000. It should be ok for the RAM available on MKR1000, but you can adapt easily:

Code: [Select]
#if defined(ARDUINO_ARCH_SAMD)
#define MAX_DISPAY_BUFFER_SIZE 15000ul // ~15k is a good compromise
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

lesept

Jean Marc, could you provide some explanation about how to do partial update?

I understand we need to define a zone of the display which will only be updated, using setPartialWindow. Can we define several such zones?
Inside the zone, do we keep the coordinate relative to the entire display or relative to the zone?
In case of several zones, do we need several display loops?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

ZinggJM

Quote
Can we define several such zones?
There is one zone active at any point in time, or else full screen (display.setFullWindow()).
Note that the coordinates are according to the actual rotation at that point in time.

Quote
do we keep the coordinate relative to the entire display or relative to the zone?
relative to the entire display, according to the active rotation.

Quote
In case of several zones, do we need several display loops?
Yes.
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

lesept

#1056
Jan 11, 2019, 11:37 pm Last Edit: Jan 11, 2019, 11:37 pm by lesept
Not sure to understand well. What is the exact syntax for setPartialWindow and the role of each argument?
Can you provide a quote example with for example two zones?
Thanks
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

ZinggJM

#1057
Jan 12, 2019, 06:09 am Last Edit: Jan 12, 2019, 06:16 am by ZinggJM
Not sure to understand well. What is the exact syntax for setPartialWindow and the role of each argument?
Can you provide a quote example with for example two zones?
Thanks
There is an open issue for GxEPD2 that I address in the next release. One point is missing comment for setPartialWindow(). I believe the parameters should be clear, as usual names are used.

Code: [Select]
   // setPartialWindow, use parameters according to actual rotation.
    // x and w should be multiple of 8, for rotation 0 or 2,
    // y and h should be multiple of 8, for rotation 1 or 3,
    // else window is increased as needed,
    // this is an addressing limitation of the e-paper controllers
    void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)


I add a function helloWorldForDummies() to GxEPD2_Example with comments for paged drawng:

Code: [Select]
void helloWorldForDummies()
{
  //Serial.println("helloWorld");
  // most e-papers have width < height (portrait) as native orientation, especially the small ones
  // in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
  // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
  display.setRotation(1);
  // select a suitable font in Adafruit_GFX
  display.setFont(&FreeMonoBold9pt7b);
  // on e-papers black on white is more pleasant to read
  display.setTextColor(GxEPD_BLACK);
  // not really centered, but allmost, should be improved
  uint16_t x = (display.width() - 160) / 2;
  uint16_t y = display.height() / 2;
  // full window mode is the initial mode, set it anyway
  display.setFullWindow();
  // here we use paged drawing, even if the processor has enough RAM for full buffer
  // so this can be used with any supported processor board.
  // the cost in code overhead and execution time penalty is marginal
  // tell the graphics class to use paged drawing mode
  display.firstPage();
  do
  {
    // this part of code is executed multiple times, as many as needed,
    // in case of full buffer it is executed once
    // IMPORTANT: each iteration needs to draw the same, to avoid strange effects
    // use a copy of values that might change, don't read e.g. from analog or pins in the loop!
    display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
    display.setCursor(x, y); // set the postition to start printing text
    display.println("Hello World!"); // print some text
    // end of part executed multiple times
  }
  // tell the graphics class to transfer the buffer content (page) to the controller buffer
  // the graphics class will command the controller to refresh to the screen when the last page has been transferred
  // returns true if more pages need be drawn and transferred
  // returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
  // returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
  // (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
  while (display.nextPage());
  //Serial.println("helloWorld done");
}


See functions helloArduino() and helloEpaper() for setPartialWindow(), these are using 2 zones.
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

ZinggJM

helloWorldForDummies() with getTextBounds() of Adafruit_GFX

Code: [Select]
void helloWorldForDummies()
{
  //Serial.println("helloWorld");
  const char text[] = "Hello World!";
  // most e-papers have width < height (portrait) as native orientation, especially the small ones
  // in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
  // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
  display.setRotation(1);
  // select a suitable font in Adafruit_GFX
  display.setFont(&FreeMonoBold9pt7b);
  // on e-papers black on white is more pleasant to read
  display.setTextColor(GxEPD_BLACK);
  // Adafruit_GFX has a handy method getTextBounds() to determine the boundary box for a text for the actual font
  int16_t tbx, tby; uint16_t tbw, tbh; // boundary box window
  display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh); // it works for 0, 0, fortunately (negative tby!)
  // center the boundary box of the text
  uint16_t x = (display.width() - tbw) / 2;
  uint16_t y = (display.height() + tbh) / 2; // y is base line!
  // full window mode is the initial mode, set it anyway
  display.setFullWindow();
  // here we use paged drawing, even if the processor has enough RAM for full buffer
  // so this can be used with any supported processor board.
  // the cost in code overhead and execution time penalty is marginal
  // tell the graphics class to use paged drawing mode
  display.firstPage();
  do
  {
    // this part of code is executed multiple times, as many as needed,
    // in case of full buffer it is executed once
    // IMPORTANT: each iteration needs to draw the same, to avoid strange effects
    // use a copy of values that might change, don't read e.g. from analog or pins in the loop!
    display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
    display.setCursor(x, y); // set the postition to start printing text
    display.print(text); // print some text
    // end of part executed multiple times
  }
  // tell the graphics class to transfer the buffer content (page) to the controller buffer
  // the graphics class will command the controller to refresh to the screen when the last page has been transferred
  // returns true if more pages need be drawn and transferred
  // returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
  // returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
  // (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
  while (display.nextPage());
  //Serial.println("helloWorld done");
}
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

lesept

Thanks but these are full windows examples. Could you add a way to change for example the word "world" by another word using partial update?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

ZinggJM

Thanks but these are full windows examples. Could you add a way to change for example the word "world" by another word using partial update?
See functions helloArduino() and helloEpaper() for setPartialWindow(), these are using 2 zones.

And they use partial window!

The example will be improved in the next release. But I need time to do this.
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

lesept

Thanks. I was asking here because the examples provided in the library are quite complex due to the fact that you made them sort of "processor agnostic "... :)

Il have a closer look.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

ZinggJM

Thanks. I was asking here because the examples provided in the library are quite complex due to the fact that you made them sort of "processor agnostic "... :)

Il have a closer look.
I might consider to add an example for full buffered graphics only, for users like you.

But then users will complain that this example can't be used with AVR Arduinos, or big e-papers with small STM32F1, or...

GxEPD2 is designed to be easily usable with different processor boards.

And as all adaptation can be done in the application - no need to modify configuration headers - this flexibility is purposely shown in the examples.
No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

lesept

Actually, I'm not really aware of the conditions under which I use the library. I have an ESP32 with 2 e-paper displays, as you know, but I have never dug deep enough to understand if I use them the correct way.

My application has 2 different contexts.
  • One : display time each minute (HH :MM) on one display. I need to update each minute, but only partially.
  • The second will display only 'static' information, mainly weather related, so they don't need to be updated more often than each hour. I can use full display update here.
So I can use some help or advice to better use the partial display.

For example, should I only update the changing digits, or update the entire zone that contains the time? This zone is roughly a quarter of the size of the display.

When experimenting with partial update, I have seen that the new digits are not as black as they were on the first time I displayed them. Is it normal or is there a better way to do this?
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

ZinggJM

Quote
For example, should I only update the changing digits, or update the entire zone that contains the time?
Update the entire zone. This is faster, as only one "fast partial update" is needed. You can even update the whole display with "fast partial update", using setPartialWindow(…) with screen dimension.

Quote
When experimenting with partial update, I have seen that the new digits are not as black as they were on the first time I displayed them. Is it normal or is there a better way to do this?
The demo code for the GDEW029T5 uses the same wavetable as the GDEW0213I5F. But this wavetable may not be optimal for avoiding fading. I have not yet experimented with VCOM values, and experimenting with wavetable modification is outside of the scope of my current work for this. I see fading when powerOff() has not been called after partial update. Calling powerOff() may help, for updates every minute.

You can decide if you rather like a version soon, and maybe later optimization, or wait until I have done more extensive tests.

Did you tell us which is your other e-paper display?


No personal message please; any question may be useful for other users. Use code tags for code. Make links clickable with URL tags. Provide links to the product in question.

Go Up