Display Analog Value of Potentiometer on SSD1306 OLED using Raspberry Pi Pico
Introduction
Display Analog Value of Potentiometer on SSD1306 OLED using Raspberry Pi Pico- The Raspberry Pi Pico, a microcontroller board based on the RP2040 microcontroller, offers a versatile platform for various electronic projects. Combining it with an SSD1306 OLED display opens up possibilities for real-time data visualization. This article explores how to display the analog voltage values from a potentiometer on an SSD1306 OLED screen using a Raspberry Pi Pico. This project serves as an excellent learning tool for understanding the basics of analog-to-digital conversion, I2C communication, and data display on a screen.
Components Required
*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!
About SSD1306 OLED display
The SSD1306 OLED display is a small, self-luminous display module that uses organic light-emitting diodes (OLEDs) to produce bright and colorful images. It is commonly used in small electronic devices such as smartphones, smartwatches, and digital cameras.
One of the key advantages of the SSD1306 OLED display is its low power consumption. Unlike traditional LCD displays, OLED displays do not require a backlight, which significantly reduces power consumption and extends battery life.
Interfacing SSD1306 Oled and Potentiometer with Pico:
Before we can start displaying the analog value on the OLED, we need to connect the components properly.
To set up your SSD1306 OLED display with the Raspberry Pi Pico, begin by connecting the VCC pin of the OLED display to the 3.3V pin on the Pico. Then, attach the GND pin of the OLED to the Pico’s GND pin. This establishes the power connection for the display. Next, for data communication, connect the SDA pin of the OLED display to the GP16 pin, and the SCL pin to the GP17 pin on the Raspberry Pi Pico. Now, for the potentiometer setup: connect one terminal to the Pico’s 3.3V pin and the other terminal to the GND pin. Finally, attach the middle terminal of the potentiometer to the GP26 pin on the Pico. This configuration allows the potentiometer to feed analog input to the Pico, which can then be displayed on the OLED screen.
Programming the Raspberry Pi Pico
To program the Raspberry Pi Pico Board, we’ll use MicroPython, a variant of Python tailored for microcontrollers. You have the option to use either Thonny IDE or any other IDE for coding and testing the board.
My preference is for Thonny IDE due to its user-friendly interface. The programming process is divided into two primary components:
ssd1306.py
main.py
The rationale behind this division is that the OLED Display initially requires the SSD1306 Driver Code. Consequently, our first step is to write and upload the code for the SSD1306 Driver. Once the SSD1306 Code is successfully uploaded to the Pico board, we can proceed to execute the main.py script.
SSD1306 oled Display driver code:
In Thonny IDE, start by creating a new file and then paste the ssd1306 OLED driver code into it. Afterward, save this file as ‘ssd1306.py‘. In my previous article, I provided a detailed explanation on how to interface the ssd1306 OLED display with the Raspberry Pi Pico, including various methods for library installation. Therefore, I recommend visiting that article for more in-depth information.
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces from micropython import const import framebuf # register definitions SET_CONTRAST = const(0x81) SET_ENTIRE_ON = const(0xA4) SET_NORM_INV = const(0xA6) SET_DISP = const(0xAE) SET_MEM_ADDR = const(0x20) SET_COL_ADDR = const(0x21) SET_PAGE_ADDR = const(0x22) SET_DISP_START_LINE = const(0x40) SET_SEG_REMAP = const(0xA0) SET_MUX_RATIO = const(0xA8) SET_COM_OUT_DIR = const(0xC0) SET_DISP_OFFSET = const(0xD3) SET_COM_PIN_CFG = const(0xDA) SET_DISP_CLK_DIV = const(0xD5) SET_PRECHARGE = const(0xD9) SET_VCOM_DESEL = const(0xDB) SET_CHARGE_PUMP = const(0x8D) # Subclassing FrameBuffer provides support for graphics primitives # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html class SSD1306(framebuf.FrameBuffer): def __init__(self, width, height, external_vcc): self.width = width self.height = height self.external_vcc = external_vcc self.pages = self.height // 8 self.buffer = bytearray(self.pages * self.width) super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB) self.init_display() def init_display(self): for cmd in ( SET_DISP | 0x00, # off # address setting SET_MEM_ADDR, 0x00, # horizontal # resolution and layout SET_DISP_START_LINE | 0x00, SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 SET_MUX_RATIO, self.height - 1, SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 SET_DISP_OFFSET, 0x00, SET_COM_PIN_CFG, 0x02 if self.width > 2 * self.height else 0x12, # timing and driving scheme SET_DISP_CLK_DIV, 0x80, SET_PRECHARGE, 0x22 if self.external_vcc else 0xF1, SET_VCOM_DESEL, 0x30, # 0.83*Vcc # display SET_CONTRAST, 0xFF, # maximum SET_ENTIRE_ON, # output follows RAM contents SET_NORM_INV, # not inverted # charge pump SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, SET_DISP | 0x01, ): # on self.write_cmd(cmd) self.fill(0) self.show() def poweroff(self): self.write_cmd(SET_DISP | 0x00) def poweron(self): self.write_cmd(SET_DISP | 0x01) def contrast(self, contrast): self.write_cmd(SET_CONTRAST) self.write_cmd(contrast) def invert(self, invert): self.write_cmd(SET_NORM_INV | (invert & 1)) def show(self): x0 = 0 x1 = self.width - 1 if self.width == 64: # displays with width of 64 pixels are shifted by 32 x0 += 32 x1 += 32 self.write_cmd(SET_COL_ADDR) self.write_cmd(x0) self.write_cmd(x1) self.write_cmd(SET_PAGE_ADDR) self.write_cmd(0) self.write_cmd(self.pages - 1) self.write_data(self.buffer) class SSD1306_I2C(SSD1306): def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False): self.i2c = i2c self.addr = addr self.temp = bytearray(2) self.write_list = [b"\x40", None] # Co=0, D/C#=1 super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.temp[0] = 0x80 # Co=1, D/C#=0 self.temp[1] = cmd self.i2c.writeto(self.addr, self.temp) def write_data(self, buf): self.write_list[1] = buf self.i2c.writevto(self.addr, self.write_list) class SSD1306_SPI(SSD1306): def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): self.rate = 10 * 1024 * 1024 dc.init(dc.OUT, value=0) res.init(res.OUT, value=0) cs.init(cs.OUT, value=1) self.spi = spi self.dc = dc self.res = res self.cs = cs import time self.res(1) time.sleep_ms(1) self.res(0) time.sleep_ms(10) self.res(1) super().__init__(width, height, external_vcc) def write_cmd(self, cmd): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(0) self.cs(0) self.spi.write(bytearray([cmd])) self.cs(1) def write_data(self, buf): self.spi.init(baudrate=self.rate, polarity=0, phase=0) self.cs(1) self.dc(1) self.cs(0) self.spi.write(buf) self.cs(1) |
main.py:
In Thonny IDE, open another new tab. Copy the code provided below and paste it into the thonny IDE window. Once done, save this file with the name ‘main.py‘.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from machine import Pin, I2C, ADC, Timer from ssd1306 import SSD1306_I2C import utime WIDTH = 128 HEIGHT = 64 i2c = I2C(0, scl=Pin(17), sda=Pin(16), freq=200000) oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Initialize ADC for potentiometer pot_Val = ADC(26) conversion_factor = 3.3 / 65535 while True: reading = pot_Val.read_u16() data = reading * conversion_factor oled.fill(0) oled.text("Voltage: ", 0, 0) oled.text(str(round(data,1)),0,15) oled.show() |
Once the ssd1306.py and main.py codes are saved, click on the run button or simply press the F5 button on the keyboard.
After clicking the run button The SSD1306 OLED Display will start showing the Analog voltage value from the potentiometer.
By rotating the potentiometer, the voltage value will change.
Code Explanation:
This Raspberry Pi Pico code is designed for interfacing with an OLED display and a potentiometer, demonstrating both digital and analog input/output capabilities. The script begins by importing necessary modules and classes: Pin, I2C, ADC, and Timer from the machine module for hardware interfacing, and SSD1306_I2C from the ssd1306 module for controlling the OLED display. Additionally, utime is imported for handling time-related functions, although it’s not explicitly used in this snippet.
The OLED display dimensions are set with WIDTH and HEIGHT variables, corresponding to a standard 128×64 pixel SSD1306 OLED display. The I2C communication interface is initialized using I2C(0, scl=Pin(17), sda=Pin(16), freq=200000), specifying the use of GPIO pins 17 and 16 for the serial clock and data lines, and setting a communication frequency of 200,000 Hz. An oled object is created to interact with the OLED display over this I2C interface.
For analog input, an Analog-to-Digital Converter (ADC) is initialized on GPIO pin 26 using ADC(26). This ADC is used to read the value from a potentiometer. A conversion_factor is defined to convert the raw ADC readings into a voltage value, based on the Pi Pico’s reference voltage of 3.3V.
In the main loop of the code, an infinite loop is created with while True: Inside this loop, the potentiometer’s value is read as a 16-bit unsigned integer using pot_Val.read_u16(). This value is then multiplied by the conversion_factor to obtain the voltage level. The OLED display is first cleared using oled.fill(0), and then the text “Voltage: ” followed by the calculated voltage value, rounded to one decimal place, is displayed on the screen at specific coordinates. The oled.show() function updates the OLED display with this new information.
Overall, this code demonstrates how the Raspberry Pi Pico can be used for reading analog sensor data, processing it, and displaying the results on an OLED screen, making it a useful tool for a wide range of electronic and IoT projects.
Conclusion
In conclusion, displaying analog values on an SSD1306 OLED using a Raspberry Pi Pico is a rewarding and versatile project that combines the power of the Raspberry Pi Pico’s GPIO pins with the visual appeal of the OLED display. By interfacing the Pico with analog sensors and leveraging Python programming, you can create dynamic and informative displays for various applications such as environmental monitoring, home automation, or data visualization.
Throughout this project, you’ve learned how to establish communication with the SSD1306 OLED display, read analog sensor data using the Pico’s ADC, and then format and display that data on the OLED screen. This integration not only provides you with real-time data visualization but also opens up possibilities for further customization and expansion, allowing you to create sophisticated projects with ease.
Related Articles:
Interfacing SSD1306 OLED Display with Raspberry Pi Pico
HC-SR04 Ultrasonic Distance Sensor with Raspberry Pi Pico and SSD1306 OLED: Displaying Measurement