2026-02-11 14:33:10 -07:00
|
|
|
|
# BLE Bridge Wiring — ESP32-S3 + 2× MAX485
|
|
|
|
|
|
|
2026-02-11 14:51:48 -07:00
|
|
|
|
Transparent BLE-to-RS422 bridge for the Winegard Carryout G2 satellite dish,
|
|
|
|
|
|
with optional IMU and barometric sensors for orientation and refraction correction.
|
2026-02-11 14:33:10 -07:00
|
|
|
|
|
|
|
|
|
|
## Parts
|
|
|
|
|
|
|
2026-02-11 14:51:48 -07:00
|
|
|
|
**Bridge (required):**
|
2026-02-11 14:33:10 -07:00
|
|
|
|
- ESP32-S3-DevKitC-1-N16R8
|
|
|
|
|
|
- 2× MAX485 TTL-to-RS485 module
|
|
|
|
|
|
- 1× SparkFun Bidirectional Logic Level Converter (BOB-12009, BSS138-based)
|
|
|
|
|
|
- RJ-12 6P6C straight-wired cable with breakout
|
|
|
|
|
|
- Hookup wire / jumpers
|
|
|
|
|
|
|
2026-02-11 14:51:48 -07:00
|
|
|
|
**Sensors (optional):**
|
|
|
|
|
|
- 1× GY-9250 (MPU-9250) — 9-axis IMU (accelerometer + gyroscope + magnetometer)
|
|
|
|
|
|
- 1× BMP388 — barometric pressure + temperature
|
2026-02-11 15:47:20 -07:00
|
|
|
|
- 1× RYS352A GPS module — observer location + PPS timing
|
2026-02-11 14:51:48 -07:00
|
|
|
|
|
2026-02-11 14:33:10 -07:00
|
|
|
|
## Schematic
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
SparkFun Level Converter (BOB-12009)
|
|
|
|
|
|
┌──────────────────────────────────────┐
|
|
|
|
|
|
│ │
|
|
|
|
|
|
ESP32 3V3 ──────────────►│ LV HV │◄── ESP32 5V
|
|
|
|
|
|
ESP32 GND ──────────────►│ GND GND │◄── (shared)
|
|
|
|
|
|
│ │
|
|
|
|
|
|
ESP32 GPIO17 (TX) ──────►│ LV1 HV1 │──────► MAX485₁ DI
|
|
|
|
|
|
ESP32 GPIO18 (RX) ◄──────│ LV2 HV2 │◄────── MAX485₂ RO
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ LV3 (spare) HV3 (spare) │
|
|
|
|
|
|
│ LV4 (spare) HV4 (spare) │
|
|
|
|
|
|
└──────────────────────────────────────┘
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MAX485 Board 1 (TX only) MAX485 Board 2 (RX only)
|
|
|
|
|
|
┌────────────────────────┐ ┌────────────────────────┐
|
|
|
|
|
|
│ VCC ◄── 5V │ │ VCC ◄── 5V │
|
|
|
|
|
|
│ GND ◄── GND │ │ GND ◄── GND │
|
|
|
|
|
|
│ │ │ │
|
|
|
|
|
|
│ DI ◄── HV1 │ │ RO ──► HV2 │
|
|
|
|
|
|
│ RO (unused) │ │ DI (unused) │
|
|
|
|
|
|
│ │ │ │
|
|
|
|
|
|
│ DE ◄── 5V ┐ locked │ │ DE ◄── GND ┐ locked │
|
|
|
|
|
|
│ RE ◄── 5V ┘ TX mode │ │ RE ◄── GND ┘ RX mode │
|
|
|
|
|
|
│ │ │ │
|
|
|
|
|
|
│ A ───────────────────┼──► pin 2 │ A ◄──────────────────┼── pin 4
|
|
|
|
|
|
│ B ───────────────────┼──► pin 3 │ B ◄──────────────────┼── pin 5
|
|
|
|
|
|
└────────────────────────┘ └────────────────────────┘
|
|
|
|
|
|
|
|
|
|
|
|
RJ-12 to Carryout G2
|
|
|
|
|
|
┌───────────────────────────┐
|
|
|
|
|
|
│ Pin 1 (White) ── GND │◄── ESP32 GND
|
|
|
|
|
|
│ Pin 2 (Red) ── TX+/TA │◄── A₁
|
|
|
|
|
|
│ Pin 3 (Black) ── TX-/TB │◄── B₁
|
|
|
|
|
|
│ Pin 4 (Yellow) ── RX+/RA │──► A₂
|
|
|
|
|
|
│ Pin 5 (Green) ── RX-/RB │──► B₂
|
|
|
|
|
|
│ Pin 6 (Blue) ── N/C │
|
|
|
|
|
|
└───────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Power Rails
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
ESP32 5V ──┬── Level Converter HV
|
|
|
|
|
|
├── MAX485₁ VCC
|
|
|
|
|
|
├── MAX485₁ DE + RE (tied high = TX mode)
|
|
|
|
|
|
└── MAX485₂ VCC
|
|
|
|
|
|
|
|
|
|
|
|
ESP32 3V3 ─── Level Converter LV
|
|
|
|
|
|
|
|
|
|
|
|
ESP32 GND ─┬── Level Converter GND
|
|
|
|
|
|
├── MAX485₁ GND
|
|
|
|
|
|
├── MAX485₂ GND
|
|
|
|
|
|
├── MAX485₂ DE + RE (tied low = RX mode)
|
|
|
|
|
|
└── RJ-12 Pin 1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## RJ-12 Cable Notes
|
|
|
|
|
|
|
|
|
|
|
|
Straight-wired 6P6C. Pin 1 is leftmost when looking at the jack with the clip
|
|
|
|
|
|
facing away from you (tab down). Wire colors per the standard flat cable:
|
|
|
|
|
|
|
|
|
|
|
|
| Pin | Color | Function | Connects to |
|
|
|
|
|
|
|-----|--------|------------------|--------------------|
|
|
|
|
|
|
| 1 | White | GND | Common ground |
|
|
|
|
|
|
| 2 | Red | TX+ (TA) | MAX485₁ A |
|
|
|
|
|
|
| 3 | Black | TX- (TB) | MAX485₁ B |
|
|
|
|
|
|
| 4 | Yellow | RX+ (RA) | MAX485₂ A |
|
|
|
|
|
|
| 5 | Green | RX- (RB) | MAX485₂ B |
|
|
|
|
|
|
| 6 | Blue | N/C | — |
|
|
|
|
|
|
|
|
|
|
|
|
If crimping your own cable, verify pin-to-color with a multimeter before
|
|
|
|
|
|
connecting to the dish. RJ-12 crimps are easy to get reversed (pins mirror
|
|
|
|
|
|
if the connector is flipped). A wrong connection won't damage anything
|
|
|
|
|
|
(differential signals are current-limited) but communication won't work.
|
|
|
|
|
|
|
|
|
|
|
|
## How It Works
|
|
|
|
|
|
|
|
|
|
|
|
The Carryout G2 uses RS-422 full-duplex: two separate differential pairs,
|
|
|
|
|
|
one for each direction. The MAX485 is a half-duplex RS-485 transceiver with
|
|
|
|
|
|
a shared A/B pair and direction control pins (DE/RE). By hardwiring DE/RE,
|
|
|
|
|
|
each board is locked into a single direction:
|
|
|
|
|
|
|
|
|
|
|
|
- **Board 1 (TX):** DE=HIGH, RE=HIGH → driver always enabled, receiver disabled.
|
|
|
|
|
|
ESP32 UART1 TX → level shifter → DI → differential A/B → G2 serial RX.
|
|
|
|
|
|
|
|
|
|
|
|
- **Board 2 (RX):** DE=LOW, RE=LOW → driver disabled, receiver always enabled.
|
|
|
|
|
|
G2 serial TX → differential A/B → RO → level shifter → ESP32 UART1 RX.
|
|
|
|
|
|
|
|
|
|
|
|
The SparkFun level converter translates between 3.3V (ESP32) and 5V (MAX485)
|
|
|
|
|
|
on both data lines. The two spare channels (LV3/HV3, LV4/HV4) are available
|
|
|
|
|
|
if DE/RE ever need GPIO control for a half-duplex variant.
|
|
|
|
|
|
|
|
|
|
|
|
## Firmware
|
|
|
|
|
|
|
|
|
|
|
|
See `firmware/ble-bridge/` — transparent BLE Nordic UART Service (NUS) bridge.
|
|
|
|
|
|
The firmware is the same regardless of whether the RS-422 transceiver is a
|
|
|
|
|
|
MAX490 (single full-duplex chip) or two MAX485s (locked half-duplex pair).
|
|
|
|
|
|
It only sees UART TX/RX on GPIO17/18.
|
|
|
|
|
|
|
2026-02-11 14:51:48 -07:00
|
|
|
|
## Sensors — I2C Bus
|
|
|
|
|
|
|
|
|
|
|
|
The MPU-9250 and BMP388 share a single I2C bus on GPIO8 (SDA) / GPIO9 (SCL).
|
|
|
|
|
|
Both run at 3.3V directly from the ESP32, no level shifting needed.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
I2C Bus (3.3V, 400kHz)
|
|
|
|
|
|
─────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
ESP32 3V3 ──┬──────────────────┬─── MPU-9250 VCC
|
|
|
|
|
|
│ └─── BMP388 VCC
|
|
|
|
|
|
│
|
|
|
|
|
|
├── 4.7KΩ ── SDA bus ──┬── MPU-9250 SDA
|
|
|
|
|
|
│ └── BMP388 SDI
|
|
|
|
|
|
│
|
|
|
|
|
|
└── 4.7KΩ ── SCL bus ──┬── MPU-9250 SCL
|
|
|
|
|
|
└── BMP388 SCK
|
|
|
|
|
|
|
|
|
|
|
|
ESP32 GPIO8 (SDA) ──── SDA bus
|
|
|
|
|
|
ESP32 GPIO9 (SCL) ──── SCL bus
|
|
|
|
|
|
|
|
|
|
|
|
ESP32 GND ──┬── MPU-9250 GND
|
|
|
|
|
|
└── BMP388 GND (SDO to GND = addr 0x76)
|
|
|
|
|
|
|
|
|
|
|
|
MPU-9250 AD0 ── GND (I2C address = 0x68)
|
|
|
|
|
|
BMP388 SDO ── GND (I2C address = 0x76)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The 4.7KΩ pull-ups are shared — one pair for the whole bus. Many breakout
|
|
|
|
|
|
boards include onboard pull-ups already; if both the GY-9250 and BMP388
|
|
|
|
|
|
boards have them, the combined parallel resistance (~2.3KΩ) is still fine
|
|
|
|
|
|
for 400kHz I2C at 3.3V. Only add external pull-ups if neither board has them.
|
|
|
|
|
|
|
|
|
|
|
|
### MPU-9250 (GY-9250) — 9-Axis IMU
|
|
|
|
|
|
|
|
|
|
|
|
| I2C Address | 0x68 (AD0 → GND) |
|
|
|
|
|
|
|-------------|-------------------|
|
|
|
|
|
|
| VCC | 3-5V (onboard LDO) |
|
|
|
|
|
|
| Interface | I2C (up to 400kHz) or SPI |
|
|
|
|
|
|
|
|
|
|
|
|
**What it provides for satellite tracking:**
|
|
|
|
|
|
|
|
|
|
|
|
- **Magnetometer (AK8963):** Compass heading for automatic north alignment.
|
|
|
|
|
|
Eliminates manual alignment of dish base "BACK" marking to true north.
|
|
|
|
|
|
Apply local magnetic declination to convert magnetic north → true north.
|
|
|
|
|
|
- **Accelerometer:** Gravity vector → tilt angle = elevation. Independent
|
|
|
|
|
|
verification of the dish firmware's reported EL position.
|
|
|
|
|
|
- **Gyroscope:** Angular rate during slews. Detect oscillation, overshoot,
|
|
|
|
|
|
and vibration for tuning the leapfrog overshoot compensation algorithm.
|
|
|
|
|
|
|
|
|
|
|
|
**Mounting considerations:** The magnetometer is extremely sensitive to nearby
|
|
|
|
|
|
ferrous metals and electromagnetic interference from motors. Mount on the
|
|
|
|
|
|
fixed base plate, away from motor housings, with a known axis aligned to the
|
|
|
|
|
|
dish's reference direction. Rigid mounting — any flex between sensor and dish
|
|
|
|
|
|
structure introduces measurement error.
|
|
|
|
|
|
|
|
|
|
|
|
### BMP388 — Barometric Pressure + Temperature
|
|
|
|
|
|
|
|
|
|
|
|
| I2C Address | 0x76 (SDO → GND) |
|
|
|
|
|
|
|-------------|-------------------|
|
|
|
|
|
|
| VCC | 3.3V |
|
|
|
|
|
|
| Pressure range | 300-1250 hPa |
|
|
|
|
|
|
| Pressure resolution | ±0.01 hPa (±8 cm altitude) |
|
|
|
|
|
|
| Temperature accuracy | ±0.5°C |
|
|
|
|
|
|
| Interface | I2C (up to 3.4MHz) or SPI |
|
|
|
|
|
|
|
|
|
|
|
|
**What it provides for satellite tracking:**
|
|
|
|
|
|
|
|
|
|
|
|
- **Atmospheric refraction correction.** Radio signals bend as they pass
|
|
|
|
|
|
through the atmosphere, especially at low elevation angles. The amount of
|
|
|
|
|
|
bending depends on air pressure and temperature. At 15° elevation (the
|
|
|
|
|
|
Trav'ler's minimum), refraction shifts apparent position by ~0.2°.
|
|
|
|
|
|
Standard refraction models (Bennett, Saemundsson) take pressure and
|
|
|
|
|
|
temperature as inputs — the BMP388 provides both in real time.
|
|
|
|
|
|
- **Temperature monitoring.** Ambient temperature at the dish for thermal
|
|
|
|
|
|
drift awareness and electronics health monitoring.
|
|
|
|
|
|
|
|
|
|
|
|
**Refraction formula (simplified Bennett):**
|
|
|
|
|
|
```
|
|
|
|
|
|
R = 1/tan(el + 7.31/(el + 4.4)) × (P/1010) × (283/(273 + T))
|
|
|
|
|
|
```
|
|
|
|
|
|
Where R is refraction in arcminutes, el is apparent elevation in degrees,
|
|
|
|
|
|
P is pressure in hPa, T is temperature in °C. At el=15°, P=1013, T=20°C:
|
|
|
|
|
|
R ≈ 3.4 arcmin ≈ 0.057°. Small but meaningful for narrow-beam antennas.
|
|
|
|
|
|
|
2026-02-11 15:47:20 -07:00
|
|
|
|
## GPS — RYS352A
|
|
|
|
|
|
|
|
|
|
|
|
The RYS352A is a compact GPS module with PPS output. It connects via UART2 and
|
|
|
|
|
|
provides observer location for satellite pass prediction and a 1Hz PPS pulse
|
|
|
|
|
|
for precise UTC time synchronization.
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
ESP32 GPIO5 (UART2 RX) ◄── RYS352A TX (NMEA sentences out)
|
|
|
|
|
|
ESP32 GPIO6 (UART2 TX) ──► RYS352A RX (config commands in, optional)
|
|
|
|
|
|
ESP32 GPIO7 ◄── RYS352A PPS (1Hz rising edge, ~100ns jitter)
|
|
|
|
|
|
ESP32 3V3 ──► RYS352A VCC
|
|
|
|
|
|
ESP32 GND ──► RYS352A GND
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
| Module Pin | ESP32 Pin | Function |
|
|
|
|
|
|
|------------|-----------|----------|
|
|
|
|
|
|
| VCC | 3V3 | 3.3V power (onboard LDO on most breakouts) |
|
|
|
|
|
|
| GND | GND | Ground |
|
2026-02-11 16:06:31 -07:00
|
|
|
|
| TX | GPIO5 (UART2 RX) | NMEA sentence output at 115200 baud |
|
2026-02-11 16:11:44 -07:00
|
|
|
|
| RX | GPIO6 (UART2 TX) | PAIR/NMEA config input (optional) |
|
2026-02-11 15:47:20 -07:00
|
|
|
|
| PPS | GPIO7 | 1Hz pulse synchronized to GPS time |
|
|
|
|
|
|
|
|
|
|
|
|
**PPS (Pulse Per Second):** The RYS352A outputs a precise 1Hz pulse on the
|
|
|
|
|
|
rising edge, synchronized to UTC via GPS constellation. The firmware captures
|
|
|
|
|
|
this edge via interrupt (`micros()` timestamp) for correlating satellite events
|
|
|
|
|
|
with sub-microsecond precision relative to the GPS epoch. The module's RTC
|
|
|
|
|
|
battery backup enables warm starts (~5s) after initial cold start fix (~30-60s).
|
|
|
|
|
|
|
2026-02-11 16:11:44 -07:00
|
|
|
|
**UART notes:** The RYS352A defaults to 115200 baud NMEA output with `GN`
|
2026-02-11 18:28:59 -07:00
|
|
|
|
talker ID (multi-constellation). The TX line (GPIO6) is used at boot to send
|
|
|
|
|
|
`$PAIR` proprietary commands (Airoha AG3352 engine) that configure the GPS
|
|
|
|
|
|
module for satellite tracking use. See `docs/RYS352x_PAIR_Command_Guide.md`
|
|
|
|
|
|
for the full command reference.
|
|
|
|
|
|
|
|
|
|
|
|
**Boot-time PAIR init sequence:** The firmware sends `$PAIR062` commands at
|
|
|
|
|
|
startup to filter NMEA output — only GGA (position/quality), GSA (fix mode/DOP),
|
|
|
|
|
|
RMC (time/date/speed), and GSV (satellite visibility, every 5th fix) are enabled.
|
|
|
|
|
|
Redundant sentences (GLL, VTG, ZDA, GRS, GST, GNS) are disabled to reduce parser
|
|
|
|
|
|
load and latency. A `$PAIR752` command configures PPS to pulse only on 2D/3D fix
|
|
|
|
|
|
with 100ms pulse width. Each command waits for `$PAIR001` ACK; failures are
|
|
|
|
|
|
logged but non-fatal — the GPS works with defaults if PAIR commands are unsupported.
|
|
|
|
|
|
|
|
|
|
|
|
The firmware uses TinyGPS++ v1.1+ with custom field extractors (`TinyGPSCustom`)
|
|
|
|
|
|
to read GGA quality (field 6: SPS/DGPS/RTK) and GSA nav mode (field 2: 2D/3D)
|
|
|
|
|
|
directly from the NMEA stream, replacing the earlier heuristic that inferred
|
|
|
|
|
|
fix type from altitude validity. Both `GN` and `GP` talker ID variants are
|
|
|
|
|
|
registered for compatibility across constellation configurations.
|
2026-02-11 15:47:20 -07:00
|
|
|
|
|
2026-02-11 14:51:48 -07:00
|
|
|
|
## Full GPIO Map
|
|
|
|
|
|
|
|
|
|
|
|
| GPIO | Function | Interface | Notes |
|
|
|
|
|
|
|------|----------|-----------|-------|
|
2026-02-11 15:47:20 -07:00
|
|
|
|
| 5 | GPS RX | UART2 RX | ← RYS352A TX (NMEA out) |
|
|
|
|
|
|
| 6 | GPS TX | UART2 TX | → RYS352A RX (config in) |
|
|
|
|
|
|
| 7 | GPS PPS | GPIO interrupt | 1Hz rising edge |
|
2026-02-11 14:51:48 -07:00
|
|
|
|
| 8 | I2C SDA | I2C | MPU-9250 + BMP388 (shared bus) |
|
|
|
|
|
|
| 9 | I2C SCL | I2C | MPU-9250 + BMP388 (shared bus) |
|
2026-02-11 15:47:20 -07:00
|
|
|
|
| 17 | RS-422 TX | UART1 TX | → Level shifter → MAX485₁ DI |
|
|
|
|
|
|
| 18 | RS-422 RX | UART1 RX | ← Level shifter ← MAX485₂ RO |
|
2026-02-11 14:51:48 -07:00
|
|
|
|
| 38 | RGB LED | WS2812 | Onboard NeoPixel (DevKitC V1.1) |
|
|
|
|
|
|
| 43 | USB Console TX | UART0 | CH343 USB-serial (untouched) |
|
|
|
|
|
|
| 44 | USB Console RX | UART0 | CH343 USB-serial (untouched) |
|
|
|
|
|
|
|
2026-02-11 14:33:10 -07:00
|
|
|
|
## Loopback Test (no dish)
|
|
|
|
|
|
|
|
|
|
|
|
Before connecting to the G2, verify the bridge by shorting MAX485₁ A to
|
|
|
|
|
|
MAX485₂ A, and MAX485₁ B to MAX485₂ B (loop TX back into RX). Anything
|
|
|
|
|
|
sent via BLE or USB serial should echo back.
|