Text Rendering on E-Ink
Text Rendering on E-Ink
Overview
Section titled “Overview”This section covers text rendering on e-paper displays using the GxEPD2 and AdaFruit GFX libraries. Proper text layout is essential for creating readable factory dashboards. After completing this section, you will be able to:
- Display text at various positions on the e-paper screen
- Change font size and style using built-in fonts
- Align text horizontally and vertically
- Combine multiple text elements on a single screen
Prerequisites
Section titled “Prerequisites”Before starting this section, please ensure:
- GxEPD2 library is installed (see 02-03)
- Display is wired and verified
- Basic understanding of display coordinates
Key Concepts
Section titled “Key Concepts”Coordinate System
Section titled “Coordinate System”The e-paper display uses a standard Cartesian coordinate system with the origin at the top-left corner:
(0,0) ──────────────────────────── X (width) │ │ +-------------------+ │ | | │ | Display Area | │ | | │ +-------------------+ │ Y (height)For a 2.13” display (250×122 pixels):
- X range: 0 to 249 (horizontal)
- Y range: 0 to 121 (vertical)
- Text is placed using
display.setCursor(x, y)
Built-in Fonts
Section titled “Built-in Fonts”The AdaFruit GFX library provides several built-in fonts:
| Font Name | Size | Use Case |
|---|---|---|
| (default) | 5×7 px | Minimal text, debug output |
&FreeMono9pt7b | 9pt monospace | Tabular data |
&FreeMonoBold12pt7b | 12pt bold mono | Headers, KPIs |
&FreeMonoBold18pt7b | 18pt bold mono | Large numbers |
&FreeMonoBold24pt7b | 24pt bold mono | Very large values |
&FreeSans9pt7b | 9pt sans-serif | Body text |
&FreeSansBold12pt7b | 12pt bold sans | Section titles |
&FreeSerif12pt7b | 12pt serif | Decorative text |
&TomThumb | 3×5 px | Ultra-small labels |
Font naming convention: &FontNameSizept7b where:
&is required prefix when referencing the font- 7b means 7-bit character encoding (standard ASCII)
Implementation Steps
Section titled “Implementation Steps”Step 1: Basic Text Output
Section titled “Step 1: Basic Text Output”#include <GxEPD2_BW.h>
#define EPD_CS 5#define EPD_DC 17#define EPD_RST 16#define EPD_BUSY 4
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display( GxEPD2_213_B72(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void setup() { Serial.begin(115200); display.init(115200); display.setRotation(1); // Landscape orientation
// Clear screen display.fillScreen(GxEPD_WHITE);
// Draw text at specific coordinates display.setCursor(10, 20); display.print("Line 1: Factory Display");
display.setCursor(10, 35); display.print("Line 2: Temperature: 25.5C");
display.setCursor(10, 50); display.print("Line 3: Humidity: 60%");
// Push to display display.display();}
void loop() {}Expected Result: Three lines of small text displayed at the left side.
Step 2: Using Different Fonts
Section titled “Step 2: Using Different Fonts”#include <GxEPD2_BW.h>
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display( GxEPD2_213_B72(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void setup() { display.init(115200); display.setRotation(1); display.fillScreen(GxEPD_WHITE);
// Default 5x7 font display.setCursor(0, 10); display.print("Default font (5x7)");
// 9pt monospace display.setFont(&FreeMono9pt7b); display.setCursor(0, 30); display.print("9pt Mono");
// 12pt bold monospace display.setFont(&FreeMonoBold12pt7b); display.setCursor(0, 55); display.print("12pt Bold");
// 18pt bold monospace (large numbers) display.setFont(&FreeMonoBold18pt7b); display.setCursor(0, 85); display.print("42.5");
display.display();}
void loop() {}Note: After changing font with
setFont(), the cursor position behavior changes. Font-based cursors use the font’s baseline as the Y reference point, while default font uses top-left.
Step 3: Centering Text
Section titled “Step 3: Centering Text”To center text horizontally, calculate the position using text bounds:
#include <GxEPD2_BW.h>
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display( GxEPD2_213_B72(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void centerText(const char* text, int y, const GFXfont* font) { display.setFont(font);
// Get text bounds int16_t x1, y1; uint16_t w, h; display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h);
// Calculate centered X position int16_t x = (display.width() - w) / 2;
// Draw text at centered position display.setCursor(x, y); display.print(text);}
void setup() { display.init(115200); display.setRotation(1); display.fillScreen(GxEPD_WHITE);
// Header centered display.setTextColor(GxEPD_BLACK); display.setFont(&FreeMonoBold12pt7b); centerText("FACTORY STATUS", 25, &FreeMonoBold12pt7b);
// Temperature value centered centerText("Temperature: 25.5C", 60, &FreeMono9pt7b);
// Humidity value centered centerText("Humidity: 60%", 85, &FreeMono9pt7b);
display.display();}
void loop() {}Step 4: Text Rotation
Section titled “Step 4: Text Rotation”E-paper displays support 4 rotation modes:
// Rotation valuesdisplay.setRotation(0); // 0° - Portrait (default)display.setRotation(1); // 90° - Landscapedisplay.setRotation(2); // 180° - Inverted portraitdisplay.setRotation(3); // 270° - Inverted landscapeFor factory dashboard typically use:
- Rotation 1 (landscape): For wider data table displays
- Rotation 0 (portrait): For KPI-style single-value displays
Step 5: Multi-Line Display Function
Section titled “Step 5: Multi-Line Display Function”void displayText(const char* title, const char* value1, const char* value2) { display.fillScreen(GxEPD_WHITE);
// Title display.setFont(&FreeMonoBold12pt7b); display.setCursor(5, 25); display.print(title);
// Horizontal separator line display.drawFastHLine(0, 35, display.width(), GxEPD_BLACK);
// Value 1 display.setFont(&FreeMono9pt7b); display.setCursor(5, 55); display.print(value1);
// Value 2 display.setCursor(5, 80); display.print(value2);
display.display();}
// Usage in setup():// displayText("PLANT A", "Temp: 25.5C", "Humi: 60%");Verification
Section titled “Verification”After uploading the text rendering sketch, verify:
- Text appears at the expected positions
- Different fonts display correctly
- Centered text is properly aligned
- Rotation changes orientation as expected
- Text is readable (black on white background)
Troubleshooting
Section titled “Troubleshooting”Issue 1: Text Shows as Garbled Characters
Section titled “Issue 1: Text Shows as Garbled Characters”Symptom:
- Random characters instead of readable text
Solution:
- Ensure font is referenced with
&prefix (e.g.,&FreeMono9pt7b) - Check that font is defined within the sketch scope
- Don’t use
setFont(NULL)accidentally between font changes
Issue 2: Text Is Cut Off
Section titled “Issue 2: Text Is Cut Off”Symptom:
- Text extends beyond the display boundary
- Bottom of text is missing
Solutions:
- Use
display.getTextBounds()to measure text width before drawing - Ensure Y position accounts for font height (larger fonts need more vertical space)
- Reduce font size or line length
Issue 3: Text Alignment Is Off
Section titled “Issue 3: Text Alignment Is Off”Symptom:
- Centered text is not truly centered
- Multiple lines don’t align vertically
Solution:
// Use a helper function for consistent alignmentint16_t getCenteredX(const char* text, const GFXfont* font) { display.setFont(font); int16_t x1, y1; uint16_t w, h; display.getTextBounds(text, 0, 0, &x1, &y1, &w, &h); return (display.width() - w) / 2;}Best Practices
Section titled “Best Practices”- ✅ Use monospace fonts for tabular data — Ensures columns align properly
- ✅ Prefer bold fonts for KPIs — Better readability at a distance
- ✅ Calculate text bounds before positioning for reliable centering
- ❌ Avoid small fonts (< 9pt) for factory floor viewing
- ❌ Don’t mix too many font sizes on one screen — Keep to 2-3 maximum
- ❌ Avoid unnecessary font changes — Each
setFont()call adds processing overhead
Common Layout Templates
Section titled “Common Layout Templates”Template 1: Single KPI (factory KPI board)
┌─────────────────────────────────────┐│ PRODUCTION LINE A │ ← 12pt bold, centered├─────────────────────────────────────┤│ ││ 25,847 │ ← 24pt bold, centered│ Units Today │ ← 9pt, centered│ ││ Target: 30,000 │ +5.3% YoY │ ← 9pt mono, two columns└─────────────────────────────────────┘Template 2: Multi-Sensor Readout
┌─────────────────────────────────────┐│ ENVIRONMENT MONITOR │ 14:30 │ ← Header with time├─────────────────────────────────────┤│ Temperature │ 25.5°C │ Normal ││ Humidity │ 60% │ Normal ││ Pressure │ 1013hPa │ Stable ││ Light │ 450 lux │ Good │└─────────────────────────────────────┘Summary
Section titled “Summary”- Text rendering uses AdaFruit GFX primitives —
setCursor(),setFont(),print() - Font selection affects cursor behavior — Font-based fonts use baseline Y coordinates
- Use
getTextBounds()for accurate positioning — Essential for centering and alignment - Display rotation changes coordinate system — Set once at initialization
- Keep text layouts simple — 2-3 font sizes maximum for readability
References
Section titled “References”Target Audience: Alibaba.com IoT Pre-sales Engineers
Status: ✅ Completed