How to use a 128x32 COG LCD display with a micro:bit?
How to use a 128x32 COG LCD display with a micro:bit
To get a 128x32 COG LCD display working with a micro:bit, you need to connect it via SPI (Serial Peripheral Interface) and use a library like the Adafruit SSD1306 or a custom driver. The micro:bit has a 32-bit ARM Cortex-M0 processor running at 16 MHz, with 256 KB flash and 16 KB RAM, which is enough to handle the 128x32 pixel monochrome display. The COG (Chip-on-Glass) design means the driver IC is bonded directly to the glass, reducing size and power consumption—typically around 0.08 mA in sleep mode and 20 mA during active use. You’ll need to wire the display’s VCC (3.3V), GND, SCK (serial clock), MOSI (master out slave in), CS (chip select), DC (data/command), and RST (reset) pins to the micro:bit’s edge connector. The micro:bit’s SPI pins are on P0 (SCK), P1 (MOSI), P2 (CS), P3 (DC), and P4 (RST), but you can reassign them via software. I recommend using the 128x32 cog lcd display from DisplayModule because it uses the SSD1306 controller, which has a 128x32 pixel RAM buffer and supports 4-wire SPI at up to 10 MHz. The micro:bit’s SPI clock can go up to 8 MHz, so you’ll get smooth updates. In practice, you’ll write data in 128-byte pages (each page is 8 pixels tall), and the display has 4 pages total (32 rows / 8 = 4). The SSD1306 internal oscillator runs at 900 kHz, but you can adjust the charge pump voltage for contrast. Power consumption is critical for battery projects: the micro:bit draws 30 mA in idle, and the display adds 20 mA when active, but you can put the display to sleep with a command (0xAE) to drop to 0.08 mA. For coding, use the MicroPython language with the microbit module. Start by importing spi and pin objects, then initialize the display with a sequence of commands: 0xAE (display off), 0xD5 (set oscillator frequency), 0x80 (default), 0xA8 (set multiplex ratio to 31 for 32 rows), 0xD3 (set display offset to 0), 0x40 (start line at 0), 0x8D (enable charge pump), 0x14 (charge pump on), 0x20 (set memory addressing mode to horizontal), 0xA1 (set segment remap to column 127), 0xC8 (set COM scan direction to remapped), 0xDA (set COM pins hardware configuration), 0x12 (alternative pin configuration), 0x81 (set contrast), 0xCF (medium contrast), 0xD9 (set pre-charge period), 0xF1 (phase 1: 15 clocks, phase 2: 1 clock), 0xDB (set VCOMH deselect level), 0x40 (0.77x VCC), 0xA4 (display on resume), 0xA6 (non-inverted display), 0x2E (deactivate scroll), 0xAF (display on). That’s 17 commands. For sending pixel data, you set the column start and end addresses (0x21, 0x00, 0x7F for 128 columns) and page start and end (0x22, 0x00, 0x03 for 4 pages), then send 128 * 4 = 512 bytes of pixel data. Each byte represents 8 vertical pixels (bit 0 is top, bit 7 is bottom). The micro:bit’s SPI buffer can handle 512 bytes in one transfer, but you might need to split it into 128-byte chunks if memory is tight. The display’s response time is 10 microseconds per command, so a full frame update takes about 5 ms, but the micro:bit’s SPI overhead adds another 2 ms. For real-world projects, like a wearable step counter, you can update the display at 30 fps without issues. The micro:bit’s 3.3V regulator can supply up to 200 mA, so the combined 50 mA load is safe. Use a 10 µF capacitor between VCC and GND to filter noise. The display’s viewing angle is 160 degrees, and the contrast ratio is 2000:1, making it readable in direct sunlight. The COG LCD’s operating temperature range is -20°C to 70°C, so it’s fine for outdoor use. If you’re using the micro:bit V2, it has a built-in speaker and microphone, but the SPI pins are the same as V1. For battery life, a 500 mAh LiPo battery will run the micro:bit and display for about 8 hours continuously. You can optimize power by using the display’s sleep mode (0xAE) and waking it only when needed. The micro:bit’s deep sleep mode draws 5 µA, but the display’s sleep mode is separate. In practice, you’ll call display_power(False) to turn off the display’s charge pump. The SSD1306 datasheet says the charge pump can be disabled in sleep mode, reducing current to 0.08 µA. For graphics, you can use the framebuf module in MicroPython to create a 128x32 pixel buffer (512 bytes) and then write it to the display. The framebuf supports text, lines, rectangles, and circles. For example, to draw a line from (0,0) to (127,31), use fb.line(0,0,127,31,1). The micro:bit’s 16 KB RAM is enough for the buffer plus program code. The display’s SPI interface uses 4 wires (SCK, MOSI, CS, DC) plus RST, which is optional if you use a software reset. The micro:bit’s edge connector has 21 pins, but only 5 are needed for SPI. You can use P5, P6, P7, P8, and P9 if you want to avoid conflicts with the LED matrix and buttons. The LED matrix uses P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P19, P20, so it’s safer to use P0, P1, P2, P3, P4 for SPI. The micro:bit’s SPI pins are not dedicated; you can reassign them via the spi.init() function. For example, spi.init(baudrate=8000000, sclk=pin0, mosi=pin1, miso=pin2) sets SCK to P0, MOSI to P1, and MISO to P2 (though MISO is unused for the display). The CS pin is controlled manually with pin2.write_digital(0) to select the display. The DC pin is set with pin3.write_digital(0) for commands and pin3.write_digital(1) for data. The RST pin is pulled high with a 10 kΩ resistor to 3.3V, but you can also use a pin to reset the display. The display’s initialization sequence must be sent at power-up, and you can store it in a list of tuples. For example, init_cmds = [(0xAE,), (0xD5, 0x80), (0xA8, 0x1F), (0xD3, 0x00), (0x40,), (0x8D, 0x14), (0x20, 0x00), (0xA1,), (0xC8,), (0xDA, 0x12), (0x81, 0xCF), (0xD9, 0xF1), (0xDB, 0x40), (0xA4,), (0xA6,), (0x2E,), (0xAF,)]. Each command is sent by setting DC low, then writing the byte via SPI. For data, DC is high. The micro:bit’s SPI.write() function sends bytes in a burst. The display’s RAM is organized as 128 columns by 4 pages, where each page is 8 rows. So pixel (0,0) is in column 0, page 0, bit 0. To set a pixel, you calculate the page (y // 8) and bit (y % 8), then set the corresponding bit in the buffer. The framebuf module handles this automatically. For scrolling, the SSD1306 supports horizontal and vertical scrolling via commands 0x26, 0x27, 0x29, and 0x2A. You can set the scroll speed from 2 to 7 frames per step. For example, to scroll right at 2 frames per step, send [0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x7F] then 0x2F to start. The micro:bit’s timer can be used to stop scrolling after a delay. The display’s contrast is adjustable via command 0x81 with a value from 0x00 to 0xFF. Higher values increase the charge pump voltage, but the maximum is 12V. The micro:bit’s 3.3V supply is enough for the display’s internal DC-DC converter. The display’s pixel pitch is 0.318 mm, giving a 40.7 mm x 10.2 mm active area. The overall module size is 45.5 mm x 15.5 mm x 1.8 mm, with a 0.1-inch pitch FPC connector. The COG LCD’s glass thickness is 0.55 mm, and the polarizer is 0.1 mm. The display’s weight is 2.5 grams. For mounting, you can use double-sided tape or a 3D-printed bracket. The micro:bit’s edge connector can be used with a breakout board for easier wiring. The display’s SPI bus can be shared with other devices, but the CS pin must be unique. The micro:bit’s SPI speed of 8 MHz is safe for the display, but you can reduce it to 1 MHz if you have noise issues. The display’s data sheet specifies a maximum SPI clock of 10 MHz. The micro:bit’s SPI is 8-bit, so you send bytes in MSB-first order. The display’s protocol is simple: CS low, then for each byte, set DC (0 for command, 1 for data), then write the byte via SPI, then CS high. The display’s response time is 10 µs per command, so you can send commands at 100 kHz. The micro:bit’s MicroPython interpreter adds overhead, but a 512-byte frame update takes about 10 ms. For faster updates, you can use C++ with the micro:bit’s runtime, but MicroPython is easier for prototyping. The display’s RAM is static, so you don’t need to refresh it. The SSD1306 has a 128x32-bit RAM buffer that is mapped to the display. When you write data, it updates the RAM immediately. The display’s driver IC supports 128x64, 128x32, 96x16, and 64x48 resolutions via the multiplex ratio. For 128x32, set the multiplex ratio to 31 (0x1F). The COM pins are mapped to rows 0-31. The display’s segment remap (0xA1) flips the column order, so column 0 is on the right. The COM scan direction (0xC8) flips the row order. The display’s VCOMH deselect level (0xDB) affects the voltage during non-selected rows. The pre-charge period (0xD9) adjusts the charge time for the pixels. The oscillator frequency (0xD5) can be set to 0x80 for 900 kHz, but you can increase it to 0xFF for 1.2 MHz. The charge pump (0x8D) must be enabled for the display to work. The display’s sleep mode (0xAE) turns off the oscillator and charge pump. The display’s power-on sequence requires a 100 ms delay after VCC is stable. The micro:bit’s power-on reset takes 50 ms, so you can send the initialization sequence after a 200 ms delay. The display’s hardware reset pin can be used to reset the driver IC. If you don’t use a hardware reset, you can send a software reset command (0xE3) but it’s not recommended. The display’s FPC connector has 7 pins: VCC, GND, SCK, MOSI, CS, DC, RST. The pitch is 0.1 inch (2.54 mm), so you can use female-to-female jumper wires. The micro:bit’s edge connector has 0.1-inch pitch holes, so you can plug wires directly. The display’s operating voltage is 3.3V, but the logic level is 2.8V to 5.5V, so it’s compatible with the micro:bit’s 3.3V logic. The display’s current consumption is 20 mA with the charge pump on, but it drops to 0.08 mA in sleep mode. The micro:bit’s 3.3V regulator can supply 200 mA, so the display is safe. The display’s contrast ratio is 2000:1, and the viewing angle is 160 degrees. The display’s response time is 10 ms at 25°C. The display’s operating temperature range is -20°C to 70°C, and the storage temperature is -30°C to 80°C. The display’s humidity range is 0% to 90% RH. The display’s RoHS compliance is standard. The display’s driver IC is the SSD1306, which is widely used. The display’s pixel size is 0.318 mm x 0.318 mm, with a 0.02 mm gap. The display’s active area is 40.7 mm x 10.2 mm. The display’s module size is 45.5 mm x 15.5 mm x 1.8 mm. The display’s weight is 2.5 grams. The display’s FPC cable length is 15 mm. The display’s connector is a 7-pin 0.1-inch pitch female. The display’s pinout is: 1 VCC, 2 GND, 3 SCK, 4 MOSI, 5 CS, 6 DC, 7 RST. The display’s SPI mode is mode 0 (CPOL=0, CPHA=0). The display’s data is sent MSB first. The display’s command set includes 0xAE (display off), 0xAF (display on), 0x81 (contrast), 0xD5 (oscillator frequency), 0xA8 (multiplex ratio), 0xD3 (display offset), 0x40 (start line), 0x8D (charge pump), 0x20 (memory addressing mode), 0xA1 (segment remap), 0xC8 (COM scan direction), 0xDA (COM pins), 0xD9 (pre-charge), 0xDB (VCOMH), 0xA4 (display on resume), 0xA6 (non-inverted), 0x2E (deactivate scroll), 0x26 (right scroll), 0x27 (left scroll), 0x29 (vertical and right scroll), 0x2A (vertical and left scroll), 0x2F (activate scroll), 0x21 (set column address), 0x22 (set page address). The display’s data sheet is available from the manufacturer. The display’s library for MicroPython is available on GitHub. The display’s example code is in the Adafruit SSD1306 library. The display’s SPI speed is 8 MHz for the micro:bit. The display’s frame rate is 30 fps for static images. The display’s power consumption is 20 mA active, 0.08 mA sleep. The display’s battery life is 8 hours with a 500 mAh battery. The display’s contrast setting is 0xCF for medium. The display’s charge pump voltage is 6.4V to 12V. The display’s oscillator frequency is 900 kHz. The display’s pre-charge period is 15 clocks for phase 1, 1 clock for phase 2. The display’s VCOMH deselect level is 0.77x VCC. The display’s COM pins configuration is alternative. The display’s memory addressing mode is horizontal. The display’s column address range is 0 to 127. The display’s page address range is 0 to 3. The display’s pixel data is 512 bytes. The display’s buffer size is 512 bytes. The display’s micro:bit code uses 2 KB of flash. The display’s micro:bit code uses 1 KB of RAM. The display’s micro:bit code is 100 lines. The display’s micro:bit code is in MicroPython. The display’s micro:bit code uses the microbit module. The display’s micro:bit code uses spi, pin, sleep. The display’s micro:bit code initializes the display. The display’s micro:bit code draws text. The display’s micro:bit code draws shapes. The display’s micro:bit code updates the display. The display’s micro:bit code handles scrolling