How to display a slider on a 1.54 inch 128x64 OLED?
Displaying a slider on a 1.54 inch 128x64 OLED involves driving a monochrome graphic display with a microcontroller, typically via SPI or I2C, and implementing a graphical user interface element that responds to user input or sensor data. The core of the task is to render a horizontal bar with a movable indicator, update it in real-time, and manage the OLED’s limited pixel grid. For this, you’ll need a 1.54 inch 128x64 oled display that uses the SSD1306 or SH1106 driver, a 3.3V or 5V microcontroller like an Arduino Uno, ESP32, or STM32, and a library such as Adafruit SSD1306 or U8g2. The slider itself is a set of pixels: a background track, a fill area, and a thumb. The track spans from x=0 to x=127, but you’ll reserve margins for labels or borders. For example, a slider from x=10 to x=117 gives 108 pixels of travel, which maps to a value range like 0 to 100. Each pixel step represents about 0.93 units, so you can interpolate. The key is to handle the OLED’s page-based memory layout—128 columns by 8 pages (each page is 8 pixels tall). To draw a slider, you write pixel data to the display buffer, then call display() to send it over SPI. A typical SPI setup uses pins: CS (chip select), DC (data/command), RES (reset), SDA (MOSI), and SCK. For an Arduino, you’d connect CS to pin 10, DC to pin 9, RES to pin 8, SDA to pin 11, and SCK to pin 13. The OLED’s resolution is 128x64, so a slider height of 8 pixels (one page) is efficient, but you can make it thicker by spanning multiple pages. For a vertical slider, you’d rotate the logic, but horizontal is standard for menus.
The slider’s visual design must account for the OLED’s contrast and refresh rate. The SSD1306 supports 128x64 pixels with a 180-degree viewing angle, 10,000:1 contrast ratio, and a typical frame rate of 30-60 Hz when using SPI at 8 MHz. To avoid flicker, update the buffer only when the slider value changes, not in a loop. Use a debounced button or encoder for input, or a potentiometer on an analog pin. For example, an analog read from 0 to 1023 maps to a slider value from 0 to 100: `int sliderValue = map(analogRead(A0), 0, 1023, 0, 100);`. Then, calculate the pixel position: `int sliderX = map(sliderValue, 0, 100, 10, 117);`. Draw the track as a line from x=10 to x=117 at y=20, height=6, using `display.drawFastHLine(10, 20, 108, WHITE);` for the background, then fill from x=10 to sliderX with `display.fillRect(10, 20, sliderX-10, 6, WHITE);`. The thumb can be a 4x8 rectangle at sliderX, y=18, or a filled circle with radius 3. For a more polished look, use a 2-pixel border and a 1-pixel gap. The OLED’s pixel pitch is 0.22 mm, so the slider occupies about 24 mm of screen width, leaving room for a label like “Volume: 75%” in a 5x7 font. The U8g2 library supports fonts up to 22 pixels tall, but for a 128x64 display, use a 6x8 or 8x13 font to fit text. A 6x8 font gives 21 characters per line, so you can display “Value: 75” in the top row.
Implementing the slider requires a state machine to handle input. For a rotary encoder, track the position with interrupts. On an ESP32, use the PCNT (pulse counter) peripheral for accuracy. The encoder’s resolution is typically 20-24 pulses per revolution, but you can use 4x decoding for 80-96 steps. Map each step to 1 unit of the slider value. For a touch sensor, like a capacitive touch slider, use the TTP229 or a self-capacitance method with an ADC. The ESP32 has a touch sensor peripheral with 10 channels, but the OLED’s I2C or SPI lines can introduce noise—keep traces short and add a 100nF capacitor on the power line. The OLED consumes 20-30 mA at full brightness, so a 3.3V regulator like the AMS1117-3.3 is fine. For a battery-powered project, the OLED’s sleep mode reduces current to 0.1 mA. Use `display.ssd1306_command(SSD1306_DISPLAYOFF);` to enter sleep and wake with `SSD1306_DISPLAYON`. The slider update should be gated by a timer, not a blocking delay. On an Arduino, use `millis()` to check if 50 ms have passed since the last update. This prevents ghosting and saves power.
Data density matters. The slider’s value can be stored as a byte (0-255) or an int (0-1000). For a 108-pixel track, a 0-255 range gives 0.42 pixels per unit, so you’ll need to round. Use `int thumbPos = (sliderValue * 108) / 255 + 10;` to avoid floating-point math. The OLED’s buffer is 1024 bytes (128x64/8), so each page is 128 bytes. Drawing a slider at y=20 (page 2, since page 0 is y=0-7, page 1 is y=8-15, page 2 is y=16-23) means you modify bytes 256 to 383 in the buffer. The `fillRect` function writes to these bytes, but you can optimize by precomputing a mask for the thumb. For example, the thumb at x=50 occupies columns 50-53, which are bits in the buffer. The SSD1306’s RAM is organized as column-major, so column 0 is the first byte of each page. To write a pixel at (x, y), use `buffer[x + (y/8)*128] |= 1 << (y%8);`. This is faster than the library’s generic drawPixel, which loops through the buffer. For a slider, batch updates: write the track once, then only update the thumb and fill area when the value changes. This reduces SPI traffic. At 8 MHz SPI, transferring 1024 bytes takes 1.3 ms, so a 50 ms update interval gives a 2.6% duty cycle. The OLED’s persistence of vision ensures smooth motion.
For a real-world application, consider a 1.54 inch 128x64 oled display used in a thermostat. The slider controls the setpoint temperature from 10°C to 30°C. The track is drawn at y=30, height=10, with tick marks every 10 pixels (5°C steps). The thumb is a 6x10 rectangle. The current temperature is read from a DS18B20 sensor over OneWire, and the slider value is set by two buttons: up and down. Each button press increments or decrements the value by 1, and the display updates the slider and the numeric readout. The debounce time is 50 ms using a software filter. The code uses the Adafruit SSD1306 library with the GFX extension. The setup initializes the OLED with `display.begin(SSD1306_SWITCHCAPVCC, 0x3C);` for I2C, or `display.begin(SSD1306_SWITCHCAPVCC);` for SPI. The loop reads the buttons, updates the slider value, and calls `display.clearDisplay();` then redraws the entire screen. This is wasteful, so instead, only clear the area of the old thumb and fill. Use `display.fillRect(oldThumbX-2, 28, 10, 14, BLACK);` to erase, then draw the new. The old thumb position is stored as a global variable. The track is drawn once in setup, and the fill area is drawn as a rectangle from the track start to the thumb. For a more efficient approach, use a double buffer: draw to a second buffer, then swap. But on an Arduino Uno with 2 KB RAM, the 1024-byte buffer plus a second buffer is tight. The ESP32 has 520 KB, so it’s fine.
The slider’s responsiveness depends on the microcontroller’s clock speed. An Arduino Uno at 16 MHz can handle 1000 slider updates per second, but the OLED’s SPI speed limits it to 769 updates per second (1024 bytes * 8 bits / 8 MHz = 1.024 ms per transfer, plus overhead). In practice, you’ll update at 20 Hz for a smooth feel. The human eye perceives motion at 10-12 Hz, so 20 Hz is adequate. For a touch slider, use a TTP223 capacitive touch module or a self-capacitive electrode. The electrode’s capacitance changes by 1-10 pF when touched, and an ADC reading at 10-bit resolution gives a 0-1023 value. Map that to the slider range. The ESP32’s touchRead() function returns a 0-255 value, but it’s noisy. Apply a moving average filter with a window of 5 samples. The slider’s track can be 100 pixels wide, so the touch position is `touchValue * 100 / 255`. The OLED’s refresh rate must match the touch sampling rate. The ESP32’s touch sensor can be sampled at 100 Hz, so the slider updates at 50 Hz with a 2-sample average.
Power consumption is a factor. The 1.54 inch 128x64 oled display draws 20 mA at 3.3V. The slider’s update rate affects power: updating at 20 Hz with a 1.3 ms transfer time gives a 2.6% duty cycle, so average current is 0.52 mA plus the idle current. The microcontroller’s current is 10-50 mA depending on the clock. For a battery-powered device, use the OLED’s sleep mode and a low-power microcontroller like the ATmega328P at 8 MHz. The slider can be updated only on input, not continuously. Use an interrupt on the button or encoder pin to wake the microcontroller from sleep. The OLED’s sleep mode is entered with `display.ssd1306_command(SSD1306_DISPLAYOFF);` and exited with `SSD1306_DISPLAYON`. The wake-up time is 100 µs, so the slider appears instantly. The total current in sleep is 0.1 mA (OLED) + 0.1 mA (microcontroller) = 0.2 mA, giving a battery life of 500 hours with a 100 mAh coin cell.
The slider’s visual feedback can include a gradient or dithering. The OLED’s monochrome nature means you can’t do grayscale, but you can use a patterned fill for the track. For example, use a 50% checkerboard pattern for the unfilled portion and solid for the filled. The pattern is a 2x2 pixel grid: pixels (0,0) and (1,1) are on, the rest off. This gives a visual distinction without extra memory. The pattern is applied by writing a byte to the buffer: for a 2x2 pattern, use 0x55 for the first row and 0xAA for the second. The track’s height is 8 pixels, so two rows of pattern. The fill area is solid 0xFF. The thumb is a 4x8 rectangle with a 1-pixel border. The border is drawn with `drawRect`, which uses XOR mode if the library supports it. The U8g2 library has a `setDrawColor(2)` for XOR mode, which inverts the pixel. This is useful for a blinking thumb when the slider is selected.
The slider’s range and step size are configurable. For a volume control, use 0 to 100 with 1% steps. For a brightness control, use 0 to 255 with 1-step resolution. The OLED’s contrast can be set via command `0x81` followed by a byte from 0 to 255. The slider can control the contrast: `display.ssd1306_command(SSD1306_SETCONTRAST); display.ssd1306_command(sliderValue);`. This is a direct hardware control. The contrast range is 0 (off) to 255 (max). The slider’s track is drawn at the bottom of the screen, and the contrast value is displayed as a number. The OLED’s contrast affects the slider’s visibility: at low contrast, the slider is dim, so the user can see the effect. This is a practical use case for a settings menu.
The slider’s implementation on a 128x64 OLED is not limited to horizontal bars. You can create a circular slider, but that’s complex. For a 1.54 inch screen, a circular slider with a radius of 30 pixels fits. The angle is mapped to a value. Use `atan2(y, x)` to calculate the angle from the center. The thumb is a 4x4 square at the circumference. The track is a circle drawn with `drawCircle`. This is more computationally intensive, requiring floating-point math. On an ESP32, it’s fine, but on an Arduino Uno, use a lookup table for sin/cos. The circular slider’s resolution is 360 steps, but the OLED’s 128x64 grid limits it to 360 pixels on the circumference, so 1 degree per pixel. The slider value is the angle in degrees. This is useful for a compass or a rotary selector.
The OLED’s SPI interface can be shared with other devices. Use a separate CS line for each device. For example, an SD card and the OLED share the same SPI bus. The slider data is stored on the SD card as a configuration file. The microcontroller reads the file, parses the slider value, and displays it. The slider’s position is updated by the user, and the new value is written back to the file. This is a persistent storage solution. The SD card’s SPI speed is 25 MHz, so the OLED’s 8 MHz is fine. The CS pin for the OLED is pin 10, and for the SD card, pin 4. The slider’s value is stored as a text string: “volume=75”. The Arduino’s SD library reads the line, extracts the number, and maps it to the slider. The write operation uses `file.println(“volume=75”);`. This adds 10 ms to the update time, but it’s only done on button release.
The slider’s user interface can include a label and a value. The label is drawn with `display.setCursor(0, 0); display.print(“Volume”);` in a 6x8 font. The value is drawn at the right side: `display.setCursor(100, 0); display.print(sliderValue); display.print(“%”);`. The font size is 6x8, so 28 characters fit. The slider’s track is at y=16, height=8. The thumb is at y=14, height=12. The total height is 14+12=26 pixels, leaving 38 pixels for the label and value. The OLED’s 64-pixel height is used efficiently. The label and value are updated only when the slider changes, not every frame. This reduces SPI traffic by 50%.
The slider’s input method can be a potentiometer. The potentiometer’s wiper is connected to an analog pin. The ADC reading is 0-1023, but it’s noisy. Use a 10-sample average with a 10 ms delay between samples. The slider’s value is updated every 100 ms. The track is drawn with a 1-pixel border, and the fill area is a solid block. The thumb is a 4x8 rectangle with a 1-pixel border. The potentiometer’s rotation is 270 degrees, so the slider’s travel is 108 pixels. The mapping is linear: `sliderX = map(analogRead(A0), 0, 1023, 10, 117);`. The potentiometer’s resistance is 10 kΩ, and the wiper current is 0.5 mA. The OLED’s power supply is separate, so no interference.
The slider’s performance on a 1.54 inch 128x64 OLED is limited by the display’s refresh rate and the microcontroller’s processing power. The SSD1306’s maximum frame rate is 60 Hz, but the SPI transfer of 1024 bytes takes 1.3 ms, so the theoretical maximum is 769 Hz. However, the library’s overhead adds 2-3 ms per frame, so the practical maximum is 200 Hz. For a slider, 20 Hz is sufficient. The slider’s visual quality is enhanced by anti-aliasing, but the OLED is monochrome, so you can’t do grayscale. Instead, use sub-pixel rendering by shifting the thumb by 1 pixel. The thumb’s position is an integer, so the slider moves in steps of 1 pixel. This is fine for a 108-pixel track. The slider’s value resolution is 0.93 units per pixel, so the user can set values with 1% accuracy.
The slider’s code structure is straightforward. Initialize the OLED, draw the track, then loop. In the loop, read the input, calculate the new position, erase the old thumb, draw the new thumb, and update the fill area. The fill area is drawn from the track start to the thumb. The track is drawn once. The thumb is drawn with `fillRect` and `drawRect`. The value is displayed with `setCursor` and `print`. The code is compact and fits in 10 KB of flash on an Arduino Uno. The RAM usage is 1 KB for the buffer plus 100 bytes for variables. The slider’s state is stored in a struct: `struct Slider { int value; int min; int max; int x; int y; int width; int height; };`. This makes the code reusable. The slider’s range is set in the constructor: `Slider
احجز مقعدك في مقهى العمل الأول في الرياض
واي فاي بسرعة الجيغابت، قهوة مختصة محمصة محلياً، وبوثات هادئة للحجز بالساعة — كل ما تحتاجه ليوم عمل عميق.
احجز مقعدك