Image Slideshow With Ili9341 Display

About the project

This example shows you how to use an ILI9341 display to output a series of images loaded from SD card.

Project info

Difficulty: Easy

Platforms: Espruino

Estimated time: 1 day

License: GNU General Public License, version 3 or later (GPL3+)

Items used in this project

Hardware components

breadboard breadboard x 1
ILI9341 LCD controller ILI9341 LCD controller x 1
114990308  ARM Espruino Pico unpinned 114990308 ARM Espruino Pico unpinned x 1

Software apps and online services

Espruino Web IDE Espruino Web IDE


This example shows you how to use an ILI9341 display to output a series of images loaded from SD card (there's an SD card connector on the back of the display).


  • Put an Espruino Pico into breadboard, with the USB connector facing left
  • Place the ILI9341 into the breadboard as show in the image - directly above the Pico
  • Connect the top-left pin of the Pico (VCC on the LCD) to 3.3v on the Pico
  • Connect the top-2nd-left pin of the Pico (GND on the LCD) to GND on the Pico
  • Now connect the 4 end pins on the LCD (for the SD card) as follows:


Before we can get started, we need to cheat a bit. Espruino can't decode JPEG files on-chip - the display is 320x240 pixels at 16bpp - that's 153600 bytes - which is more RAM than Espruino has in total!

Instead, we're going to store the pictures in a format that Espruino can load directly onto the LCD.

To do that, we need to resize the pictures by 320x240, rotate them (the display is actually 240x320), and convert them to a raw 16bpp RGB565 file formatr.

This is something that you can do with the ImageMagick command-line tools. You just need the command:

  1. convert -size 320x240 -rotate 90 -depth 8 inputfile.jpg
  2. -channel R +level 0,31 -evaluate multiply 2048 +channel
  3. -channel G +level 0,63 -evaluate multiply 32 +channel
  4. -channel B +level 0,31 -evaluate multiply 1 +channel
  5. -channel RGBA -separate +channel
  6. -channel R -evaluate-sequence add +channel
  7. -depth 16 R:outputfile.raw

There's one final step - the display expects 16 bits per pixel, but those bits are sent as two 8 bit bytes. Unfortunately when ImageMagick writes the file, it writes those two bytes in the wrong order so you need to swap them.

On Linux, this is easy:

  1. dd if=outputfile.raw of=fixedoutputfile.raw conv=swab

But on Windows/Mac you may have to find another method.

Once you've got the files sorted, copy them into the root of an SD empty card and put in in the LCD.


Just put the code below into the right-hand side of the Web IDE and click upload. It won't work immediately - you'll have to type save() on the left-hand side to load it and start it working.

Comments are inline

Source Code

  1. /* global variables - as we're going to be directly accessing the display,
  2. we need to remember what the CE and DC pins are */
  3. var gspi = new SPI();
  4. var gce = B14;
  5. var gdc = B10;
  6. // graphics object for display - we don't use this directly, but we could do
  7. // if we wanted to draw text over the image
  8. var g;
  10. // List of our files - loaded at power on
  11. var files = [];
  13. function onInit() {
  14. // Set up SD card - load a list of files
  15. var SPI1 = new SPI();
  16. SPI1.setup({mosi:B5,miso:B4,sck:B3,baud:10000000});
  17. E.connectSDCard(SPI1, B6);
  18. files = require("fs").readdirSync();
  20. // Turn LCD backlight on
  21. A6.set();
  22. // Set up LCD (we're using software SPI to avoid wiring the LCD up properly)
  23. gspi.setup({sck:A7, /*miso:A5, */mosi:B1});
  24. g = require("ILI9341").connect(gspi, gdc, gce, B13, function() {
  25. // When initialised, load an image
  26. nextSlide();
  27. });
  28. }
  30. // Load an image onto the screen
  31. function updateScreen(filename) {
  32. // screen width and height
  33. var x2 = 239;
  34. var y2 = 319;
  35. // this code is copied from the ILI9341 module - we need
  36. // to send pixels directly....
  37. // enable SPI bus for LCD
  38. gce.reset();
  39. // Write the 'window' - this will be the whole screen
  40. gspi.write(0x2A,gdc);
  41. gspi.write(0,0,x2>>8,x2);
  42. gspi.write(0x2B,gdc);
  43. gspi.write(0,0,y2>>8,y2);
  44. gspi.write(0x2C,gdc);
  45. // Now open a file, and copy the contents in
  46. // big chunks onto the LCD
  47. var fd = E.openFile(filename,'r');
  48. var d =;
  49. while (d !== undefined) {
  50. gspi.write(d);
  51. d =;
  52. }
  53. fd.close();
  54. // disable SPI for the LCD
  55. gce.set();
  56. }
  58. // Choose a new image from our list of filenames
  59. function nextSlide() {
  60. var r = (E.hwRand()&0xFFFFFF)%files.length;
  61. // load
  62. updateScreen(files[r]);
  63. // reschedule again in 5 seconds
  64. setTimeout(nextSlide, 5000);
  65. }


Source code


Photo of Espruino


Espruino, Espruino Pico and Puck.js are low-power Microcontrollers that run JavaScript. Espruino is a JavaScript Interpreter for Microcontrollers that is designed to make development quick and easy. The Espruino interpreter is firmware that runs on a variety of different microcontrollers, but we also make Espruino Boards that come with the interpreter pre-installed and are the easiest devices to get started with. However Espruino itself isn't just the interpreter firmware or hardware - there's also the Web IDE, command-line tools, documentation, tutorials, and modules that form a complete solution for embedded software development.


Leave your feedback...