Low power display for Puck (ST7302)

Posted on
  • The 2.13" (250 x 122 pixel ) reflective display shown below connected to a Puck.js V2.1 has an ST7302 hardware driver. The display is similar to a Sharp Memory Display in that has no backlight and it permits much faster updates than Epaper displays.

    It is also much cheaper than the Sharp displays - I got three from Aliexpress for less than 20 pounds (incl. postage and tax). Just search for ST7302 display.

    In low power mode with frame refresh set to 4Hz, it uses on average 30 microamps. This is a versatile display, in that, in high power mode it can update at a 32Hz frame rate with current consumption still less than 1 milliamp.

    The driver and example code can be found here

  • Nice!

    Did you also try the one that is probably also used on pixl.js? https://www.espruino.com/Pixl.js
    It is ~$5USD thing on aliexpress. Also with low power draw.but forgot how low.

    Just beware the 5V version has regulator that draws much more. Also some of them have SPI font chip that can be removed which draws a bit more power too.

    EDIT: here https://www.espruino.com/Pixl.js#power-u­sage 200uA so not that good

  • Thanks,

    Have not tried that one.
    The pixel.js display is much lower resolution (128x64) and has a backlight so I think this would be a much better display for a Pixl.js V2!

    BTW. I am using HW SPI at 10Mhz to update the display which works well. I am thinking of trying to connect the display to one of my old NRF52832 watches to get the extra flash memory.

    PS.I think the time display above may be adapted from some of your code - look familiar?

  • Thanks for posting that up - I hadn't seen ST7302 before, but they look great! I guess there's no greyscale but given they're higher res I guess dithering is less of a big deal. Have you seen anything physically bigger than 23.548.5mm display area (which looks like the standard one)? As you say they'd make a great display for a new Pixl - the original Pixl's display is around 150uA IIRC

    Just looking at the code you have there - it's a shame to have to implement your own fill/setpixel (even if it's in C). Am I right in thinking it's because the display puts each 2x12 block of pixels next to each other? It's a bit of an odd layout!

    I guess we have the vertical_byte mode that does 1x8 pixel blocks, so it might be possible to do something fancy to turn 3 rows of 8 into 2 rows of 12 when we update the screen - but the 2-column spacing makes even that hard! Anyway, it's not a big deal.

    Would you be interested in adding your code so it can just be pulled in for Espruino?

  • @Gordon I have not seen a bigger display for sale, however, I found this presentation from the manufacturer which refers to larger and even colour displays using the same technology.

    Yes, the C -code is due to the odd layout - its sort of interleaved as well with bit 0 of a 24 bit chunk in one column and bit 1 in the next. There is a good write up here in Technoblogy where I noticed the display.

    It would be great if the fill/setpixels code was included in Espruino in some way as it would make the driver much faster.

    PS Very happy for the ST7302 module to be included in the Espruino module library although not sure how that works with embedded C.

  • Thanks - those links look really neat - looks like ST7301/ST7303 should also be capable of greyscale. I guess given these are only on aliexpress and not eBay yet they must be quite new, but it sure sounds from that presentation like we should see a lot more screens appearing soon (although that's dated 2018!).

    How does the display actually look compared to something like a Memory LCD? Does it look just like a 'normal' black and while LCD like you might find on the Pixl, just it's super low power?

    I'm sure there are some hacks we can do to get the data in the right format - for instance I think this should work - although not having a display here at the moment I can't be sure:

    g = Graphics.createArrayBuffer(250,128,1,{ms­b:true});
    g.flip = function() {
      function interleave(x) { "jit"
        // We have a 24 bit number, which is the 2x columns of 12 pixels
        // If we can interleave them, we should be good, so use:
        // https://graphics.stanford.edu/~seander/b­ithacks.html#InterleaveBMN
        var y = x>>12;
        x = x&0xFFF;
        x = (x | (x << 8)) & 0xFF00FF;
        x = (x | (x << 4)) & 0x0F0F0F;
        x = (x | (x << 2)) & 0x333333;
        x = (x | (x << 1)) & 0x555555;
        y = (y | (y << 8)) & 0xFF00FF;
        y = (y | (y << 4)) & 0x0F0F0F;
        y = (y | (y << 2)) & 0x333333;
        y = (y | (y << 1)) & 0x555555;
        return x | (y << 1);
      var t = Graphics.createArrayBuffer(12,250,1,{msb­:true});
      for (var y=0;y<122;y+=12) {
        var b = new Uint24Array(t.buffer);
        // output t.buffer

    Having said that, even that takes 2.5 sec to render (0.5s is drawImage). How fast is your current code with the inline c?

    You could do a similar thing without the intermediate image, using a graphics with vertical_byte and then inline C to take two columns of 12 pixels and interleave them, but that still means having to use inline C so it's not that much better than your current solution (if at all).

    I should add that if JIT gets better (for example by handling integer operations as ints rather than by sending them off to the JS maths lib) the code above should work quite well. It's just not great at the moment

  • The display background is not as white as an Epaper display but it is very clear and the background is similar to that in the original Kindle. It is not as "dull green" looking as the Pixel or old Nokia displays look in some lights. I do not have a Pixel so that is from photos!

    The current code is useable in that it takes 550ms to draw the clock and widgets on the screen shown above of which only 10ms is need for the g.flip() call. Clearing the screen i.e. g.clear();g.flip() takes only 30ms. So a lot of the time in drawing text is probably the Espruino interpreter calling the C setPixel() routine.

    I will try your ingenious code above to see if it works:-)

    BTW: I want to try to see how using the screen as a Terminal might work. I have built a version of the PUCKJS firmware with the TERMINAL module but I cannot see a way to set the graphics instance that Terminal uses. It seems to assume it is built in. Is there a way of setting the instance from Espruino?

  • Thanks! That's interesting then - I guess 550ms isn't too painful. It's a lot better than my JS-only solution!

    Is there a way of setting the instance from Espruino?

    I just looked at the code, and I think what you need is here: https://github.com/espruino/Espruino/blo­b/master/libs/graphics/jswrap_graphics.c­#L579-L583

    So all you need is global["\xff"].gfx = g and I think that'll do it?

  • That works great - many thank s- I did not know you could access the hidden root that way!

    I tried another version of the ST7302 driver which uses an image buffer in addition to the screen mirror buffer. This version only copies the updated part of the image buffer into the screen buffer put still blits the whole screen buffer in g.flip.

    This version reduces 550ms to 146ms which is much more useable and has better power consumption at the expense of the additional 4000 byte buffer.

    The new version is in the repository here. I am sure the update function can be optimised using some of your bithack code.

  • Cool stuff, will try to order some.

  • Just to say I got one here and connected it up and it works great with your driver!

    As you say, 146ms is definitely pretty usable as far as updates go

  • I've just tested with a Puck.js with same pin config and ST7302 V2 driver. It works like a charm. Seems that this display would be really suited for outdoor use (as it is a reflective display). The higher resolution is really a plus. thank you for sharing your work!

  • Happy it works for you. I have just updated the ST7302 V2 driver with a version that improves performance at the expense of a more complex C update function. It now takes 128ms to render rhe example with g.flip now taking 31ms (it was 49 ms in the previous version).

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Low power display for Puck (ST7302)

Posted by Avatar for jeffmer @jeffmer