Skip to content
vancevojPublic

About

RC plane flown from a laptop over LoRa, C class final that got out of hand

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rc-plane

flying an RC plane from my laptop keyboard, over LoRa.

this started as the final project for my C programming class (ECE 22900 at PFW). everything had to be written in C, and by the time the semester ended I liked it too much to let it sit, so I've kept building on it since.

how it works

three programs, all C, talking through one shared packet format:

  • controller/ runs on the laptop. reads the keyboard in raw mode, packs the control state into a 13-byte packet, and ships it out over USB serial. there's a single live status line in the terminal showing throttle, control surfaces, round-trip time, and dropped packets.
  • firmware_bridge/ runs on a Heltec V3 (ESP32-S3 + SX1262) plugged into the laptop. it takes packets off the USB UART and retransmits them over LoRa at 915 MHz. it also timestamps every packet it sends and waits for the plane to echo it back, which is how the laptop knows the real round-trip latency.
  • firmware/ runs on a second Heltec V3 mounted on the plane. receives packets, drives the servos and ESC with PWM, mirrors the link state on the little OLED, and echoes packets back for the latency measurement.

the wire format and CRC live in common/packet.c so the laptop and both boards parse the exact same bytes. no chance of the three drifting apart.

the packet

13 bytes, little endian:

bytes field notes
0 magic 0xA5 sync byte
1 seq wraps every 256
2-3 throttle 0..1000
4-5 aileron -500..500
6-7 elevator -500..500
8-9 rudder -500..500
10 flags bit0 ARMED, bit1 LED
11-12 crc CRC-16-CCITT over bytes 0..10

the plane drops anything with a bad magic byte, a bad CRC, or a stale sequence number. if 500 ms pass without a good packet it fails safe: throttle to zero, surfaces neutral. that part got tested a lot (on the bench, on purpose, mostly).

latency

round trip from keypress to servo and back is usually 25 to 35 ms at SF7 / 500 kHz bandwidth. about 14 ms of that is just LoRa time on air for the 13-byte payload, the rest is UART and processing. good enough to feel immediate.

building

laptop side is plain make:

cd controller
make
./controller             # /dev/ttyUSB0 by default
./controller --dry-run   # no serial, handy for testing keys

flags: --port DEV, --log PATH (CSV flight log), --rate HZ, --dry-run.

both firmwares are ESP-IDF v5.3 projects:

cd firmware          # or firmware_bridge
idf.py build
idf.py -p /dev/ttyUSB0 flash

pin defaults match the Heltec V3. if your board differs, the #defines are at the top of each main/*.c.

keys

WASD-ish. edit BINDINGS[] at the top of controller/src/main.c to remap.

key action
W / S throttle up / down
Q / E aileron
Space / LShift elevator
A / D rudder
G / B arm / disarm
T trim reset
L toggle plane LED
Esc quit

hardware

  • 2x Heltec WiFi LoRa 32 V3
  • standard 9g hobby servos (SG90 etc.) on 5 V, signal straight from the ESP32 GPIO
  • any servo-PWM ESC for the motor

what's next

the plan is to close the loop: IMU and barometer on the plane, and eventually let it hold position on its own instead of me mashing WASD. the link layer here is the foundation for that.

About

RC plane flown from a laptop over LoRa, C class final that got out of hand

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages