rpycrsf
Python library to control CRSF (Crossfire/ELRS) based drones from a Raspberry Pi.
rpycrsf opens the Pi's UART, packs stick/switch positions into CRSF
RC_CHANNELS_PACKED frames, and streams them to the flight controller from
a background thread at a steady rate — so the link doesn't drop into
failsafe just because your script is busy doing something else.
Install
pip install rpycrsf
Or from a checkout:
pip install -e .
Raspberry Pi setup
- Enable the hardware UART:
sudo raspi-config→ Interface Options → Serial Port → disable the login shell over serial, enable the hardware port. - On boards where Bluetooth uses the primary UART (Pi 3 / Pi 4 / Zero W),
add
dtoverlay=disable-btto/boot/firmware/config.txt(or/boot/config.txt) andsudo systemctl disable hciuartso the PL011 UART is freed up for/dev/serial0instead of being routed to Bluetooth via the slower mini-UART. - Add your user to the
dialoutgroup so you don't needsudoto open the port:sudo usermod -aG dialout $USER(log out/in to take effect). - Wire the CRSF TX module's UART RX/TX to the Pi's TX/GPIO14 and RX/GPIO15 pins (cross them: Pi TX → module RX, Pi RX → module TX), plus a common ground.
- Use
/dev/serial0as the device — it's a symlink to the correct UART for your board.
Usage
import time
from rpycrsf import Drone
with Drone("/dev/serial0") as d:
d.arm(True)
d.set_mode(True) # AUX2 -> angle mode
d.set_sticks(throttle=0.5, roll=0.0, pitch=0.1, yaw=0.0)
time.sleep(5)
# `close()` (called automatically by the `with` block) disarms and stops
# the sender thread before the port closes.
Drone starts a background thread on construction that resends the
current channel state at update_rate_hz (150 Hz by default). Calling
arm(), set_mode(), or set_sticks() only updates in-memory state —
you don't need to call send() yourself in normal use; it exists for
cases where you want a change reflected on the wire immediately instead
of waiting for the next scheduled tick.
API
Drone(device, baudrate=420000, update_rate_hz=150.0, auto_start=True)arm(armed: bool)— AUX1set_mode(angle: bool)— AUX2set_althold(enabled: bool)— AUX3 (BetaflightALTHOLDmode range)set_sticks(roll=0.0, pitch=0.0, yaw=0.0, throttle=0.0)— roll/pitch/yaw are-1.0..1.0, throttle is0.0..1.0send()— force an immediate transmitstart()/stop()— control the background sender threadclose()— disarm, stop the thread, close the port (called by__exit__)
See examples/basic_arm.py for a runnable example.
Lower level frame packing/CRC helpers and a raw CRSFPort (for sending
custom frame types or reading telemetry) are available under
rpycrsf.protocol if you need to go below the Drone API.
Development
pip install -e ".[dev]"
pytest
Metadata
Release files for rpycrsf 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| rpycrsf-0.1.0.tar.gz | 10.9 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rpycrsf-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.1 kB
Release files / rpycrsf-0.1.0.tar.gz
| Download URL | rpycrsf-0.1.0.tar.gz |
|---|---|
| Size | 10.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ac74ab91dfeb819a96e6cf634926aa5e94a5334ec93df7e1cc72571b36d1180b
|
|
BLAKE2b-256 checksum How to use checksums |
3293abcaad31b78d509f272c464d55697b10d49144b44da89253b4681e05fc3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.
Transparency logRelease files / rpycrsf-0.1.0-py3-none-any.whl
| Download URL | rpycrsf-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87906a9ea2c98f89a2cd3f2484fce7a217beff4bbb57a7c5c34aec9eb49b14e7
|
|
BLAKE2b-256 checksum How to use checksums |
42345a91b8669d51b068d835cb0a0a832297a4f2c0057ee07b07f741324a29f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.
Transparency logSecurity for rpycrsf 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for rpycrsf-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.