An Arduino library for the SH1106 I2C OLED display, for the lower end of the Atmel AVR MCU range that has limited resources. The size is achieved by using libraries that are modular and are size conscious themselves, restricting the featuer list, and eliminating the buffer alltogether.
- Absolutely no buffer
- Minimal RAM (33 bytes) and flash (~2300 bytes) requirement
- Designed for 8-bit AVR devices with limited resources (see Supported Devices)
- Supports hardware and software I2C modes
- Modular design: size will vary based on the features you enable
You must install the following libraries first:
- https://playground.arduino.cc/Main/SoftwareI2CLibrary
- https://github.com/notisrac/TinyPrint
- This library :)
Follow this guide to install them: https://www.arduino.cc/en/Guide/Libraries
This is the minimal code required to make the library work:
// first, we need to define the I2C pins for the softwareI2C lib
#define SDA_PORT PORTC
#define SDA_PIN 4 // = A4 on Arduino UNO
#define SCL_PORT PORTC
#define SCL_PIN 5 // = A5 on Arduino UNO
#include "SH1106Lib.h"
SH1106Lib display;
void setup() {
display.initialize();
display.clearDisplay();
}
void loop() {
// use display.
}
The bare minimum configuration you have to do is telling the SoftI2CMaster what pins to use:
#define SDA_PORT PORTC
#define SDA_PIN 4
#define SCL_PORT PORTC
#define SCL_PIN 5
To confugre the underlying two other libraries, check their readmes:
// displays a white pixel at 10, 10
display.drawPixel(10, 10, WHITE);
// draws a white filled rectangle at 5, 5, with a width of 10 and height of 3
display.fillRect(5, 5, 10, 3, WHITE);
// need to include the font itself
#include "glcdfont.h"
...
// first we tell the lib the font and its properties, that we want to use
display.setFont(font, 5, 7);
// OR
// display.setFont(font_3x5, FONT_3x5_WIDTH, FONT_3x5_HEIGHT, 45, FONT_NUMBERS | FONT_UPPERCASECHARS);
// set whether long text should wrap to the next line upon reaching the end of the display
display.setTextWrap(true);
// set the text front and background color
display.setTextColor(WHITE, TRANSPARENT);
// set where we want to print the text to
display.setCursor(0, 0);
// display the text, using the standard Arduino print methods
display.print(F("Hello world!"));
// need to include the image itself
// created with: https://notisrac.github.io/FileToCArray/
#define BATTERY_HEIGHT 5
#define BATTERY_WIDTH 11
// array size is 11
static const byte battery[] PROGMEM = {
B00011111, B00010001,
B00010001, B00010001,
B00010001, B00010001,
B00010001, B00010001,
B00011111, B00001010,
B00001110
};
...
// display the bitmap at 5, 3, in white, with transparent background
display.drawBitmap(5, 3, battery, BATTERY_WIDTH, BATTERY_HEIGHT, WHITE, TRANSPARENT);
To be able to use your fonts/bitmaps with this library, you need to convert it to a specified format. For this you can use the File to C style array converter like this:
- Load the image into the converter ("Browse...", select image, "Open")
- Set the code format to your liking
- Set the palette mod to 1bit line art
- Tick the Optimize for column read checkbox
- Click "Convert"
- Click "Save as file" OR Click "Copy to clipboard"
- Much slower than a bufferd lib like the U8g2
- Printing text that don't span the page boundary (aka y % 8 == 0) lines are about 50% faster
- Displaying an image that don't span the page boundary (aka y % 8 == 0) lines are about 50% faster
- Plotting individual pixels in large numbers is slow
- If constanty updating a text/image on screen, if the design allows it, set the background to SOLID. This is much faster, than clearing the area with fillRect
- Keep in mind, that enabling functions, and adding your own code can increase the size of the binaries pretty fast. So if you can, choose a uc with at least 8k of program space, just to be on the safe side.
Note: all measurements are made on an Arduino UNO with I2C_FASTMODE on, I2C_HARDWARE, I2C_TIMEOUT = 10 and I2C_MAXWAIT = 10
Library | Prog storage (bytes) | Memory (bytes) | Device support | Comment |
---|---|---|---|---|
U8g2 Page buffer mode (Picture Loop) | 9156 | 581 | Almost all of them | Empty example sketch, with lib and init |
Adafruit_SH1106 | 8726 | 1299 | SH1106 OLED display only | Empty example sketch, init code. This is the Adafruit SSD1306 lib converted to SH1106 |
SH1106LIB (this lib) | 2312 | 33 | SH1106 OLED display only | Empty example sketch, init code, HW I2C support off, tinyprint off |
Below is a list or AVRs that meet the criteria of running this library - based on their flash and the sram sizes! (4 < flash <= 32 or 64 < sram <= 1024) Please see the "Tested" column, whether a uc has been tested with the lib or not!
Product | Program Mem (KB) | SRAM (Bytes) | HW I2C | Tested | Comment |
---|---|---|---|---|---|
ATmega328 | 32 | 2048 | 1 | YES | Arduino UNO, I2C_HARDWARE on/off, I2C_FASTMODE on/off |
ATmega16 | 16 | 1024 | 1 | no | |
ATmega164 | 16 | 1024 | 1 | no | |
ATmega168 | 16 | 1024 | 1 | no | |
ATmega169 | 16 | 1024 | 1 | no | |
ATmega16A | 16 | 1024 | 1 | no | |
ATmega16M1 | 16 | 1024 | 0 | no | |
ATmega16U2 | 16 | 512 | 0 | no | |
ATmega16U4 | 16 | 1256 | 1 | no | |
ATmega32U2 | 32 | 1024 | 0 | no | |
ATmega48 | 4 | 512 | 1 | no | |
ATmega48 | 4 | 512 | 1 | no | |
ATmega8 | 8 | 1024 | 1 | no | |
ATmega88 | 8 | 1024 | 1 | no | |
ATmega8A | 8 | 1024 | 1 | no | |
ATmega8U2 | 8 | 512 | 0 | no | |
ATTINY1607 | 16 | 1024 | 1 | no | |
ATtiny1634 | 16 | 1024 | 1 | no | |
ATtiny167 | 16 | 512 | 1 | no | |
ATtiny40 | 4 | 256 | 1 | no | |
ATTINY402 | 4 | 256 | 1 | no | |
ATTINY404 | 4 | 256 | 1 | no | |
ATTINY406 | 4 | 256 | 1 | no | |
ATTINY412 | 4 | 256 | 1 | no | |
ATTINY414 | 4 | 256 | 1 | no | |
ATTINY416 | 4 | 256 | 1 | no | |
ATTINY417 | 4 | 256 | 1 | no | |
ATtiny4313 | 4 | 256 | 1 | no | |
ATtiny43U | 4 | 256 | 1 | no | |
ATtiny44 | 4 | 256 | 1 | no | |
ATtiny441 | 4 | 256 | 1 | no | |
ATtiny44A | 4 | 256 | 1 | no | |
ATtiny45 | 4 | 256 | 1??? | YES | I2C_HARDWARE off, works with the 1MHz internal clock too |
ATtiny461 | 4 | 256 | 1 | no | |
ATtiny48 | 4 | 256 | 1 | no | |
ATTINY807 | 8 | 512 | 1 | no | |
ATTINY814 | 8 | 256 | 1 | no | |
ATTINY816 | 8 | 512 | 1 | no | |
ATTINY817 | 8 | 512 | 1 | no | |
ATtiny828 | 8 | 512 | 1 | no | |
ATtiny84 | 8 | 512 | 1 | no | |
ATtiny841 | 8 | 512 | 1 | no | |
ATtiny84A | 8 | 512 | 1??? | YES | I2C_HARDWARE off, works with the 1MHz internal clock too |
ATtiny85 | 8 | 512 | 1 | no | |
ATtiny861 | 8 | 512 | 1 | no | |
ATtiny87 | 8 | 512 | 1 | no | |
ATtiny88 | 8 | 512 | 1 | no | |
ATxmega8E5 | 8 | 1024 | 1 | no |
Last updated: 2018.09.23
The constructor
Initializes the display
Sends a single command to the display
- command: the command (byte) that needs to be sent to the device
Sends a single byte of data to the display
- data: the data (byte) that needs to be sent to the device
Clears the display
Displays a filled rectangle
- left: x coordinate of the top left corner of the rectangle
- top: y coordinate of the top left corner of the rectangle
- width: width of the rectangle
- height: height of the rectangle
- color: color of the rectangle
void drawBitmap(uint8_t x, uint8_t y, const byte *bitmap, uint8_t w, uint8_t h, uint8_t color, uint8_t backgroundType)
Draws a bitmap from the program memory to the display
- x: the x coordinate to put the bitmap
- y: the y coordiante to put the bitmap
- bitmap: the byte array representing the image
- w: the width of the image
- h: the height of the image
- color: the color which the image should be displayed (BLACK/WHITE)
- backgroundType: SOLID or TRANSPARENT background
Draws a single pixel on th display
- x: the x coordinate to put the pixel
- y: the y coordiante to put the pixel
- color: the color of the pixel (WHITE or BLACK)
Sets the text cursor to this position
- x: the x coordinate
- y: the y coordiante
void setFont(const unsigned char *font, uint8_t width, uint8_t height, int8_t offset = 0, uint8_t flags = FONT_FULL)
Sets the font to write with
- font: pinter to the array containing the font
- width: the width of the font in pixels
- height: the height of the font in pixels
- offset: signed value to offset the position the character is found in the font
- flags: set of flags describing the properties of the font
// Examples:
// this is an 5x7 full font
display.setFont(font, 5, 7);
// this is a 10x11 font, that only contains numbers
display.setFont(font_10x11, 10, 11, 48, FONT_NUMBERS);
// this is a 3x5 font, that has numbers and upper case characters, but no lowercase or space character
display.setFont(font_3x5, 3, 5, 45, FONT_NUMBERS | FONT_UPPERCASECHARS);
Sets whether the text should continue on the next row, if it has reached the end of the current one
- enableWrap: true to enable, false to disable
Sets whether the text should continue on the next row, if it has reached the end of the current one
- color: the color of the text
- backColor: the color of the background of the text. Set it to TRANSPARENT to have a transparend background
Inherited via TinyPrint Displays a single character
- c: the character to display
- returns: 1
Draws a character on the screen from the font
- x: x coordinate where the character should be displayed
- y: y coordinate where the character should be displayed
- character: The character to display
- color: the color of the character
- backgroundType: SOLID or TRANSPARENT
- BLACK
- WHITE
- SOLID
- TRANSPARENT
- FONT_NUMBERS: the font has numbers
- FONT_UPPERCASECHARS: the font has upper case characters
- FONT_LOWERCASECHARS: the font has lower case characters
- FONT_HASSPACE: the font has a separate character for the space (' ')
- FONT_FULL: a full font (this has all of the above)
// Examples:
// this is a font, that only contains numbers
FONT_NUMBERS
// this is a font, that has numbers and upper case characters, but no lowercase or space character
FONT_NUMBERS | FONT_UPPERCASECHARS
- Write display initialization code
- Implement single pixel drawing
- Implement clearDisplay
- Implement text printing functionality
- Use SoftwareI2CLibrary
- Display bitmaps
- Implement drawLine
- Implement drawCircle
- Implement drawRect
- Put the whole thing into a library format
- Write example codes for lib
- Figure out how the Read Modify Write (RMW) mode works
- Implement fillRect with RMW mode
- Change drawChar to use RMW mode
- Change drawBitmap to use RMW mode
- Do measurements on different devices