M5 Paper - please help me understand the canvas

  • The docs - e.g. https://docs.m5stack.com/en/api/m5paper/epd_canvas - list functions and their parameters, but don't give much explanation or context.

    From reading them, I thought that declaring a canvas effectively creates a bitmap which can be displayed on the screen (using pushCanvas).

    However, looking at the examples on the above doc page, I tried something like this:

    M5EPD_Canvas canvas(&M5.EPD);
    void setup() {
        canvas.createCanvas(440, 900);
        canvas.drawString("Flower!", 0, 30);
        canvas.pushCanvas(0, 0, UPDATE_MODE_DU4);
    loop () {
    void loop() {
        sprintf(timeStrbuff, "%02d:%02d:%02d", RTCtime.hour, RTCtime.min, RTCtime.sec);
        canvas.drawString(timeStrbuff, 50, 50);
        canvas.pushCanvas(0, 400, UPDATE_MODE_DU4);

    (There was a bit more to it.)

    I expected that I'd see the flower and initial text filling the screen; then the same thing repeated half way down, with an updating timestamp.

    What I actually see is the flower and initial text filling the screen; then the initial text repeated, and the dynamic timestamp, half way down the screen, with the flower image still visible, but not offset.

    In other words it seems that the canvas operates to clip the drawJpgUrl operation; but it goes direct to the screen, and doesn't actually draw onto the canvas. Whereas the drawString function does seem to draw into the canvas, and then pushCanvas copies that on to the screen (in an additive manner, in other words the text appears on top of the flower image).

    Is this correct? And is this documented anywhere?


  • Replying to my own post: it seems that drawJpgURL only takes effect in setup, not in loop - and the same for drawLine. That seems implausible, so I'm sure I'm doing something wrong. But what??


  • Hello @Hamnet

    two things come to mind.

    Firstly, a canvas is like a preparation area and its content is pushed onto the display with pushCanvas(). However doing that doesn't automatically clear the canvas, so if you add more stuff to the same canvas and push it again, old stuff and new stuff might overlap (depending on the coordinates). If you don't want that you can use canvas.fillCanvas(0) to clear the canvas.

    Secondly, when a canvas is pushed the controller needs some time to actually put the data onto the paper display. So if you push the canvas too quickly the controller simply abandons the previous drawing process and starts over with the new content. And if you do that in a loop nothing ever gets drawn on the paper display. Try adding a delay() to your loop(). You can find some timings for the different update modes here search for this table m5epd_update_mode_t.


  • Yes as @felmue said, canvas is an of screen area in memory that you write to and then the finish designed is transferred to the screen from the canvas. EINK displays are NOT mono displays and do not work the same way. Unlike mono displays eINK displays are slow and need a delay of several seconds between each write to slow the previous write to complete (that is why the screens flash black and white several times each write process.
    Also due to the limitations of the esp32 and eink display, you can not use any jpg files. JPEG files must be of a certain data size and must have a very specific data structure ( I have written about this on numerous occasions) please look them my documents on github for partial information on using the M5 paper and m5ink devices. I have ever written a Christmas themed guide on using them which you can find among my other guides on hackster.io

  • Thanks Felix and @ajb2k3. I've found the root of my problem, which is that I was using a different update mode (DU4) in the loop than in the setup (GC16).

    From this I infer that there are least two buffers in a canvas (one for graphics, one for text); since when I pushed the canvas shifted to a different position, using DU4, it placed the text in a shifted position, but didn't update the graphic.

    Is that correct, and are there more than two buffers?