Epson Projector RS232 Hex Codes: ESC/VP21 Byte by Byte
Epson does not have a separate "hex protocol". ESC/VP21 commands are ASCII text ending in a carriage return, and the hex codes are simply those same characters written as bytes: PWR? plus CR is 50 57 52 3F 0D on the wire, whichever way your controller lets you type it. Three bytes frame every exchange — 0D ends a command, 3A (a colon) means the projector is ready for the next one, and 45 52 52 0D 3A is the ERR reply. The one byte-level trap that catches people is the input code in SOURCE: it is two ASCII characters, not one byte, and its meaning changes from model to model.
This page is the byte-level companion to our Epson projector RS232 commands guide, which covers the ASCII command list, wiring and the colon prompt. Here we only deal with what the bytes look like and where hex entry goes wrong.
Hex and ASCII are the same command
ESC/VP21 is independent of the transport: Epson's command guide says the same commands can be sent over serial, USB or a TCP/IP network. It is plain text, and the guide points out that a projector can be driven from a terminal emulator such as HyperTerminal.
So when would you need hex at all? Only when the thing doing the sending insists on it — a control processor or test tool whose command field accepts hex bytes rather than text. Epson's own European FAQ on network control shows exactly this situation: its example tool can send "either as ASCII or Hexadecimal", and for the hex route it tells you to convert the ASCII command and then add 0d to the end. The two worked examples in that FAQ are:
PWR? = 50 57 52 3f 0d
LAMP? = 4c 41 4d 50 3f 0dReading them byte by byte shows the whole encoding scheme. Each letter is its ASCII code (P = 50, W = 57, R = 52), the question mark that turns a command into a query is 3F, a space between command and parameter is 20, and the carriage return is 0D. There is no length byte, no checksum and no start or end marker. If you want the general background on when a device protocol needs checksums and when it does not, see RS232 command formats: ASCII, hex and checksums.
The three bytes that frame every exchange
0D — the terminator and the null command. Epson's guide defines the null command as the return key code, Hex 0D, on its own. The projector answers it with a colon, and the guide describes it as a way to confirm the projector is in operation. That makes a single 0D the cheapest possible line test.
3A — the colon. A set command (command plus parameter) is answered with a colon once the projector has executed it. The EB-PU2220B user's guide spells out the byte: a colon ":" (3Ah) is returned, and only then does the projector accept the next command. If a command terminates abnormally, an error message is output first and the colon still follows.
45 52 52 0D 3A — the ERR reply. For an invalid command the guide says the projector returns "ERR", then the return key code (Hex 0D), then a colon. On the wire that is five bytes:
TX 0D null command
RX 3A :
TX 50 57 52 20 4F 4E 0D PWR ON<CR>
RX 3A : (after execution)
TX (an invalid command)
RX 45 52 52 0D 3A ERR<CR>:ERR is not only about typos. Epson's guide states that all projectors return ERR when the command format is not good and also when the projector is not ready to reply. On some models the standby state restricts what is accepted: for example, the guide says EMP-61/81/830/835/740/745/821/828 return ERR for anything other than PWR ON, PWR?, LAMP? and the null command. A byte-perfect SOURCE command can therefore still come back as 45 52 52 0D 3A.
For query (get) commands, the guide says the projector returns a response parameter; for PWR? it lists return codes 00 to 05, with each code applying to a specific set of models. The exact byte layout of a complete reply line is not found in Epson's official documentation, so capture a real reply before you hard-code a parser.
Byte table: power, mute, freeze and status queries
Every row ends in 0D. Nothing else is added before or after.
| Command | Purpose | Bytes (hex) |
|---|---|---|
PWR ON | Power on | 50 57 52 20 4F 4E 0D |
PWR OFF | Power off | 50 57 52 20 4F 46 46 0D |
PWR? | Power status | 50 57 52 3F 0D |
LAMP? | Lamp hours | 4C 41 4D 50 3F 0D |
SOURCE? | Current input | 53 4F 55 52 43 45 3F 0D |
MUTE ON | A/V mute on | 4D 55 54 45 20 4F 4E 0D |
MUTE OFF | A/V mute off | 4D 55 54 45 20 4F 46 46 0D |
MUTE? | Mute status | 4D 55 54 45 3F 0D |
FREEZE ON | Freeze on | 46 52 45 45 5A 45 20 4F 4E 0D |
FREEZE OFF | Freeze off | 46 52 45 45 5A 45 20 4F 46 46 0D |
ERR? | Error status | 45 52 52 3F 0D |
| null command | Line test | 0D |
Verification: from-vendor-doc — command names per Epson's ESC/VP21 Command User's Guide; PWR? and LAMP? bytes match Epson's official ESC/VP.net FAQ, the other rows are the ASCII of the documented command strings. Not tested against real hardware in this repo.
Note that the parameters ON and OFF differ in length (4F 4E versus 4F 46 46), so the power-on and power-off strings are seven and eight bytes respectively.
SOURCE codes: two characters, model-specific meaning
The input parameter is where hex entry most often goes wrong. In SOURCE 30, the 30 is sent as two ASCII characters, 3 and 0, which are the bytes 33 30. It is not the single byte 0x30. A code written with a letter, such as B0, becomes 42 30.
SOURCE 30<CR> = 53 4F 55 52 43 45 20 33 30 0D
SOURCE B0<CR> = 53 4F 55 52 43 45 20 42 30 0DThe second trap is meaning. The current Rev.Q guide does not print a source code table at all: it says SOURCE? returns 00 to FF and refers to a separate "all commands list". The older Rev.J guide (2008) does list codes, model by model. Here is how the same codes read across four model groups from that document ("—" means Rev.J lists no such code for that group):
| Code | Bytes after SOURCE | 600/800/810/811/820 | 8300/9300 | 7800/7850 | 54/74 |
|---|---|---|---|---|---|
10 | 31 30 | — | INPUT1 (D-Sub) | INPUT1 (D-Sub) | — |
11 | 31 31 | PC1 (analog RGB) | INPUT1 (analog RGB) | INPUT1 (analog RGB) | RGB |
20 | 32 30 | — | INPUT2 (D-Sub) | — | Input 2 |
21 | 32 31 | PC2 (analog RGB) | INPUT2 (analog RGB) | — | Input 2 (RGB) |
30 | 33 30 | — | INPUT3 (DVI-D) | INPUT3 (DVI-D) | — |
41 | 34 31 | Video (RCA) | Video (RCA) | Video (RCA) | Video (RCA) |
42 | 34 32 | Video (S) | Video (S) | Video (S) | Video (S) |
B0 | 42 30 | — | INPUT4 (BNC) | INPUT4 (BNC) | — |
Each full command is 53 4F 55 52 43 45 20, then the two code bytes, then 0D.
The same Rev.J document lists 30 as INPUT3 (HDMI) for the G5350/G5300/G5150/G5100/G5200W/G5000 group — the same two bytes that mean DVI-D on the 8300/9300. That is why this page gives no universal HDMI code: none of the Epson documents we rely on defines one, and newer user's guides refer you to each model's Specifications for the available commands. The practical method is to select each input by hand, send SOURCE?, and record what that projector reports.
Verification: from-vendor-doc — codes per Epson's ESC/VP21 Command User's Guide Rev.J, for the listed models only; bytes are the ASCII of each code. Not tested against real hardware in this repo.
ESC/VP.net: the only real binary in the stack
Over the network, Epson's guide says ESC/VP21 commands are sent after a TCP session is established, with details in the ESC/VP.net manual. Epson's FAQ has you connect to TCP port 3629 and send this in hex before anything else:
45 53 43 2F 56 50 2E 6E 65 74 10 03 00 00 00 00Epson's ESC/VP.net developer manual defines this 16-byte common header field by field: the first 10 bytes are the text ESC/VP.net; 10 is the version (high four bits major, low four bits minor, so 1.0); 03 is the type CONNECT; the next two bytes are reserved and set to 0; the next byte is the status, always 00 in a request; the last byte is the number of headers that follow, here none. A successful reply differs only in the status byte, which becomes 20:
45 53 43 2F 56 50 2E 6E 65 74 10 03 00 00 20 00After that, the manual says ESC/VP21 commands are transferred directly — the same bytes as in the tables above. The manual also lists non-success statuses for CONNECT (41 password required, 43 wrong password, 53 busy), each followed by the projector closing the connection.
Verification: from-vendor-doc — request bytes per Epson's official ESC/VP.net FAQ, field meanings and the success status per Epson's ESC/VP.net developer manual. Not tested against real hardware in this repo.
Field notes: where hex commands fail
These are the failure modes that follow directly from the byte rules above, in the order worth checking.
- Missing
0D. A hex field sends exactly the bytes you type. Epson's FAQ explicitly tells you to add0d; if the string ends in3For4E, the terminator the protocol requires was never sent. What the projector does with an unterminated string is not found in Epson's official documentation — so do not treat silence as a clue to anything else until the0Dis there.
- Source code sent as one byte.
SOURCE 30ending in20 30 0Dis wrong; it must end in20 33 30 0D.
- Hex header sent on serial. The 16-byte ESC/VP.net header belongs to the TCP session on port 3629. The serial appendix in Epson's guide gives the communication settings (9600 bps, 8 data bits, no parity, 1 stop bit, no flow control) and no header of any kind.
45 52 52 0D 3Acoming back. The bytes arrived. Now separate format from state: send the null command, thenPWR?(50 57 52 3F 0D, straight from Epson's FAQ). If those get colons but your command gets ERR, check whether the projector is in standby and whether your model accepts that command in standby, and whether the input signal was changing — the guide notes thatSOURCEreturns ERR if the signal changes while the projector is recognising it.
- No colon at all, even for
0D. This is no longer a hex problem. Either the link is wrong, or the projector is in an abnormal state (Epson's guide gives lamp failure and abnormal high temperature as examples), in which it neither executes commands nor returns a colon. For the link side, go back to cable and port settings; see Epson projector RS232 baud rate and settings.
SoftControl import snippets
In SoftControl a serial command uses protocol: serial, the COM port in targetIpOrCom and the baud rate in portOrBaud. The serial driver always runs 8 data bits, 1 stop bit, no parity, which matches Epson's documented settings. The payloadFormat field decides how commandText is read: text converts the escape \r into the 0D byte; hex takes space-separated hex bytes. These two commands put identical bytes on the wire:
name: Epson power on
protocol: serial
targetIpOrCom: COM1
portOrBaud: 9600
payloadFormat: text
commandText: PWR ON\rname: Epson power on (hex)
protocol: serial
targetIpOrCom: COM1
portOrBaud: 9600
payloadFormat: hex
commandText: 50 57 52 20 4F 4E 0DAn input switch in hex, using a code you have confirmed with SOURCE? on your own projector (30 shown here only as a byte example):
name: Epson input 30 (hex)
protocol: serial
targetIpOrCom: COM1
portOrBaud: 9600
payloadFormat: hex
commandText: 53 4F 55 52 43 45 20 33 30 0DTwo SoftControl behaviours to plan around. First, the serial driver does not add a CR for you and does not read the reply, so it will not wait for the 3A colon; use a terminal program for the colon checks above. Second, because it does not wait, a power-on followed by an input switch needs the gap set as delayMs on the second command (the wait before that command runs), using the execution time Epson lists for your model. SoftControl's TCP driver does not perform the ESC/VP.net handshake, so do not point it at port 3629.
Verification: from-vendor-doc — bytes per Epson's documentation; there is no Epson project in this repo's real configurations, so these snippets have not been run against a real projector.
Next step
Before typing any hex into a controller, send a single 0D and confirm 3A comes back. Then send 50 57 52 3F 0D. Only after both work is it worth debugging the bytes of a specific command — and for SOURCE, the code must come from the projector in front of you, not from a list written for another model.