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).

  • Just a note to say I finally got an ST7301 400x300 LCD working. I don't have a datasheet (do you have one?) but I just used your exact code, changed the window (0x2A/2B) for writing and write 2 bits per pixel, and it works!

    Ideally I'd know what I'm setting everything to though as I assume I need to adjust all the voltages to get greyscale on it (which it should do). I can get something that looks a bit different but it's not grey :)

  • I have only got the datasheet for the ST7302 which I have attached. I did not manage to get hold of a ST7301, what is the physical size?

    1 Attachment

  • Thanks - yes, that's the datasheet I used - but I could really do with a bit more info about how the greyscale is handled on ST7301 (I think there are different modes).

    It was this one: https://www.aliexpress.com/item/10050053­00414591.html - KD042WQTMN001

    So not super cheap, but not bad one-off (although you need an FPC breakout) for it.

    It's a really nice display though. Around 85x65mm viewable area, with maybe a 3mm border. When running in the low power more I reckon it's using about 100uA or less, and it's really sharp.

    I'm seriously considering it for a new Pixl.js type device assuming I can get them in quantity cheap enough.

  • Ok, so I finally got the 2 bit color working rather than just black and white on it. The pixels go:

    x0y0b0 x1y0b0 x0y0b1 x1y0b1
    x0y1b0 x1y1b0 x0y1b1 x1y1b1

    So the two bits of color aren't even next to each other!

    I was expecting greyscale, but what I actually got was better. You get cyan and red, and then I guess the two mix to make black.

    So you could kind of use it to antialias text and it wouldn't notice, but you actually get colour!

    1 Attachment

    • IMG_20240422_120317.jpg
  • That looks really nice, a new Pixl with this display, NRF52840 and some extra flash would be very attractive.

  • Great job, it looks nice!
    For such a display, it would be worth having a way of using it as a connected dashboard like some used in Home Assistant but in Bluetooth instead

  • it would be worth having a way of using it as a connected dashboard

    Yes, I know. I wanted to make an 'Espruino' integration for Home Assistant so that you could connect and send data to Espruino devices via Bluetooth, but I haven't got around to it yet.

    But I think if I make a new board with this, I'd stick WiFi on it anyway. It'll be a bit more expensive because of the display anyway, and even if it's not used by some people being able to connect to a WiFi network would be super helpful

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

Low power display for Puck (ST7302)

Posted by Avatar for jeffmer @jeffmer