ESP32 OLED Yoda Quote Display – Learn to Code You Must
Here’s a fun little project that builds a Star Wars Yoda inspiration quotes display using an ESP32 and SSD1351 OLED. It’s really easy to replace the images if you’re not a fan of Star Wars. This is a nice little school Computer Science project or an interesting little toy for the Star Wars fan in your life.
The code here could potentially be used on an Arduino Uno, but images like these really gobble up memory, and the Arduino just doesn’t have enough of it. So for graphics heavy Internet of Things devices the ESP32, ESP32 CAM or ESP8266 are better choices.
I believe the ESP32 memory can hold a maximum of 32 128×64 16-bit images. However this wouldn’t need much space for application code. If you need to store more then it would be better to store the images on an SD card, then load them in as required.
Interesting Arduino IDE techniques I show in this video: how to wire up a Waveshare SSD1351 1.5 inch 128×64 OLED to the ESP32, how to display a full colour 16 bit image on a display (without using an SD card), how to choose a random string, and how to display a random image on an OLED, TFT or LCD display, how to put code into an external embedded C header file.
Source Code
The source code is below. Two important notes:
- You need to make a regular sketch file and also add a header (.h) file called quote_images.h. This has to reside in the same folder as the sketch’s .ino file. In the Arduino IDE you can add a file using Sketch > Add File.
- To avoid copyright complications I haven’t included the Yoda images in the quote_images.h. You’ll have to add your own images. Use LCD Image Converter and follow the tutorial in the video to prepare some images suitable for use with the project.
Sketch Code
//Yoda inspirational quotes display for ESP32 and SSD13 #include <Adafruit_GFX.h> #include <Adafruit_SSD1351.h> #include <SPI.h> #include "quote_images.h" // Screen dimensions #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 128 // Change this to 96 for 1.27" OLED. //Many thanks to redditors wi1k1n and roaringmuffin for figuring out the ESP32 pins //These work whereas the suggested pins in Examples/Adafruit SSD1351 library/test do not work //with the Waveshare 1.5 inch RGB OLED module //These must stay like this due to use of hardware SPI #define SCLK_PIN GPIO_NUM_18 // CLK (or use constant SCK) #define MOSI_PIN GPIO_NUM_23 // DIN (or use constant MOSI) //These can be changed to other pins if desired #define DC_PIN GPIO_NUM_2 #define CS_PIN GPIO_NUM_0 #define RST_PIN GPIO_NUM_4 // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, CS_PIN, DC_PIN, MOSI_PIN, SCLK_PIN, RST_PIN); char *quotes[] = { "No! Try not. Do. Or do not. There is no try.", "Always pass on what you have learned.", "Powerful you have become, the dark side I sense in you.", "Train yourself to let go of everything you fear to lose.", "Feel the force!", "Wars not make one great.", "Control, control, you must learn control!", "Always in motion is the future.", "Your path you must decide.", "You must unlearn what you have learned.", "Anger, fear, aggression. The dark side are they.", "Forever gone is the moment that is gone.", "Subscribe to Coding With Brett, you must.",}; #define imageWidth 128 #define imageHeight 64 #define imageXPos 0 #define imageYPos 10 const uint8_t numberOfImages = 7; void setup(void) { Serial.begin(9600); Serial.println("ESP32 is starting up"); Serial.println("TFT screen initialising"); tft.begin(); // You can optionally rotate the display by running the line below. // Note that a value of 0 means no rotation, 1 means 90 clockwise, // 2 means 180 degrees clockwise, and 3 means 270 degrees clockwise. //tft.setRotation(1); randomSeed(12345); } void loop() { uint8_t quoteNumber = random(sizeof(quotes)/sizeof(char*)); tft.fillScreen(BLACK); drawRandomImage(); delay(500); renderQuote(quotes[quoteNumber], WHITE); delay(5000); } void renderQuote(char *text, uint16_t color) { tft.setCursor(0,90); tft.setTextColor(color); tft.print(text); } void drawRandomImage() { uint8_t imageNumber = random(1, numberOfImages); Serial.print("Selected image #"); Serial.println(imageNumber); switch (imageNumber) { case 1: tft.drawRGBBitmap(imageXPos, imageYPos, image1, imageWidth, imageHeight); break; case 2: tft.drawRGBBitmap(imageXPos, imageYPos, image2, imageWidth, imageHeight); break; case 3: tft.drawRGBBitmap(imageXPos, imageYPos, image3, imageWidth, imageHeight); break; case 4: tft.drawRGBBitmap(imageXPos, imageYPos, image4, imageWidth, imageHeight); break; case 5: tft.drawRGBBitmap(imageXPos, imageYPos, image5, imageWidth, imageHeight); break; case 6: tft.drawRGBBitmap(imageXPos, imageYPos, image6, imageWidth, imageHeight); break; case 7: tft.drawRGBBitmap(imageXPos, imageYPos, image7, imageWidth, imageHeight); break; default: tft.drawRGBBitmap(imageXPos, imageYPos, image1, imageWidth, imageHeight); break; } }
quote_images.h Code
static const uint16_t image1[] PROGMEM = {}; static const uint16_t image2[] PROGMEM = {}; static const uint16_t image3[] PROGMEM = {}; static const uint16_t image4[] PROGMEM = {}; static const uint16_t image5[] PROGMEM = {}; static const uint16_t image6[] PROGMEM = {}; static const uint16_t image7[] PROGMEM = {};