自制 FlightGear 飞行模拟升降舵配平轮:Arduino Nano + Python UDP 桥接方案
项目动机
FlightGear 官方 Wiki 的串口通信教程已过时,无法直接将 Arduino 串口数据映射为模拟器属性。本项目提供一套「Arduino 采集电位器 → Python 脚本转发 UDP → FlightGear Generic Protocol 解析」的完整工程化方案,成本仅约 $15,体积如信用卡大小,适合桌面飞行模拟爱好者。
硬件清单
- Arduino Nano R3 ×1
- 10kΩ 单圈旋转电位器(带金属轴、旋钮)×1
- 0.96″ SSD1306 OLED(I2C,4 引脚)×1
- 100µF 电解电容(电位器信号滤波)×1
- 杜邦线、排针、热缩管若干
软件环境
- Arduino IDE 1.8.x + U8glib 库
- Python 3.x +
pyserial(pip install pyserial) - FlightGear 2020.3+(任意平台)
电路连接
| 元件引脚 | Arduino 引脚 | 备注 |
|---|---|---|
| 电位器中间抽头 | A6 | 模拟输入,两端分别接 5V/GND |
| 电位器两端并联 100µF | — | 正极接抽头,负极接 GND,滤除抖动 |
| OLED VCC | 5V | |
| OLED GND | GND | |
| OLED SDA | A4 | 硬件 I2C |
| OLED SCL | A5 |
Arduino 固件要点
#include
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);
const int POT_PIN = A6;
int p, w, m; // 原始值、映射后配平值(-100~100)、仪表针角度(0~90)
u8g_uint_t needleAngle;
void setup() {
Serial.begin(9600);
u8g.setFont(u8g_font_chikita);
u8g.setColorIndex(1);
}
void loop() {
p = analogRead(POT_PIN); // 0~1023
w = map(p, 0, 1023, 100, -100); // 配平值:向上+100,向下-100
m = map(p, 0, 1023, 90, 0); // 仪表针角度:0°~90°
// 串口发送浮点数(每行一个值,Python 端按行读取)
float val = (p - 512.0) / 512.0; // -1.0 ~ +1.0
Serial.println(val, 4);
// OLED 绘制仪表盘
needleAngle = (m < 45) ? m + 135 : m - 45; // 几何修正
u8g.firstPage();
do { drawGauge(needleAngle); } while (u8g.nextPage());
delay(10); // 约 100Hz 采样率
}
Python 桥接脚本 arduinoElevatorTrim.py
#!/usr/bin/env python3
import serial, sys
from socket import *
HOST = "localhost"
PORT = 21567
ADDR = (HOST, PORT)
SERIAL_PORT = "COM4" # Linux/Mac 通常为 /dev/ttyUSB0
BAUD = 9600
sock = socket(AF_INET, SOCK_DGRAM)
ser = serial.Serial(SERIAL_PORT, BAUD, timeout=1)
print(f"Listening on {SERIAL_PORT} -> UDP {ADDR}")
prev = ""
while True:
line = ser.readline().decode().strip()
if line and line != prev:
sock.sendto(line.encode(), ADDR)
prev = line
FlightGear 协议文件 arduinoElevatorTrim.xml
放入 <FlightGear根目录>/data/Protocol/ 目录:
<?xml version="1.0"?>
<PropertyList>
<generic>
<input>
<line_separator>\n</line_separator>
<var_separator>,</var_separator>
<chunk>
<name>Elevator trim</name>
<node>/controls/flight/elevator-trim</node>
<type>float</type>
</chunk>
</input>
</generic>
</PropertyList>
启动流程
- 上传 Arduino 固件,打开串口监视器确认输出
-1.0000 ~ +1.0000连续变化。 - 关闭串口监视器(释放 COM 口),运行 Python 脚本:
python arduinoElevatorTrim.py - 启动 FlightGear 时追加参数(无空格):
--generic=socket,in,30,localhost,21567,udp,arduinoElevatorTrim - 进入驾驶舱,观察升降舵配平指示器随电位器转动同步移动。