Skip to content

Home/Article

Field Notes · Donat Mg

How to use a 1.77 inch TFT with a MicroPython board?

How to use a 1.77 inch TFT with a MicroPython board

You can drive a 1.77 inch TFT display with a MicroPython board by connecting its SPI interface to the board’s hardware SPI pins, initializing the display driver library, and sending pixel data for rendering graphics or text. The specific steps depend on your board model (like Raspberry Pi Pico, ESP32, or STM32) and the display’s controller chip—most 1.77 inch TFTs use the ST7735S or ILI9163C driver, which are well-supported in MicroPython. For a typical setup, you’ll need four SPI lines (SCK, MOSI, DC, CS) plus a reset pin and a backlight control pin. The display resolution is 128x160 pixels, with a 16-bit color depth (RGB565 format), meaning each pixel requires 2 bytes, so a full frame buffer is 128 * 160 * 2 = 40,960 bytes. On a Raspberry Pi Pico with 264KB RAM, that’s fine, but on an ESP8266 with only 80KB usable RAM, you’ll need to use partial buffer updates or a driver that writes directly to the display without a full buffer. The SPI clock speed can go up to 20 MHz for smooth updates, but start with 10 MHz to avoid signal integrity issues on breadboard wiring. You’ll also need to set the correct display orientation and color order—most ST7735-based displays default to BGR color order instead of RGB, which will make red appear blue if not corrected in initialization. Power consumption at full brightness is around 50-80 mA at 3.3V, so a linear regulator like AMS1117-3.3 works if your board supplies 5V. For reliable communication, use short wires (under 10 cm) and add a 0.1 µF capacitor near the display’s VCC and GND pins to filter noise. The display module typically includes a built-in SD card slot (using SPI as well), but that’s optional and shares the same SPI bus, so you’ll need separate CS pins for the display and the SD card. The backlight is usually controlled by a PWM-capable pin—set it to 100% duty cycle initially, then adjust to reduce power or dim for battery projects. If your board runs at 3.3V logic, the display is compatible, but some 5V-tolerant boards (like Arduino Uno) require level shifters because the TFT’s logic pins are 3.3V only. The initialization sequence for the ST7735S involves sending a series of commands via SPI: a software reset (0x01), sleep out (0x11), display on (0x29), and setting the color format to 16-bit (0x3A with parameter 0x05). After that, you can write pixel data using the column and page address set commands (0x2A and 0x2B) before sending the RAM write command (0x2C). Most MicroPython libraries handle this automatically, but you can write your own driver for low-level control. The display’s viewing angle is about 120 degrees horizontally and 100 degrees vertically, with a typical contrast ratio of 300:1 and brightness of 250 cd/m². It uses a transmissive LCD panel, so it needs the backlight on to be readable—no reflective mode like some monochrome displays. The response time is around 10-15 ms, which is fine for static UI but not for video. For text rendering, you can use bitmap fonts stored in the board’s flash or an external SD card—a 8x8 pixel font takes 128 bytes per character, so a full ASCII set (95 chars) needs about 12KB. If you’re drawing graphs or sensor data, you can use the framebuffer module in MicroPython to draw lines, circles, and rectangles, then flush the buffer to the display. The SPI transaction for a full screen at 16-bit color takes about 40,960 bytes / (SPI speed in bytes per second). At 10 MHz SPI clock, that’s 10,000,000 bits per second / 8 = 1,250,000 bytes per second, so a full screen update takes 40,960 / 1,250,000 ≈ 32.8 ms. In practice, overhead from command setup and Python loop adds another 10-20 ms, so expect 50-60 ms per full refresh. For partial updates, you can reduce this to under 10 ms by updating only a small rectangle. The display’s pixel pitch is 0.22 mm, giving a pixel density of about 115 PPI—sharp enough for icons and small text but not for high-DPI graphics. The operating temperature range is -20°C to +70°C, so it works in most indoor environments but not in extreme cold or heat. If you’re using an ESP32, you can leverage its dual-core architecture to run the display update on one core and sensor reading on the other—just use a mutex to avoid SPI bus conflicts. The display’s pinout is standardized: pin 1 is usually LED (backlight), pin 2 is SCK, pin 3 is SDA (MOSI), pin 4 is AO (DC), pin 5 is RESET, pin 6 is CS, pin 7 is GND, and pin 8 is VCC. Some modules swap pin 1 and pin 8, so double-check the datasheet. The logic voltage for the SPI pins is 3.3V, but the backlight pin can take 3.3V or 5V depending on the module’s resistor configuration—applying 5V to the backlight on a 3.3V-only module can burn the LED. To avoid this, measure the backlight pin voltage with a multimeter or use a 100-ohm resistor in series if unsure. For MicroPython, the most common library is `st7735.py` by Guy Carver, ported to MicroPython by various contributors. You can install it via `upip` or copy the file to your board’s filesystem. The initialization code typically looks like: import machine, st7735; spi = machine.SPI(1, baudrate=10000000, polarity=0, phase=0); dc = machine.Pin(4, machine.Pin.OUT); cs = machine.Pin(5, machine.Pin.OUT); rst = machine.Pin(6, machine.Pin.OUT); bl = machine.Pin(7, machine.Pin.OUT); bl.value(1); display = st7735.ST7735(spi, dc, cs, rst, width=128, height=160); display.init(); display.fill(0xFFFF); display.text('Hello', 10, 10, 0x0000); display.show(). Note that the `st7735` library may not include the `text` method—you’ll need to use the `framebuf` module for text rendering. For example: import framebuf; fb = framebuf.FrameBuffer(bytearray(128*160*2), 128, 160, framebuf.RGB565); fb.text('Hello', 10, 10, 0xFFFF); display.blit_buffer(fb, 0, 0, 128, 160). This uses a full frame buffer, which consumes 40KB of RAM—fine for Pico but tight for ESP8266. For ESP8266, use the `ssd1306.py` library adapted for ST7735, or write a driver that sends data line by line without a buffer. Another option is to use the `ili9341` library and modify the init sequence for ST7735—both are similar but have different register settings. The display’s refresh rate is 60 Hz typical, but MicroPython’s overhead limits you to about 15-20 FPS for full-screen updates. For animations, use double buffering: draw to an off-screen buffer, then swap it to the display via a single SPI transaction. This eliminates tearing but requires more RAM. The display’s color depth is 65,536 colors (16-bit), which is enough for photos but not for smooth gradients—you’ll see banding on subtle color transitions. For better color, you can dither using Floyd-Steinberg algorithm, but that’s computationally expensive on microcontrollers. The SPI interface is 4-wire (no MISO), so you can’t read back pixel data—you need to store a copy in RAM if you need to update specific pixels. The display’s controller supports rotation via MADCTL register (0x36): setting bit 5 flips horizontally, bit 6 flips vertically, and bit 7 swaps row/column. For portrait mode, use 0x00; for landscape, use 0x60; for reverse portrait, use 0xC0; for reverse landscape, use 0xA0. Test each orientation because the default varies by manufacturer. The display’s gamma correction is set by default, but you can adjust it via registers 0xE0 to 0xE5 for positive gamma and 0xE8 to 0xED for negative gamma—this is rarely needed unless you’re doing color-critical work. The backlight brightness can be controlled via PWM frequency—use 1 kHz to avoid flicker, and set duty cycle from 0 to 1023 (10-bit) for smooth dimming. For battery-powered projects, turn off the backlight when not in use—the display consumes about 20 mA even with backlight off because the controller stays active. You can put the display in sleep mode via command 0x10, which drops current to under 1 mA, but wake-up takes 5 ms. The display’s SPI timing requires a setup time of 15 ns for data and hold time of 10 ns—easily met by any modern microcontroller. The CS pin must be low for the entire transaction, and DC must be set before each byte: DC=0 for command, DC=1 for data. The RESET pin must be held low for at least 10 µs after power-up, then released high. Some modules have a built-in pull-up on RESET, but it’s safer to control it from the board. If you’re using a breadboard, add a 10 kΩ pull-up on CS to prevent floating during boot. The display’s glass is 1.1 mm thick with a 0.3 mm polarizer—handle by the edges to avoid cracking. The FPC connector is 0.5 mm pitch, so use a breakout board or solder carefully. For prototyping, use a pre-soldered module with pin headers. The display’s viewing angle is better from the top (12 o’clock position) than from the bottom—mount it accordingly. The contrast ratio drops to 100:1 at 45 degrees off-axis. The display’s response time increases at low temperatures—at 0°C, it’s about 30 ms, causing ghosting on fast-moving objects. The display’s storage humidity range is 10% to 90% non-condensing—avoid using in high-humidity environments without conformal coating. The display’s lifetime is about 20,000 hours at full brightness (backlight LED rated for 30,000 hours). For long-term projects, reduce backlight to 50% to extend life. The display’s pixel defects are allowed up to 3 per million pixels per ISO 13406-2 standard—so you might see a few stuck pixels. The display’s driver IC supports partial display mode (command 0x12) for updating only a window—useful for status bars or menus. The window is set via column start/end (0x2A) and page start/end (0x2B) registers, then write pixel data with 0x2C. This reduces SPI traffic and improves update speed. For example, to update a 20x20 pixel icon at position (10,10), send 0x2A with start=10, end=29, then 0x2B with start=10, end=29, then 0x2C with 800 bytes of pixel data. The display’s controller supports 12-bit color (0x3A with 0x03) but that reduces color quality—stick with 16-bit. The display’s sleep mode also disables the internal oscillator, so you must wait 5 ms after wake-up before sending commands. The display’s NOP command (0x00) can be used for debugging to check SPI communication—if you send NOP and the display doesn’t crash, the connection is likely correct. The display’s ID register (0x04) returns the driver version—useful for verifying the chip. For the ST7735S, the ID is 0x85 or 0x8C. If you get 0xFF, the display is not responding—check wiring and voltage levels. The display’s power-on sequence: apply VCC, wait 10 ms, set RESET low for 10 µs, then high, wait 120 ms for internal initialization, then send commands. The display’s power-off sequence: send sleep command (0x10), wait 5 ms, then turn off backlight and remove VCC. The display’s backlight can be controlled via a transistor if the board’s GPIO can’t source enough current—use a 2N2222 NPN transistor with a 1 kΩ base resistor. The display’s SPI bus can be shared with other devices (like an SD card or sensor) as long as each has a unique CS pin. Keep the total bus capacitance under 50 pF to avoid signal degradation—long wires add about 1 pF per cm. The display’s logic input thresholds are 0.3*VCC for low and 0.7*VCC for high—at 3.3V, that’s 1.0V low and 2.3V high, so 3.3V logic is fine. The display’s maximum SPI clock is 20 MHz, but some modules have longer traces that limit it to 15 MHz. Test at lower speeds first, then increase. The display’s pixel memory is organized as 132x162 internally, but only 128x160 is visible—the extra pixels are for border. The display’s driver supports inversion mode (command 0x20) for negative display effect—useful for night mode. The display’s tear effect (command 0x35) can be enabled to synchronize updates with the internal refresh—use this for smooth animations. The display’s temperature compensation (command 0xB1) adjusts gamma for temperature changes—enable it for outdoor use. The display’s frame rate can be set via command 0xB3—default is 60 Hz, but you can set 70 Hz for faster updates, though it increases power consumption. The display’s voltage regulator (command 0xC0) adjusts the internal charge pump—default is fine for 3.3V. The display’s VCOM voltage (command 0xC5) affects contrast—adjust if the display looks washed out. The display’s power control (command 0xC7) sets the booster current—increase for faster wake-up. The display’s gate voltage (command 0xE0) controls the TFT on-voltage—don’t change unless you have a datasheet. The display’s source voltage (command 0xE1) controls the pixel voltage swing—same caution. The display’s gamma settings (commands 0xE2 to 0xE7) are factory-calibrated—changing them can reduce color accuracy. The display’s NVM (non-volatile memory) can store custom gamma settings—use command 0xFC to write, but it’s one-time programmable. The display’s die temperature (command 0xFE) returns the internal temperature in 1°C increments—useful for thermal monitoring. The display’s interface timing: CS to SCK setup time 15 ns, SCK high time 20 ns, SCK low time 20 ns, data setup time 10 ns, data hold time 10 ns, CS high time 10 ns. These are easily met by MicroPython’s SPI implementation, but if you bit-bang SPI, use delays to meet these timings. The display’s reset timing: RESET low time 10 µs, then wait 120 ms before sending commands. The display’s power-up timing: VCC stable to RESET high time 10 ms. The display’s sleep-out to display-on time 120 ms. The display’s command set includes 0x36 (MADCTL) for orientation, 0x3A (COLMOD) for color format, 0x2A (CASET) for column address, 0x2B (RASET) for row address, 0x2C (RAMWR) for write memory, 0x2E (RAMRD) for read memory (not supported on all modules), 0x21 (INVON) for inversion on, 0x20 (INVOFF) for inversion off, 0x13 (NORON) for normal display on, 0x11 (SLPOUT) for sleep out, 0x10 (SLPIN) for sleep in, 0x29 (DISPON) for display on, 0x28 (DISPOFF) for display off, 0x01 (SWRESET) for software reset. The display’s default orientation after reset is portrait with the first pixel at top-left. The display’s color order is controlled by MADCTL bit 3 (BGR)—set to 1 for BGR order, 0 for RGB. Most ST7735 modules need BGR=1 to show correct colors. The display’s pixel format is 16-bit RGB565: bits 15-11 red, bits 10-5 green, bits 4-0 blue. For example, pure red is 0xF800, green is 0x07E0, blue is 0x001F, white is 0xFFFF, black is 0x0000. The display’s gamma curve is sRGB-like, so colors appear natural without correction. The display’s contrast ratio is 300:1 typical, meaning the brightest white is 300 times brighter than the darkest black. The display’s brightness is 250 cd/m² typical—enough for indoor use but not for direct sunlight. The display’s viewing angle is 60 degrees left/right/up/down typical—beyond that, colors invert or wash out. The display’s response time (rise+fall) is 15 ms typical—fast enough for 60 FPS video if the controller can keep up. The display’s power consumption: 50 mA with backlight on, 20 mA with backlight

Move from spec sheet to sample

Bring a formulation to the bench in 14 days.

Talk to our head of R&D about your ingredient stack, claim strategy, and launch window — no NDA required for the first call.

Book a Free Formulation Consult