Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ After flashing you need to configure few things first:
* Magnetometers: HMC5883, QMC5883, AK8963, QMC5883P
* Receivers: PPM, SBUS, IBUS, CRSF/ELRS
* Esc Protocols: PWM, BRUSHED, ONESHOT125, ONESHOT42, MULTISHOT, DSHOT150, DSHOT300, DSHOT600
* GPS: M8, M9, F9 & M10(dual band, all constellations configurable by cli)
* Other protocols: MSP, CLI, BLACKBOX, ESPNOW

## Issues
Expand Down
230 changes: 226 additions & 4 deletions docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,225 @@ Then go to the `Receiver` tab, and select `Receiver mode` and `Serial Receiver P

To use ESP-NOW receiver, choose "SPI Rx (e.g. built-in Rx)" receiver mode in Receiver tab. You need compatible transmitter module. Read more about [ESP-FC Wireless Functions](/docs/wireless.md)

## GPS Setup

ESP-FC supports u-blox M8, M9, F9, and M10 GPS modules via UART. M10 modules provide enhanced accuracy with dual-band L1+L5 GNSS support.

### Hardware Connection

1. Connect GPS TX to ESP32 RX pin (e.g., UART2 RX)
2. Connect GPS RX to ESP32 TX pin (e.g., UART2 TX)
3. Connect VCC (3.3V or 5V depending on module) and GND

### Enable GPS Feature

In the `Configuration` tab, under `Other Features`, enable **GPS** or use CLI:

```
set feature_gps 1
save
```

### Configure Serial Port

In the `Ports` tab, enable GPS on the UART connected to your GPS module. Set baud rate to `115200` (recommended for M10) or `230400` for 25Hz update rate.

Alternatively, via CLI:

```
# For UART2 (common GPS port)
serial 1 1024 115200 115200 0 115200
save
```

### Basic GPS Configuration

Go to CLI tab and configure basic GPS settings:

```
# Minimum satellites required for valid fix
set gps_min_sats 8

# Set home only once (0 = update home on each arm)
set gps_set_home_once 1

save
```

### M10 GNSS Configuration (Advanced)

M10 modules support multiple GNSS constellations and dual-band (L1+L5) for better accuracy. Configure via CLI:

#### Quick Preset Modes

```
# Mode 0: Auto (use individual constellation flags) - DEFAULT
set gps_gnss_mode 0

# Mode 1: GPS only (maximum compatibility, lowest power)
set gps_gnss_mode 1

# Mode 2: GPS + GLONASS (good for high latitudes)
set gps_gnss_mode 2

# Mode 3: GPS + Galileo (best accuracy in Europe)
set gps_gnss_mode 3

# Mode 4: GPS + BeiDou (optimized for Asia-Pacific)
set gps_gnss_mode 4

# Mode 5: All constellations (maximum satellites, best accuracy)
set gps_gnss_mode 5

save
reboot
```

#### Dual-Band Configuration (M10 Only)

```
# Enable L1+L5 dual-band on M10 (better multipath rejection)
set gps_enable_dual_band 1

# Disable dual-band (force L1 only for compatibility)
set gps_enable_dual_band 0

save
reboot
```

> [!NOTE]
> M8/M9 modules always use L1 single-band. The `gps_enable_dual_band` setting only affects M10 modules.

#### Individual Constellation Control

When `gps_gnss_mode 0`, you can enable/disable each constellation individually:

```
set gps_enable_gps 1 # GPS (USA)
set gps_enable_glonass 1 # GLONASS (Russia)
set gps_enable_galileo 1 # Galileo (EU)
set gps_enable_beidou 1 # BeiDou (China)
set gps_enable_qzss 1 # QZSS (Japan/Asia-Pacific)
set gps_enable_sbas 1 # SBAS/WAAS/EGNOS augmentation

save
reboot
```

### Configuration Examples

#### Maximum Accuracy (M10 Recommended)
```
set gps_gnss_mode 5 # All constellations
set gps_enable_dual_band 1 # L1+L5 dual-band
save
reboot
```
**Result:** GPS+GLONASS+Galileo+BeiDou+QZSS+SBAS with L1+L5
**Power:** High

#### Balanced Performance (M10)
```
set gps_gnss_mode 3 # GPS + Galileo
set gps_enable_dual_band 1 # L1+L5 for multipath rejection
save
reboot
```
**Result:** GPS+Galileo with L1+L5
**Power:** Medium

#### Battery Saver (Any Module)
```
set gps_gnss_mode 1 # GPS only
set gps_enable_dual_band 0 # L1 only
save
reboot
```
**Result:** GPS only, L1 band
**Power:** Low

#### Urban/City Flying (M10)
```
set gps_gnss_mode 3 # GPS + Galileo
set gps_enable_dual_band 1 # L5 rejects building reflections
save
reboot
```
**Result:** GPS+Galileo with L1+L5
**Power:** Medium

#### Asia-Pacific Optimized (M10)
```
set gps_gnss_mode 0 # Custom mode
set gps_enable_gps 1
set gps_enable_galileo 1
set gps_enable_beidou 1 # Strong in Asia
set gps_enable_qzss 1 # Regional augmentation
set gps_enable_glonass 0 # Disable to save power
set gps_enable_dual_band 1
save
reboot
```
**Result:** GPS+Galileo+BeiDou+QZSS with L1+L5
**Power:** Medium

### Verification

After rebooting, check GPS status in CLI:

```
# View current GPS configuration
get gps

# Check GPS status (in another CLI session or via status command)
status
```

Look for initialization messages in the boot log:

```
GPS DET 115200 # Baud rate detected
GPS VER: 000A0000 # M10 module detected
GPS GNSS L1+L5 [GPS GLO GAL BDS QZSS SBAS] # Configuration applied
GPS RATE 40/1 # 25Hz update rate (M10 at 230400 baud)
GPS UBX # UBX protocol enabled
GPS NAV5 # Navigation mode: Airborne
```

### Troubleshooting

#### No GPS Fix
1. Check antenna has clear sky view (away from carbon fiber, metal)
2. Enable more constellations: `set gps_gnss_mode 5`
3. Wait 2-3 minutes for initial fix (TTFF - Time To First Fix)
4. Verify baud rate matches GPS module (115200 or 230400)

#### GPS Not Detected
1. Check wiring (TX/RX crossed between GPS and FC)
2. Verify serial port configuration in `Ports` tab
3. Try different baud rates (9600, 38400, 57600, 115200, 230400)
4. Check boot logs for `GPS ERROR` or `GPS DET` messages

#### Low Satellite Count
1. Move to open area with clear sky view
2. Enable all constellations: `set gps_gnss_mode 5`
3. Check antenna connection
4. Wait longer for satellites to be acquired

#### M10 Not Using Dual-Band
1. Verify module is actually M10 (check boot log: `GPS VER: 000A0000`)
2. Ensure `gps_enable_dual_band 1` is set
3. Check log for `GPS GNSS L1+L5` (not just `L1`)
4. Some M10 modules need firmware update for L5 support

#### Slow Fix Time

1. Enable more constellations: `set gps_gnss_mode 5`
2. Ensure SBAS is enabled: `set gps_enable_sbas 1`
3. Check for clear sky view (no buildings, trees blocking)
4. First fix always takes longer (cold start), subsequent fixes are faster

## Motor setup

In `Motors` tab you must configure
Expand Down Expand Up @@ -140,14 +359,18 @@ OpenLager can handle it easily. If you plan to use OpenLog, you might need to fl

### Configuration tab

In Other features you can enable only `Dynamic Filter` and `SoftSerial`
In Other features you can enable only `Dynamic Filter`, `GPS`, and `SoftSerial`

`AirMode` is only available in modes tab. If you want to enable it permanently, use the same control channel as ARM.

### Failsafe tab

Only "Drop" Stage 2 procedule is possible

### GPS tab

GPS configuration is currently CLI-only. Use the commands documented in the GPS Setup section above. The GPS tab in Betaflight Configurator shows GPS status but cannot modify GNSS constellation settings.

### Presets tab

Presets aren't supported, do not try to apply any of them.
Expand All @@ -167,7 +390,7 @@ Besides that most of Betaflight principles can be applied here according to PID
### Receiver

1. Not all protocols are implemented, currently only PPM, CRSF, SBUS, IBUS
2. NoOnly CRSF telemetry and and rssi_adc
2. Only CRSF telemetry and rssi_adc
3. RC deadband applies to RPY, no separate Yaw deadband

### Modes
Expand All @@ -192,5 +415,4 @@ Not yet implemented, work in progess

### OSD

Not implemented, but MW_OSD should works via serial port and MSP protocol.

Not implemented, but MW_OSD should works via serial port and MSP protocol.
6 changes: 3 additions & 3 deletions docs/wiring.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ESP-FC wiring examples and PIN mapping

ESP32 MCUs allows to remap pins, so the wiring is not final and you can remap intputs and outputs to your needs. To change pin function go to the CLI and use `get pin` command to check current assignment. For example, to set first output to pin 1 use command
ESP32 MCUs allows to remap pins, so the wiring is not final and you can remap intputs and outputs to your needs. To change pin function go to the CLI and use `get pin` command to check current assignment. For example, to set first output to pin 1 use command

`set pin_output_0 1`

Expand Down Expand Up @@ -54,14 +54,14 @@ Tu unmap pin function use -1 as pin number
| RX 2 | `pin_serial_1_rx` | 32 | 15 |
| TX 2 | `pin_serial_1_tx` | 33 | 16 |
| RX 3 | `pin_serial_2_rx` | 16 | 17 |
| TX 4 | `pin_serial_2_tx` | 17 | 18 |
| TX 3 | `pin_serial_2_tx` | 17 | 18 |

## Default Analog pin mapping

| Uart | CLI name | ESP32 | ESP32-S3 |
|--------:|-------------------|------:|---------:|
| Voltage | `pin_input_adc_0` | 36 | 1 |
| Current | `pin_input_adc_1` | 19 | 4 |
| Current | `pin_input_adc_1` | 39 | 4 |

> [!NOTE]
> On ESP32 choose only pins assigned to ADC1 channels
Expand Down
56 changes: 53 additions & 3 deletions lib/Espfc/src/Connect/Cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ const Cli::Param * Cli::initialize(ModelConfig& c)
Param(PSTR("feature_soft_serial"), &c.featureMask, 6),
Param(PSTR("feature_telemetry"), &c.featureMask, 10),


Param(PSTR("debug_mode"), &c.debug.mode, debugModeChoices),
Param(PSTR("debug_axis"), &c.debug.axis),

Expand Down Expand Up @@ -432,7 +433,16 @@ const Cli::Param * Cli::initialize(ModelConfig& c)

Param(PSTR("gps_min_sats"), &c.gps.minSats),
Param(PSTR("gps_set_home_once"), &c.gps.setHomeOnce),


Param(PSTR("gps_gnss_mode"), &c.gps.gnssMode),
Param(PSTR("gps_enable_dual_band"), &c.gps.enableDualBand),
Param(PSTR("gps_enable_gps"), &c.gps.enableGPS),
Param(PSTR("gps_enable_glonass"), &c.gps.enableGLONASS),
Param(PSTR("gps_enable_galileo"), &c.gps.enableGalileo),
Param(PSTR("gps_enable_beidou"), &c.gps.enableBeiDou),
Param(PSTR("gps_enable_qzss"), &c.gps.enableQZSS),
Param(PSTR("gps_enable_sbas"), &c.gps.enableSBAS),

Param(PSTR("board_align_roll"), &c.boardAlignment[0]),
Param(PSTR("board_align_pitch"), &c.boardAlignment[1]),
Param(PSTR("board_align_yaw"), &c.boardAlignment[2]),
Expand Down Expand Up @@ -876,7 +886,7 @@ void Cli::execute(CliCmd& cmd, Stream& s)
PSTR("available commands:"),
PSTR(" help"), PSTR(" dump"), PSTR(" get param"), PSTR(" set param value ..."), PSTR(" cal [gyro]"),
PSTR(" defaults"), PSTR(" save"), PSTR(" reboot"), PSTR(" scaler"), PSTR(" mixer"),
PSTR(" stats"), PSTR(" status"), PSTR(" devinfo"), PSTR(" version"), PSTR(" logs"), PSTR(" gps"),
PSTR(" stats"), PSTR(" status"), PSTR(" devinfo"), PSTR(" version"), PSTR(" logs"), PSTR(" gps [set_home|clear_home]"),
//PSTR(" load"), PSTR(" eeprom"),
//PSTR(" fsinfo"), PSTR(" fsformat"), PSTR(" log"),
nullptr
Expand Down Expand Up @@ -1062,7 +1072,20 @@ void Cli::execute(CliCmd& cmd, Stream& s)
}
else if(strcmp_P(cmd.args[0], PSTR("gps")) == 0)
{
printGpsStatus(s, true);
if(cmd.args[1] && strcmp_P(cmd.args[1], PSTR("set_home")) == 0)
{
_model.setGpsHome(true);
s.println(_model.state.gps.homeSet ? F("Home position set") : F("No GPS fix"));
}
else if(cmd.args[1] && strcmp_P(cmd.args[1], PSTR("clear_home")) == 0)
{
_model.state.gps.homeSet = false;
s.println(F("Home position cleared"));
}
else
{
printGpsStatus(s, true);
}
}
else if(strcmp_P(cmd.args[0], PSTR("preset")) == 0)
{
Expand Down Expand Up @@ -1562,6 +1585,33 @@ void Cli::printGpsStatus(Stream& s, bool full) const
s.printf("%s %3d %3d %s %s", getGnssName(sv.gnssId), sv.id, sv.cno, getUsedName(sv.quality.svUsed), getQualityName(sv.quality.qualityInd));
s.println();
}
s.println(F("Home:"));
if (_model.state.gps.homeSet)
{
s.print(F(" Lat: "));
s.print(_model.state.gps.location.home.lat);
s.print(F(" ("));
s.print(_model.state.gps.location.home.lat * 1e-7f, 7);
s.println(F(")"));

s.print(F(" Lon: "));
s.print(_model.state.gps.location.home.lon);
s.print(F(" ("));
s.print(_model.state.gps.location.home.lon * 1e-7f, 7);
s.println(F(")"));

s.print(F(" Dist: "));
s.print(_model.state.gps.distanceToHome);
s.println(F(" m"));

s.print(F(" Bear: "));
s.print(_model.state.gps.directionToHome);
s.println(F(" deg"));
}
else
{
s.println(F(" Not set"));
}
#endif
}

Expand Down
Loading