https://github.com/anders94/waveshare-epaper
A modular Node.js driver for Waveshare E-Paper displays that supports multiple display models with different resolutions and color modes
https://github.com/anders94/waveshare-epaper
Last synced: 5 months ago
JSON representation
A modular Node.js driver for Waveshare E-Paper displays that supports multiple display models with different resolutions and color modes
- Host: GitHub
- URL: https://github.com/anders94/waveshare-epaper
- Owner: anders94
- License: mit
- Created: 2025-09-14T02:33:22.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-09-27T13:14:10.000Z (8 months ago)
- Last Synced: 2025-09-27T15:12:03.320Z (8 months ago)
- Language: JavaScript
- Size: 121 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Waveshare E-Paper Node.js Driver
[](https://www.npmjs.com/package/waveshare-epaper)
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
```bash
npm install waveshare-epaper
```
### GPIO Permissions (Recommended)
For security, add your user to the `gpio` group instead of running as root:
```bash
# 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`.
## Quick Start
### 13.3" 4-grayscale Example
```javascript
const { createDisplay } = require('waveshare-epaper');
(async () => {
// 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)
```javascript
const { createDisplay } = require('waveshare-epaper');
(async () => {
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`
```javascript
const { createDisplay } = require('waveshare-epaper');
(async () => {
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);
// Draw a rectangle around the text
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();
})();
```
## 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:
```javascript
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:
```javascript
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:
```javascript
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
```bash
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:
```javascript
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:
```bash
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:
```bash
# 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:
```bash
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:
```bash
export GPIO_CHIP=gpiochip4 # For Pi 5
node your-epd-program.js
```
Then check for this variable in your code:
```javascript
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/](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
```javascript
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
```javascript
// 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:
```javascript
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:
```bash
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:
```javascript
// 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:
```javascript
const { EPD13in3k } = require('waveshare-epaper');
const epd = new EPD13in3k();
```
However, using the new factory function is recommended:
```javascript
const { createDisplay } = require('waveshare-epaper');
const epd = createDisplay('13in3k', 'mono');
```
## Publishing
To publish a new version to npm:
```bash
npm version patch # or minor/major
npm publish
```
## License
MIT License - see [LICENSE](LICENSE) file for details.
Based on Waveshare example code.