Skip to content

Library to repurposing the control panel of EPSON XP 520/530/540 printers from an Arduino.

License

Notifications You must be signed in to change notification settings

XavierBrassoud/Arduino_Epson_PNL_CE02

Repository files navigation

Arduino - EPSON XP 520/530/540 Control Panel (PNL CE02)

logo

Library to repurposing the control panel (PNL CE02) of EPSON XP 520/530/540 printers from an Arduino.

Motivation

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!

Installation

Hardware requirements

Connecting the control panel

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

Connecting diagram for Arduino MEGA 2560

connecting_diagram_mega_2560

Let's play!

examples/buttons:

#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.

Using display

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.

  1. Require patch tool installed in your system.
  2. Copy pio-tools/patches.py and patches/ folder to the root of your project.
  3. 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:
  1. Download MCUFRIEND_kbv v3
  2. Apply patch command with diff files provided in patches/ 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:

  1. Definition for Epson_PNL_CE02 controlPanel(...)
  2. Turn display ON before INIT:
controlPanel.extenderWrite(ExtenderPin::LCD_BACKLIGHT, HIGH);
tft.begin(0x9163);

examples/display:

#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);
}

Library documentation

Epson_PNL_CE02_Pinout Struct

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.

Epson_PNL_CE02 Class

Constructor

Parameter Description
pPinout Reference to Epson_PNL_CE02_Pinout.

Functions

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.

Utils

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).

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)

ExtenderPin

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).

Credits

Thanks @phooky for your inspiring guide!

Examples uses:

And... EPSON for the control panel 😉

Like this project? ❤️

Star this project to provide better visibility to the community!

💻 Support this project by purchasing affiliated hardwares

Buy me a coffee

Thank you!