OLED SH1106 I2C Examples
Welcome to the SH1106 Lab
In this lab, you will use an SH1106 OLED display with the Inter-Integrated Circuit (I2C) connection. You will show text, count numbers, animate a moving box, and even bounce a ball!
We use small Organic Light-Emitting Diode (OLED) displays in many of our labs because:
- They are inexpensive — about $4 each.
- They are easy to connect via I2C. You only need four wires: GND, VCC, Clock, and Data.
- They have a large area to show feedback. Most are 128 x 64 pixels.
- Once you get the driver installed, they are easy to program. You only need to set up the device and run
oled.fill(),oled.text(), andoled.show(). - OLEDs keep high contrast even when batteries get low. Liquid Crystal Displays (LCDs) can look dim as batteries drain, but OLEDs stay bright.
- There is plenty of sample code and tutorials online.
The first step is to find out which graphics chip is inside your OLED. This page covers the SH1106 chip.
SH1106 Example
This is the simplest program you can write for an SH1106 display. It shows the text "CoderDojo" on screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
What each line does:
from machine import Pin, I2C— loads only the parts of the machine library you need.import sh1106— loads the SH1106 display driver.sda = machine.Pin(0)— names the data wire pin (GPIO 0).scl = machine.Pin(1)— names the clock wire pin (GPIO 1).i2c = I2C(0, ...)— creates the I2C bus. The number 400000 sets the speed (400,000 signals per second).display = sh1106.SH1106_I2C(128, 64, i2c, Pin(4), 0x3c)— creates the display object.0x3cis the address of the display in hexadecimal.display.sleep(False)— wakes up the display. Some displays start in sleep mode.display.fill(0)— fills the screen with black (0 = off).display.text('CoderDojo', 0, 0, 1)— draws the text.0, 0is the top-left corner.1means white.display.show()— sends everything to the screen. Nothing appears until you call this!print('done')— shows a message in the console when the program ends.
Monty's Tip
Always call display.fill(0) before drawing new things. This clears the old image. Without it, old pixels stay on screen and make everything look messy.
Counter Example
In this example, you will update the display 50 times. A counter counts from 1 to 50. There is a short pause between each update so you can watch it count.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
What each line does:
1–6. Setup lines — same as above, setting up the I2C bus and display.
7. for i in range(1, 51): — runs the loop 50 times. i starts at 1 and goes up to 50.
8. oled.fill(0) — clears the screen each time through the loop.
9. oled.text('CoderDojo Rocks!', 0, 0, 1) — draws a title at the top.
10. oled.text(str(i), 40, 20, 1) — draws the counter number. str(i) turns the number into text. 40 moves it right. 20 moves it down.
11. oled.show() — sends the new image to the screen.
12. utime.sleep(0.1) — pauses for 0.1 seconds (100 ms) between updates.
Animated Box
This example draws a title and a border rectangle. Then it draws a small filled box that slides from left to right across the display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
What each line does:
1–7. Setup lines — load libraries and set up the I2C bus and display.
8. display.fill(0) — clears the screen.
9. display.text(...) — draws the title.
10. display.hline(0, 9, 127, 1) — draws a horizontal line. Arguments are: x start, y position, length, color.
11. display.vline(0, 10, 32, 1) — draws a vertical line. Arguments are: x position, y start, height, color.
12. for i in range(0, 118): — loops 118 times, one step for each pixel position.
13. display.fill_rect(i, 10, 10, 10, 1) — draws a filled white rectangle. Arguments are: x, y, width, height, color.
14. display.fill_rect(10, 21, 30, 8, 0) — draws a black rectangle to erase the old number.
15. display.text(str(i), 10, 21, 1) — draws the current position as a number.
16. display.show() — sends the new frame to the screen.
Key Idea
Animation on a display works just like a flip-book. You draw a new image, show it, then clear and draw the next one. Do this fast enough and it looks like smooth motion!
Bounce on the SH1106 Display using I2C
This example shows a small ball bouncing around inside a border rectangle. The ball changes direction when it hits any edge.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
What each line does:
1–7. Setup — loads libraries and creates the I2C bus and display.
8. oled.fill(0) — clears the screen.
9–13. border() function — draws four lines that form a rectangle around the edges.
14–19. draw_ball() function — draws or erases the ball one pixel at a time. The state argument is 1 for white and 0 for black.
20. border(width, height) — calls the function to draw the border.
21–25. Starting values — sets the ball's starting position and direction.
26. while True: — loops forever until you stop the program.
27. draw_ball(..., 1) — draws the ball in white.
28. oled.show() — sends the frame to the screen.
29. draw_ball(..., 0) — erases the ball before moving it.
30–37. Edge checks — reverses the direction when the ball reaches a wall.
38–39. Position update — moves the ball one pixel in the current direction.
SH1106 References
Great Work!
You made text, a counter, a sliding box, and a bouncing ball! You are now an OLED animator. Next, try changing the ball size or speed to make it your own!