Skip to content

Serial Protocol

The Winegard dish variants use two different differential signaling standards. Understanding which one your variant uses is essential for choosing the right USB adapter.

One shared differential pair carries both TX and RX. Only one device talks at a time — the transmitter drives the bus, then releases it so the other side can respond. This is how the Trav’ler IDU communicates with the ODU: the IDU sends a command on the shared T/R pair, then listens for the response on the same wires. Simple wiring (2 signal wires + ground), but throughput is limited by the turn-around time between send and receive.

Two separate differential pairs — one dedicated TX pair and one dedicated RX pair. Both sides can transmit simultaneously because the signals do not share wires. Higher throughput (no bus turnaround penalty), and the Carryout G2 uses this at 115200 baud. Point-to-point only (one transmitter per pair).

Electrically identical to RS-422 wiring (same 4-wire differential pairs), but the RS-485 spec allows multiple transmitters on each pair (multi-drop bus). For our point-to-point dish-to-computer connection, 4-wire RS-485 and RS-422 are interchangeable.

PropertyRS-485 half-duplexRS-422 / RS-485 full-duplex
Signal wires2 (+ GND)4 (+ GND)
DirectionOne direction at a timeBoth directions simultaneously
Max nodes32 drivers + 32 receivers1 driver + 10 receivers (RS-422)
Max distance1200m / 4000ft1200m / 4000ft
Max baud~10 Mbps~10 Mbps
Voltage swing+/-1.5V to +/-5V differential+/-2V to +/-5V differential
Bus turnaroundRequired (adds latency)Not needed
Typical adapterUSB-to-RS485 (DTECH, etc.)USB-to-RS422 (FTDI, DIYables, etc.)
  • RS-485 serial, 57600 baud, 8N1 (Trav’ler variants) or RS-422, 115200 baud, 8N1 (Carryout G2)
  • Motor commands: a <motor_id> <degrees> (0=azimuth, 1=elevation)
  • Position query: a (in motor submenu) returns position in variant-specific format
  • Two motor control methods:
    • a <id> <deg> — queues command, waits for current motor to finish. Tolerant of rapid command streams from Gpredict.
    • g <az> <el> <sk> — immediate move, aborts on any new keystroke/character. Some firmware has a typo listing the order as az/sk/el.
  • Skew motor can run simultaneously with AZ or EL (the others are mutually exclusive)
  • Elevation floor: HAL 2.05 unreliable below 15 degrees with direct motor commands
  • Cable wrap limit: usually 360 or 455 degrees, dish reverses at limit
  • Console does not accept backspace — hit enter to clear on typo
  • Firmware prompt character is > (ASCII 62) — used for reliable response termination in prompt-terminated read strategies
  • Firmware expects ASCII CR (0x0D) as line terminator

The DIYables RS422-to-TTL module uses the MAX490 transceiver chip (2.5 Mbps max, well above the 115200 baud requirement).

  • 5V TTL logic on the microcontroller side (RXD/TXD)
  • 15 kV ESD protection on RS-422 lines
  • TVS diode for lightning/spike suppression
  • 10 ohm current-limiting resistors for overcurrent protection
  • Built-in 120 ohm termination resistor (reduces echo on long runs)
  • Power + TX/RX activity LEDs
  • Board size: 5.0cm x 2.7cm

Workaround options:

  1. Add external bias resistors — pull A/RX+ toward V+ and B/RX- toward GND through ~560 ohm resistors. This biases the idle bus to a known logic-high state (RS-422 “mark” / idle). Solder to the module or add inline on the RJ-12 breakout.

  2. Use the prompt-terminated read strategy — the CarryoutG2Protocol._send() reads until > (ASCII 62) which naturally filters out garbage between commands, since random transitions are unlikely to produce a valid > in context.

  3. Ignore idle noise in firmware — the Winegard firmware likely ignores unexpected input while it is processing or idle, but any bytes received during the bus float could corrupt the next valid command if they land in the UART buffer at the wrong time.

For short cable runs (under ~3m between ESP32 and dish), the built-in 120 ohm termination is sufficient and bus float is less likely to cause issues. For longer runs or electrically noisy environments (near motors, power supplies), add the bias resistors.

Execute once, return a result, and show the prompt (>). Safe to use programmatically.

a
Angle[0] = 180.00
Angle[1] = 45.00
MOT>

Run indefinitely until interrupted. Some accept q to stop, others require closing the serial port. Known streamers include ts, agc, lnbv, snr, qls, nid, and stats.

Reads:1 SNR[avg: 0.0 cur: 0.0]
Reads:2 SNR[avg: 0.0 cur: 0.0]
...

Modify state (motor position, NVS values, fault registers). The firmware provides no confirmation prompts for destructive operations.

The most reliable strategy for programmatic serial communication is to read until the prompt character > (ASCII 62) appears. This is what the CarryoutG2Protocol._send() method does:

def _send(self, cmd: str) -> str:
self._serial.write(f"{cmd}\r".encode("ascii"))
resp_data = bytearray()
while True:
byte = self._serial.read(1)
if len(byte) == 0:
raise TimeoutError(f"No prompt after command: {cmd!r}")
resp_data.append(byte[0])
if byte[0] == 62: # ASCII '>'
break
return resp_data.decode("utf-8", errors="ignore")

This approach handles variable-length responses and is resilient to bus noise, since random garbage is unlikely to produce a valid > in the expected context.