This scenario presents how to use the OLED display. Our OLED display is an RGB (16bit colour, 64k colours) 1.5in, 128×128 pixels. The OLED chip is SSD1351, and it is controlled over the SPI interface using the following pin configuration:
As usual, there is no need to program SPI directly; instead, it should be handled by a dedicated library. In addition to the protocol communication library and display library, we will use a graphic abstraction layer for drawing primitives such as lines, images, text, circles, and so on:
lib_deps = adafruit/Adafruit SSD1351 library@^1.2.8
Note that the graphics abstraction library (Adafruit GFX) is loaded automatically because of the
lib_ldf_mode = deep+
declaration in the platformio.ini
. You can also add it explicitly, as below:
lib_deps = adafruit/Adafruit SSD1351 library@^1.3.2 adafruit/Adafruit GFX Library@^1.11.9
To generate an array of bytes representing an image in 565 format, it is easiest to use an online tool, e.g.:
Draw a text on the OLED display and an image of your choice (small, to fit both text and image).
Perhaps you will need to use an external tool to preprocess an image to the desired size (we suggest something no bigger than 100×100 pixels) and another tool (see hint above) to convert an image to an array of bytes.
Check if you can see a full OLED Display in your video stream. Book a device and create a dummy Arduino file with void setup()…
and void loop()…
.
Prepare a small bitmap and convert it to the byte array for 16-bit colour settings.
Sample project favicon you can use is present in Figure 1:
Remember to include the source array in the code when drawing an image. The corresponding generated C array for the logo in Figure 1 is too extensive to present here in the textual form, so below it is just the first couple of pixels represented in the array, and full contents you can download here: ZIPed archive with a C file containing all pixel data of the image .
const uint16_t epd_bitmap_logo_60 [] PROGMEM = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf7be, 0xbdd7, 0x8430, 0x5aeb, 0x39c7, 0x2104, 0x1082, 0x0020, 0x0020, 0x1082, 0x2104, 0x39c7, 0x5aeb, 0x8430, 0xbdd7, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, .... .... 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; // Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 3616) const int epd_bitmap_allArray_LEN = 1; const uint16_t* epd_bitmap_allArray[1] = { epd_bitmap_logo_60 };
Include necessary libraries:
#include <Arduino.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1351.h> #include <SPI.h> //Fonts #include <Fonts/FreeMono9pt7b.h>
The code above also includes a font to draw text on the OLED Display. There are many fonts one can use, and a non-exhaustive list is present below (files are located in the Adafruit GFX Library
, subfolder Fonts
):
FreeMono12pt7b.h FreeMono18pt7b.h FreeMono24pt7b.h FreeMono9pt7b.h FreeMonoBold12pt7b.h FreeMonoBold18pt7b.h FreeMonoBold24pt7b.h FreeMonoBold9pt7b.h FreeMonoBoldOblique12pt7b.h FreeMonoBoldOblique18pt7b.h FreeMonoBoldOblique24pt7b.h FreeMonoBoldOblique9pt7b.h FreeMonoOblique12pt7b.h FreeMonoOblique18pt7b.h FreeMonoOblique24pt7b.h FreeMonoOblique9pt7b.h FreeSans12pt7b.h FreeSans18pt7b.h FreeSans24pt7b.h FreeSans9pt7b.h FreeSansBold12pt7b.h FreeSansBold18pt7b.h FreeSansBold24pt7b.h FreeSansBold9pt7b.h FreeSansBoldOblique12pt7b.h FreeSansBoldOblique18pt7b.h FreeSansBoldOblique24pt7b.h FreeSansBoldOblique9pt7b.h FreeSansOblique12pt7b.h FreeSansOblique18pt7b.h FreeSansOblique24pt7b.h FreeSansOblique9pt7b.h FreeSerif12pt7b.h FreeSerif18pt7b.h FreeSerif24pt7b.h FreeSerif9pt7b.h FreeSerifBold12pt7b.h FreeSerifBold18pt7b.h FreeSerifBold24pt7b.h FreeSerifBold9pt7b.h FreeSerifBoldItalic12pt7b.h FreeSerifBoldItalic18pt7b.h FreeSerifBoldItalic24pt7b.h FreeSerifBoldItalic9pt7b.h FreeSerifItalic12pt7b.h FreeSerifItalic18pt7b.h FreeSerifItalic24pt7b.h FreeSerifItalic9pt7b.h
Add declarations for GPIOs, colours (to ease programming and use names instead of hexadecimal values) and screen height and width. To recall, the OLED display in our lab is square: 128×128 pixels, 16k colours (16-bit 565: RRRRRGGGGGGBBBBB colour model):
//Test configuration of the SPI #define OLED_SPI_MOSI_PIN 15 //DIN #define OLED_SPI_SCLK_PIN 18 //CLK #define OLED_SPI_CS_PIN 11 #define OLED_SPI_DC_PIN 13 #define OLED_SPI_RST_PIN 12 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 128 // 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
Declare an SPI communication and OLED controller objects:
static SPIClass hspi(HSPI); static Adafruit_SSD1351 tft = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &hspi, OLED_SPI_CS_PIN, OLED_SPI_DC_PIN, OLED_SPI_RST_PIN);
Initialise the SPI communication object and the OLED controller object. Then clear the screen (write all black):
pinMode(OLED_SPI_CS_PIN, OUTPUT); hspi.begin(OLED_SPI_SCLK_PIN, -1, OLED_SPI_MOSI_PIN, -1); delay(50); digitalWrite(OLED_SPI_CS_PIN,LOW); tft.begin(); delay(100); tft.fillScreen(BLACK);
Draw a bitmap around the centre part of the screen (screen is 128x128px); please mind that OLED_SPI_CS_PIN
must be LOW
(OLED SPI device controller selected) before executing the following code:
tft.drawRGBBitmap(48,48, epd_bitmap_logo_60, 60, 60);
Drop some additional text on the screen:
tft.setFont(&FreeMono9pt7b); tft.setTextSize(1); tft.setTextColor(WHITE); tft.setCursor(0,10); tft.println("Hello IoT");
Some remarks regarding coordinates:
setFont
sets the base font later used for printing. The font size is given in the font name, so in the case of the FreeMono9pt7b
, the base font size is 9 pixels vertically,setTextSize
sets a relative font scaling; assuming the base font is 9 pixels, setTextSize(2)
will scale it up to 200% (18 pixels); there is no fractal calling here :(,setTextColor
controls the colour of the text: as we have a black screen (fillScreen(BLACK)
), we will use white here, but any other colour is valid,setCursor(X,Y)
sets the text location; note the upper-left corner is 0.0, but that relates to the lower-left corner of the first letter. So, to write in the first line, you need to offset it down (Y-coordinate) by at least font size (relative, also regarding text size calling, if any).println(…)
to print the text is very handy as once executed, setCursor
is automatically called to set the cursor in the next line so you can continue printing in a new line without a need to set the cursor's position explicitly. Use print(…)
to continue printing in the current line.
Besides the functions presented above, the controller class has several other handy functions (among others):
drawPixel(x,y, colour)
draws a pixel in x,y
coordinates of the colour
colour,drawCircle(x,y, radius, colour)
draws a circle in x,y
coordinates with colour colour
and specified radius
(in pixels),drawLine(x1,y1, x2,y2, colour)
draws a line starting from x1,y1
and finished in x2,y2
with given colour
- to draw straight (horizontal or vertical) lines there is a faster option:drawFastHLine(x,y, w, colour)
draws horizontal line that starts from x,y
and of the length w
with given colour
,drawFastVLine(x,y, h, colour)
draws vertical line that starts from x,y
and of the length h
with given colour
,drawRect(x,y, w,h, colour)
draws a rectange starting in x,y
of the width and height w
and h
and with given colour
(no fill),drawTriangle(x1,y1, x2,y2, x3,y3, colour)
draws a triangle using 3 vertexes and of given colour (no fill),You should see the image and the text in the video stream.
The screen is black even if I write to it. What to do?: Check if you have initialised an SPI communication object and pulled the “chip select” GPIO down to LOW before drawing. Follow the code example in this manual: it does work!