Library to repurposing the control panel (PNL CE02) of EPSON XP 520/530/540 printers from an Arduino.
- Motivation
- Installation
- Hardware requirements
- Connecting the control panel
- Let's play!
- Using display
- Library documentation
- Credits
- Like this project? ❤️
Nothing is lost, nothing is created, everything is transformed
-- Antoine LAVOISIER
I don't like waste. So the day my printer stopped working, I put it aside until the day I needed a control panel. When this day came, I decided to embark on the reverse engineering of this control panel. Of course, there are many components compatible with Arduino. But you know... in an ecological approach and especially for the technical challenges, I rushed headlong! See REVERSE.md for details.
This control panel can now be recycled and interfaced with an Arduino.
Happy hacking!
-
Arduino IDE: Search for "Epson_PNL_CE02" in the built-in Arduino IDE Library manager (details)
-
PlatformIO: Add
XavierBassoud/Epson_PNL_CE02
in thelib_deps
section of your platformio.ini file (details) -
Direct download from source: Clone this repository into Arduino/Libraries
- Arduino (tested with Arduino MEGA 2560)
- FPC 14 pin 1.0mm adapter (avoid pads destroyed by soldering)
- Level shifter (5v to 3.3v)
- Control panel (PNL CE02) of EPSON XP 520/530/540 printers (obviously)
Pin | Purpose | MEGA 2560 |
---|---|---|
1 | 3-STATE Output Enable Input (OE) | 45 |
2 | Serial Data Output (SER OUT) | 50 (SPI MISO) |
3 | GND | GND |
4 | Power button | 46 🔺 |
5 | 3.3V supply | 3.3V |
6 | LCD reset | 47 ⚡ |
7 | LCD backlight (+5V !) | 5V |
8 | GND | - |
9 | Shift Register Clock Input (SCK) | 52 (SPI SCK) |
10 | Serial Data Input (SER IN) | 51 (SPI MOSI) |
11 | Storage Register Clock Input (RCK) | 48 |
12 | GND | - |
13 | LCD write | 49 ⚡ |
14 | GND | - |
⚡ Require a 3.3v level-shifter, screen makes shadows and may be destroyed after long use.
🔺 Require a 10k pull-up resistor wired between 3.3V and Arduino pin
#include <Epson_PNL_CE02.h>
Epson_PNL_CE02_Pinout pinout = {
/* Control panel to Arduino pinout */
.EXTENDER_OE = 45, // FFC 1
.SERIAL_OUT = 50, // SPI MISO / FFC 2
.POWER_BUTTON = 46, // FFC 4
.LCD_RESET = 47, // FFC 6
.CLOCK = 52, // SPI SCK / FFC 9
.SERIAL_IN = 51, // SPI MOSI / FFC 10
.LATCH = 48, // FFC 11
.LCD_WRITE = 49, // FFC 13
};
Epson_PNL_CE02 controlPanel(&pinout);
const byte OK = static_cast<byte>(ButtonMask::OK);
const byte HOME = static_cast<byte>(ButtonMask::HOME);
void setup()
{
Serial.begin(9600);
controlPanel.begin();
}
void loop()
{
switch (controlPanel.readButtons())
{
case OK:
Serial.println("Button OK pressed!");
break;
case OK | HOME:
Serial.println("Button OK and button HOME pressed!");
break;
}
// Power button has a dedicated pin
if (controlPanel.isPowerButtonPressed())
{
Serial.println("Button POWER pressed!");
}
delay(50);
}
See more usages in examples
folder.
The control panel embed a GIANTPLUS ILI9163C screen driven by 8-bit parallel interface.
This library is not a GFX library. You can rely on Adafruit GFX library derivatives, such as the excellent MCUFRIEND_kbv library.
Bellow an adaptation using MCUFRIEND_kbv library, examples/display
and examples/full
are based on.
- PlatformIO users:
- Require
patch
tool installed in your system. - Copy
pio-tools/patches.py
andpatches/
folder to the root of your project. - Adding this line to your
platformio.ini
:
lib_deps =
prenticedavid/MCUFRIEND_kbv @ ^3
adafruit/Adafruit GFX Library @ ^1
adafruit/Adafruit BusIO @ ^1
Wire
SPI
extra_scripts = pre:pio-tools/patches.py
- Other users:
- Download MCUFRIEND_kbv v3
- Apply
patch
command with diff files provided inpatches/
folder:
patch MCUFRIEND_kbv/MCUFRIEND_kbv.cpp patches/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp
patch MCUFRIEND_kbv/utility/mcufriend_special.h patches/MCUFRIEND_kbv/utility/mcufriend_special.h
patch MCUFRIEND_kbv/utility/mcufriend_shield.h patches/MCUFRIEND_kbv/utility/mcufriend_shield.h
Nice! Now your code requires this final steps:
- Definition for
Epson_PNL_CE02 controlPanel(...)
- Turn display ON before INIT:
controlPanel.extenderWrite(ExtenderPin::LCD_BACKLIGHT, HIGH);
tft.begin(0x9163);
#include <Epson_PNL_CE02.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
Epson_PNL_CE02_Pinout pinout = {
/* Control panel to Arduino pinout */
.EXTENDER_OE = 45, // FFC 1
.SERIAL_OUT = 50, // SPI MISO / FFC 2
.POWER_BUTTON = 46, // FFC 4
.LCD_RESET = 47, // FFC 6
.CLOCK = 52, // SPI SCK / FFC 9
.SERIAL_IN = 51, // SPI MOSI / FFC 10
.LATCH = 48, // FFC 11
.LCD_WRITE = 49, // FFC 13
};
Epson_PNL_CE02 controlPanel(&pinout);
MCUFRIEND_kbv tft;
void setup()
{
controlPanel.begin();
// STEP 1: Turn display ON
controlPanel.extenderWrite(ExtenderPin::LCD_BACKLIGHT, HIGH);
// STEP 2: INIT display
tft.begin(0x9163); // Force ILI9163C as the control panel wired the display in write-only mode
// STEP 3: Use display
tft.fillScreen(TFT_RED);
tft.setCursor(5, 5);
tft.setTextColor(TFT_BLACK);
tft.print("Hello World");
}
void loop()
{
delay(1000);
}
Member | Pin | Description |
---|---|---|
EXTENDER_OE |
#1 | Extender output enable pin. Unused. |
SERIAL_OUT |
#2 | Serial output pin. Read value for buttons. (SPI MISO) |
POWER_BUTTON |
#4 | Dedicated pin for the power button. |
LCD_RESET |
#6 | Display reset pin. Refer to "Using display" section. |
CLOCK |
#9 | Shared clock pin for extender, buttons and display. (SPI SCK) |
SERIAL_IN |
#10 | Serial input pin. Write value in extender. (SPI MOSI) |
LATCH |
#11 | Write extender selector. |
LCD_WRITE |
#13 | Display write pin. Refer to "Using display" section. |
Parameter | Description |
---|---|
pPinout |
Reference to Epson_PNL_CE02_Pinout . |
Function | Description |
---|---|
void begin() |
Set pins directions and initialize SPI bus. |
void extenderWrite(ExtenderPin pin, byte mode) |
Write a HIGH or a LOW value to the control panel extender pin (refer to ExtenderPin ). |
void displayWrite(byte data) |
Write parallel data (D0-D7) to the display. |
byte readButtons() |
Read current pressed buttons in 8-bit sequence (0 : no pressed, 1 : pressed, refer to ButtonMask ). |
bool isPowerButtonPressed() |
Determine if the power button is pressed or not. The power button has a dedicated pin. |
Function | Description |
---|---|
char[] buttonName(ButtonMask mask) |
Get button name (refer to ButtonMask ). |
bool isButtonPressed(byte sequence, ButtonMask mask) |
Determines if a button is pressed in the 8-bit sequence (refer to ButtonMask ). |
Button | Mask |
---|---|
HOME |
00000001 |
STOP |
00000010 |
DOWN |
00000100 |
START |
00001000 |
LEFT |
00010000 |
UP |
00100000 |
OK |
01000000 |
RIGHT |
10000000 |
POWER |
The power button has a dedicated pin (refer to Epson_PNL_CE02_Pinout Struct ) |
Pin | Active | Description |
---|---|---|
POWER_LED |
LOW |
Control the state of the power led. |
LCD_BACKLIGHT |
HIGH |
Control the state of the display backlight. |
LCD_CS |
HIGH |
Control the state of the display CS pin (ChipSelect). |
LCD_DC |
HIGH |
Control the state of the display D/C pin (Data / Command). |
Thanks @phooky for your inspiring guide!
Examples uses:
- @mathertel's OneButton library (BSD license).
- @prenticedavid's MCUFRIEND_kbv library (BSD license).
- Adafruit team for Adafruit-GFX-Library library (BSD license).
And... EPSON for the control panel 😉
⭐ Star this project to provide better visibility to the community!
💻 Support this project by purchasing affiliated hardwares
Thank you!