npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

waveshare-epaper

v0.2.4

Published

A modular Node.js driver for Waveshare E-Paper displays that supports multiple display models with different resolutions and color modes

Readme

Waveshare E-Paper Node.js Driver

npm version

A modular Node.js driver for Waveshare E-Paper displays that supports multiple display models with different resolutions and color modes.

Features

  • Modular architecture: Easy to extend with new display models
  • Multiple display support: Currently supports 8+ display models with more easily added
  • Color mode support: Monochrome, grayscale and color modes where supported by hardware
  • Common API: Unified interface across all display models
  • Hardware abstraction: Base class handles common SPI/GPIO operations
  • PNG image loading: Built-in support for loading and displaying PNG images

Supported Displays

Not all devices have been tested in the field. Please create a GitHub issue if you have confirmed one of the untested platforms working.

| Model | Resolution | Color Modes | Description | Status | |-----------|-------------|-------------------|------------------------------------|-------------------| | 2in13 | 122 × 250 | Monochrome | 2.13" black/white | Untested | | 2in7 | 176 × 264 | Mono, 4-grayscale | 2.7" with grayscale support | Untested | | 2in7b | 176 × 264 | 3-color | 2.7" black/white/red or yellow | Untested | | 7in5 | 640 × 384 | Monochrome | 7.5" black/white | Confirmed working | | 7in3f | 800 × 480 | 7-color | 7.3" full color (7 colors) | Untested | | 13in3k | 960 × 680 | Mono, 4-grayscale | 13.3" with grayscale support | Confirmed working | | 13in3b | 960 × 680 | 3-color | 13.3" black/white/red or yellow | Untested | | 13in3gray | 1600 × 1200 | 16-grayscale | 13.3" 16-level grayscale (IT8951) | Untested |

Installation

npm install waveshare-epaper

GPIO Permissions (Recommended)

For security, add your user to the gpio group instead of running as root:

# Add current user to gpio group
sudo usermod -a -G gpio $USER

# Log out and back in, then verify group membership
groups

After logging back in, you can run GPIO programs without sudo. If you still encounter permission issues, sudo can be used as a fallback, though it's less secure.

Quick Start

const { createDisplay } = require('waveshare-epaper');

async function example() {
    // Create display instance (13.3" 4-grayscale)
    const epd = createDisplay('13in3k', '4gray', {
        rstPin: 17,
        dcPin: 25,
        busyPin: 24,
        pwrPin: 18
    });

    // Initialize and use
    await epd.init();
    await epd.clear();

    // Draw with different gray levels (0=black, 1=dark gray, 2=light gray, 3=white)
    epd.drawRect(10, 10, 100, 50, 0, true);   // Black filled rectangle
    epd.drawRect(120, 10, 100, 50, 1, true);  // Dark gray rectangle
    epd.drawRect(230, 10, 100, 50, 2, true);  // Light gray rectangle
    epd.drawLine(10, 80, 330, 80, 0);         // Black line

    // Update display
    await epd.display();
    await epd.sleep();
}

// 16-grayscale example (IT8951 controller)
async function grayscaleExample() {
    const epd = createDisplay('13in3gray', '16gray', {
        rstPin: 17,
        dcPin: 25,
        busyPin: 24,
        pwrPin: 18,
        vcom: -2.30  // Adjust according to your display
    });

    await epd.init();
    await epd.clear();

    // Draw with 16 different gray levels (0=black, 15=white)
    const cellWidth = 100;
    for (let i = 0; i < 16; i++) {
        const x = (i % 8) * cellWidth;
        const y = Math.floor(i / 8) * 60;
        epd.drawRect(x, y, cellWidth - 2, 58, i, true);
    }

    // Display with high quality GC16 mode
    await epd.display('GC16');
    await epd.sleep();
}

// Canvas example (requires: npm install canvas)
async function canvasExample() {
    const { createCanvas } = require('canvas');
    const epd = createDisplay('13in3k', '4gray', {
        rstPin: 17, dcPin: 25, busyPin: 24, pwrPin: 18
    });

    await epd.init();

    // Create a simple canvas
    const canvas = createCanvas(400, 200);
    const ctx = canvas.getContext('2d');

    // White background
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Draw text and shapes
    ctx.fillStyle = 'black';
    ctx.font = '36px Arial';
    ctx.fillText('Canvas Demo', 50, 100);

    ctx.strokeStyle = 'gray';
    ctx.lineWidth = 2;
    ctx.strokeRect(10, 10, 380, 180);

    // Draw to display
    await epd.drawCanvas(canvas, 100, 100);
    await epd.display();
    await epd.sleep();
}

example().catch(console.error);
// grayscaleExample().catch(console.error);

API Reference

Factory Functions

createDisplay(model, colorMode, options)

Creates a display instance for the specified model.

  • model (string): Display model ('2in13', '2in7', '2in7b', '7in5', '7in3f', '13in3k', '13in3b', '13in3gray')
  • colorMode (string): Color mode ('mono', '4gray', '16gray', '3color', '7color') - must be supported by the display
  • options (object): Configuration options

Options:

  • rstPin (number): Reset GPIO pin (default: 17)
  • dcPin (number): Data/Command GPIO pin (default: 25)
  • busyPin (number): Busy GPIO pin (default: 24)
  • csPin (number): Chip Select GPIO pin (default: 22)
  • pwrPin (number): Power control GPIO pin (default: 18)
  • gpioChip (string): GPIO chip name (default: 'gpiochip0')
  • busNumber (number): SPI bus number (default: 0)
  • deviceNumber (number): SPI device number (default: 0)
  • maxSpeedHz (number): SPI max speed (default: 4000000)
  • accentColor (string): For 3-color displays, specify 'red' or 'yellow' accent color
  • vcom (number): VCOM voltage for IT8951 displays (default: -2.30)

getSupportedModels()

Returns array of supported models with their specifications.

Display Methods

Basic Operations

  • await epd.init() - Initialize the display
  • await epd.clear() - Clear display to background color
  • await epd.display() - Update the display with current buffer
  • await epd.sleep() - Put display into low power mode
  • await epd.cleanup() - Clean up resources

Power Control

  • await epd.powerOn() - Turn on display power (automatically called during init)
  • await epd.powerOff() - Turn off display power (automatically called during cleanup)

Drawing Functions

  • epd.setPixel(x, y, color) - Set individual pixel
  • epd.drawLine(x0, y0, x1, y1, color) - Draw line
  • epd.drawRect(x, y, width, height, color, filled) - Draw rectangle
  • await epd.drawPNG(filePath, x, y) - Load and draw PNG image
  • await epd.drawCanvas(canvas, x, y) - Draw HTML5 Canvas object

Enhanced Drawing (Color Displays)

7-color displays:

  • epd.setPixelColor(x, y, colorName) - Set pixel using color name
  • epd.drawColorLine(x0, y0, x1, y1, colorName) - Draw colored line
  • epd.drawColorRect(x, y, w, h, colorName, filled) - Draw colored rectangle
  • await epd.show7Block() - Display all 7 colors in blocks

3-color displays:

  • epd.drawBlackRect(x, y, w, h, filled) - Draw black rectangle
  • epd.drawRedRect(x, y, w, h, filled) - Draw accent color rectangle
  • await epd.show3ColorTest() - Display 3-color test pattern

Color Values

  • Monochrome mode: 0 = black, 1 = white
  • 4-grayscale mode: 0 = black, 1 = dark gray, 2 = light gray, 3 = white
  • 16-grayscale mode: 0 = black, 1-14 = varying gray levels, 15 = white
  • 3-color mode: 0 = black, 1 = white, 2 = accent color (red or yellow, configurable)
  • 7-color mode: 0 = black, 1 = white, 2 = green, 3 = blue, 4 = red, 5 = yellow, 6 = orange

Color Names (7-color displays)

For 7-color displays, you can use color names:

epd.setPixelColor(x, y, 'RED');
epd.drawColorRect(10, 10, 100, 50, 'BLUE', true);
epd.drawColorLine(0, 0, 100, 100, 'GREEN');

Available colors: BLACK, WHITE, RED, GREEN, BLUE, YELLOW, ORANGE

Architecture

File Structure

├── index.js              # Main entry point and factory functions
├── EPDBase.js             # Base class with common functionality
├── displays/
│   ├── index.js           # Display module exports
│   ├── EPD2in13.js        # 2.13" monochrome display driver
│   ├── EPD2in7.js         # 2.7" mono/4-grayscale display driver
│   ├── EPD2in7b.js        # 2.7" 3-color display driver
│   ├── EPD7in5.js         # 7.5" monochrome display driver
│   ├── EPD7in3f.js        # 7.3" 7-color display driver
│   ├── EPD13in3k.js       # 13.3" mono/4-grayscale display driver
│   ├── EPD13in3b.js       # 13.3" 3-color display driver
│   └── EPD13in3Gray.js    # 13.3" 16-grayscale display driver (IT8951)
├── examples/              # Usage examples for each feature
└── README.md              # This file

Extending with New Displays

To add support for a new display model:

  1. Create a new file in displays/ (e.g., EPDNewModel.js)

  2. Extend EPDBase class:

    const EPDBase = require('../EPDBase');
    
    class EPDNewModel extends EPDBase {
        constructor(options = {}) {
            super(options);
            this.width = 200;    // Set display width
            this.height = 200;   // Set display height
            this.colorMode = options.colorMode || 'mono';
            this.bitsPerPixel = this.colorMode === '4gray' ? 2 : 1;
            this.initializeBuffer();
        }
    
        async initDisplay() {
            // Implement display-specific initialization
        }
    
        async displayImage() {
            // Implement display-specific image update
        }
    }
  3. Add to displays/index.js exports

  4. Add case to createDisplay() function

Hardware Requirements

System Requirements

  • Raspberry Pi with SPI enabled
  • gpiod tools installed (apt install gpiod)
  • Node.js 14+ (recommended: Node.js 18+)

Raspberry Pi Model Compatibility

| Model | GPIO Chip | Pin Layout | SPI Interface | Initialization Notes | |------------------|-----------------|-------------------|------------------|----------------------------------| | Pi 1 Model A/B | gpiochip0 | 26-pin (original) | /dev/spidev0.0 | Limited pins, use adapted wiring | | Pi 1 Model A+/B+ | gpiochip0 | 40-pin | /dev/spidev0.0 | Full compatibility | | Pi 2 Model B | gpiochip0 | 40-pin | /dev/spidev0.0 | Full compatibility | | Pi 3 Model A+/B+ | gpiochip0 | 40-pin | /dev/spidev0.0 | Full compatibility | | Pi 4 Model B | gpiochip0 | 40-pin | /dev/spidev0.0 | Full compatibility | | Pi 5 | gpiochip4 | 40-pin | /dev/spidev0.0 | Requires gpioChip option |

Raspberry Pi 5 Configuration

Critical: Pi 5 uses gpiochip4 instead of gpiochip0. You must specify this in your configuration or initialization will fail:

const epd = createDisplay('13in3k', 'mono', {
    rstPin: 17,
    dcPin: 25,
    busyPin: 24,
    pwrPin: 18,
    gpioChip: 'gpiochip4'  // Required for Pi 5
});

Legacy Pi Models (26-pin)

Original Pi 1 Model A/B have only 26 GPIO pins. Use this pin mapping:

  • RST: GPIO 17 ✓ (available)
  • DC: GPIO 25 ✓ (available)
  • CS: GPIO 22 ✓ (available)
  • BUSY: GPIO 24 ✓ (available)
  • PWR: GPIO 18 ✓ (available)

GPIO Pin Connections

The following GPIO pins are required for proper operation:

| Function | Default Pin | Description | |----------|-------------|---------------------------------------------------------------| | RST | GPIO 17 | Reset signal (output) | | DC | GPIO 25 | Data/Command signal (output) | | CS | GPIO 22 | SPI Chip Select (output) | | BUSY | GPIO 24 | Busy status signal (input) | | PWR | GPIO 18 | Power control (output) - Critical for cold boot operation |

Important: The power pin (PWR) is essential for reliable operation, especially when cold-booting the Raspberry Pi. Many Waveshare e-paper displays require explicit power control to function properly. Without this pin, the display may:

  • Not respond to commands after a cold boot
  • Work only after running other display programs first
  • Show inconsistent initialization behavior

SPI Configuration

The driver uses SPI interface with these default settings:

  • SPI Bus: /dev/spidev0.0 (bus 0, device 0)
  • Speed: 4 MHz (configurable)
  • Mode: SPI Mode 0 (CPOL=0, CPHA=0)

Enable SPI on Raspberry Pi

sudo raspi-config
# Navigate to: Interfacing Options → SPI → Enable
# Or add to /boot/config.txt:
echo "dtparam=spi=on" | sudo tee -a /boot/config.txt
sudo reboot

Troubleshooting

Display Not Working After Cold Boot

Symptoms: Display appears to initialize (no errors) but screen doesn't update, or works only after running manufacturer's example programs.

Cause: Missing power pin configuration. Many Waveshare displays have internal power management that requires explicit control.

Solution: Always specify the power pin in your configuration:

const epd = createDisplay('13in3k', 'mono', {
    rstPin: 17,
    dcPin: 25,
    busyPin: 24,
    pwrPin: 18
});

Common GPIO Issues

Permission errors: Make sure you're running with appropriate permissions or add your user to the gpio group:

sudo usermod -a -G gpio $USER
# Then log out and back in

GPIO already in use: If you see "Device or resource busy" errors, check what's using the GPIO pins:

# Check what's using GPIO pins
sudo lsof /dev/gpiomem
# Or check specific pins
gpioinfo | grep -E "(17|18|24|25)"

Auto-Detection and Troubleshooting

Checking Your GPIO Chip

If you're unsure which GPIO chip your Pi uses, run:

gpioinfo | head -n 1

For Pi 5, you'll see: gpiochip4 - 54 lines For older Pi models: gpiochip0 - 54 lines (or similar)

Environment Variable (Alternative)

You can also set the GPIO chip via environment variable:

export GPIO_CHIP=gpiochip4  # For Pi 5
node your-epd-program.js

Then check for this variable in your code:

const epd = createDisplay('13in3k', 'mono', {
    gpioChip: process.env.GPIO_CHIP || 'gpiochip0'
});

Cairo Error

If while loading canvas you get this error:

Error: libcairo.so.2: ELF load command address/offset not page-aligned

Tru removing canvas and re-installing by compiling from source.

rm -fr node_modules/canvas/
npm install canvas --build-from-source

This can happen if you compile Node.js from source because the precompiled ciaro library that comes with canvas might not be compatible with what you have.

Examples

See the examples/ directory for working examples of each feature. Each example demonstrates a specific capability and can be copied directly into your projects.

Usage Examples

7-Color Display Example

const epd = createDisplay('7in3f', '7color');
await epd.init();

// Show all 7 colors in blocks
await epd.show7Block();

// Draw using color names
epd.drawColorRect(50, 50, 100, 80, 'RED', true);
epd.drawColorLine(0, 100, 800, 100, 'BLUE');
epd.setPixelColor(10, 10, 'GREEN');

await epd.display();

3-Color Display Example

// Black/White/Red display
const epd = createDisplay('13in3b', 'red');
// Or Black/White/Yellow display
const epd = createDisplay('13in3b', 'yellow');

await epd.init();

// Draw in different colors
epd.drawBlackRect(50, 50, 200, 100, true);  // Black rectangle
epd.drawRedRect(300, 50, 200, 100, true);   // Accent color rectangle
// White is the background color

// Show test pattern
await epd.show3ColorTest();

Canvas Support

The drawCanvas() method allows rendering HTML5 Canvas objects directly to the display. This enables dynamic text rendering with TrueType fonts, graphics drawing, and complex layouts:

const { createCanvas, registerFont } = require('canvas');

// Register a TrueType font
registerFont('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', { family: 'MyFont' });

// Create and configure canvas
const canvas = createCanvas(800, 400);
const ctx = canvas.getContext('2d');

// White background
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw text with custom font
ctx.fillStyle = 'black';
ctx.font = '48px MyFont';
ctx.textAlign = 'center';
ctx.fillText('Hello E-Paper!', canvas.width / 2, canvas.height / 2);

// Draw graphics
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
ctx.strokeRect(10, 10, canvas.width - 20, canvas.height - 20);

// Render to display
await epd.drawCanvas(canvas, 0, 0);

Canvas Features:

  • TrueType font rendering with canvas package
  • Text, shapes, gradients, and complex graphics
  • Automatic color conversion for all display modes
  • Transparency support (transparent pixels become background color)
  • Full HTML5 Canvas API compatibility

Requirements: Install the canvas package for Canvas support:

npm install canvas

See canvas-example.js for a complete working example.

Advanced Color Detection

The driver automatically converts PNG images to the appropriate color format:

// 7-color display will convert RGB to nearest of 7 colors
await epd.drawPNG('colorful-image.png', 0, 0);

// 3-color display will detect red/yellow regions and convert others to black/white
await epd.drawPNG('mixed-color-image.png', 0, 0);

Migration from Original Code

The original display classes are still available for backward compatibility:

const { EPD13in3k } = require('waveshare-epaper');
const epd = new EPD13in3k();

However, using the new factory function is recommended:

const { createDisplay } = require('waveshare-epaper');
const epd = createDisplay('13in3k', 'mono');

Publishing

To publish a new version to npm:

npm version patch  # or minor/major
npm publish

License

MIT License - see LICENSE file for details.

Based on Waveshare example code.