STM_7: Using OLED display

This scenario presents how to use the OLED display connected to the STM32WB55 SoC. 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 pin configuration as described in STM32 node Hardware Reference in Table 1 STM32WB55 Node Hardware Details.

Prerequisites

There is no need to program SPI because the display is connected to the hardware SPI directly, which is handled by a library built in the STMDuino. We will use an SSD1351 display library, and a graphic abstraction layer for drawing primitives such as lines, images, text, circles, and so on:

lib_deps =
  adafruit/Adafruit SSD1351 library@^1.3.2
  adafruit/Adafruit GFX Library@^1.11.9

Note that the graphics abstraction library (Adafruit GFX) can be loaded automatically if the

lib_ldf_mode = deep+

declaration in the platformio.ini is set.

Suggested Readings and Knowledge Resources

To generate an array of bytes representing an image in 565 format, it is easiest to use an online tool, e.g.:

By default, this converter works for monochrome displays!
You need to change “Brightness / alpha threshold:” to “0” and “Draw mode:” to “Horizontal - 2 bytes per pixel (565)”.

Hands-on Lab Scenario

Task to be implemented

Draw a text on the OLED display and an image of your choice (small, to fit both text and image).

Start

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.

Note that when using a conversion tool, the conversion should be done for the 64k colour (16bit) model, not RGB.
The 16-bit model is referenced as “2-bytes per pixel” or so-called “565”.

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:

Figure 1: IOT-OPEN.EU Reloaded favicon 64px x 64px

Steps

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 file containing all pixel data of the image .

const uint16_t epd_bitmap_logo64 [] 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
};

Step 1

Include necessary libraries:

// Libraries
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
 
// Fonts
#include <Fonts/FreeMono9pt7b.h>
 
// Here you can also include the file with the picture
#include "epd_bitmap_logo64.cpp"

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

Step 2

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

// Pins definition for OLED 
#define SCLK_PIN     D13 // It also works with STM numbering style PB_13
#define MOSI_PIN     D11 // It also works with STM numbering style PB_15
#define MISO_PIN     D12 // It also works with STM numbering style PB_14
#define OLED_DC_PIN  D4
#define OLED_CS_PIN  D2  // Doesn't work with STM numbering style
#define OLED_RST_PIN D10 //
 
// Colours 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
 
// Screen dimensions
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 128

Step 3

Declare an OLED controller objects:

Adafruit_SSD1351 oled = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, OLED_CS_PIN, OLED_DC_PIN, OLED_RST_PIN);

Step 4

Initialise the OLED controller object. Then clear the screen (write all black):

  pinMode(OLED_CS_PIN, OUTPUT);
  pinMode(OLED_RST_PIN, OUTPUT);
  oled.begin();
  oled.fillRect(0, 0, 128, 128, BLACK);

Step 5

Draw a bitmap in the left top corner of the screen (screen is 128x128px). The OLED library handles the OLED_CS_PIN automatically.

  oled.drawRGBBitmap(0,0, epd_bitmap_logo64, 64, 64);

Step 6

Write some additional text in the middle of the screen:

  oled.setFont(&FreeMono9pt7b);
  oled.setTextSize(1);
  oled.setTextColor(WHITE);
  oled.setCursor(10,80);
  oled.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).
To speed up screen updating and avoid flickering, you may use a trick to clear the afore-written text: instead of clearing the whole or partial screen, write the same text in the same location but in the background colour.
Using 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),

Result validation

You should see the image and the text in the video stream.

FAQ

The screen is black even if I write to it. What to do?: Check if you have done all the steps shown in the example. Check if you used proper GPIOs to control the OLED display. Follow carefully the code example in this manual: it does work!

Project information


This Intellectual Output was implemented under the Erasmus+ KA2.
Project IOT-OPEN.EU Reloaded – Education-based strengthening of the European universities, companies and labour force in the global IoT market.
Project number: 2022-1-PL01-KA220-HED-000085090.

Erasmus+ Disclaimer
This project has been funded with support from the European Commission.
This publication reflects the views of only the author, and the Commission cannot be held responsible for any use that may be made of the information contained therein.

Copyright Notice
This content was created by the IOT-OPEN.EU Reloaded consortium, 2022,2024.
The content is Copyrighted and distributed under CC BY-NC Creative Commons Licence, free for Non-Commercial use.

en/iot-open/practical/hardware/sut/stm32/emb7_1.txt · Last modified: 2024/04/25 19:17 by ktokarz
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0