跳到主要内容
树莓派 4B 连接大疆 M300 无人机开发教程 | 极客日志
C++
树莓派 4B 连接大疆 M300 无人机开发教程 综述由AI生成 介绍树莓派 4B 连接大疆 M300 RTK 无人机的硬件搭建与软件开发流程。内容包括 E-Port 套件选型、USB-TTL 及同轴线连接方式、Linux 系统环境配置(OpenCV、FFmpeg 等)、USB Gadget 设置以支持 Bulk 传输,以及 Payload SDK 3.11.0 的应用编译与调试。针对 M300 特有的 OSDK 接口连接模式、波特率配置及相机码流订阅进行了详细说明,并提供了常见错误排查方法。
不羁 发布于 2026/4/6 更新于 2026/5/21 24 浏览注 :本教程适用于树莓派 4B 连接大疆 M300 RTK 无人机,若是其余型号可以参考本文思路,但是具体细节请前往官方教程或大疆开发者论坛查找。第三方开发板连接大疆无人机,不同型号之间会有很多细节差异,请确认自己的型号然后针对性查找。
官方教程网址 :Payload SDK (官方的是树莓派 4B 连接 M350!并非 M300,实现细节完全不同,请慎重查看)
大疆开发者论坛网址 :Payload SDK – 大疆创新 SDK 技术支持论坛
1. 硬件准备
1.1 硬件选型
无人机型号 :M300 RTK。M300 顶部一共有三个接口,其中 OSDK 端口和云台口(Payload SDK Port)可以用来运行 PSDK 程序,TypeC 调参口则是用来与电脑连接,打开 DJI Assistant2 软件后,可以升级无人机固件,导出日志,使用模拟器,绑定负载等。
1.FPV 摄像头 13.左视和右视红外感知系统 25.调参接口 2.前视红外感知系统 14.左视和右视视觉系统 26.OSDK 接口 3.前视视觉系统 15.智能飞行电池 27.PSDK 接口 4.云台接口 16.电池电量指示灯 28.下视红外感知系统 5.云台相机解锁按钮 17.电池电量按键 29.下视视觉系统 6.机臂 18.D-RTK2 天线 30.下视补光灯 7.电机 19.飞行器状态指示灯 31.下视夜航灯 8.螺旋桨 20.上视夜航灯 32.后视红外感知系统 9.电调 LED 指示灯 21.电源按键/指示灯 33.后视视觉系统 10.图传天线 22.上视红外感知系统 34.电池锁紧旋钮 11.起落架 23.上视补光灯 35.云台相机 12.防尘网 24.上视视觉系统 36.无线上网卡接口
第三方开发板 :Raspberry Pi 4B(树莓派 4B)
注 :左侧开关,靠近接口侧为 off,反之为 on;右侧 USB 主/从设备切换,靠近接口侧为 host,反之为 device。
其余设备 :除上面的设备外,还需要下面的设备用于连线。
USB-TTL(CH340) :某些树莓派的串口性能较差,建议使用 USB 转 TTL 模块连接串口。
XT30 转 TypeC 线 :E-Port 开发套件配套的,用于树莓派供电。
TypeA-TypeC 数据线 :必须是数据线,需要能够传输数据。
E-Port 同轴线 :E-Port 开发套件配套的。
1.2 硬件连接
树莓派连接 USB-TTL 线 :TypeA 端插入树莓派的 USB3.0 协议插口。
E-Port 开发板连接 USB-TTL 线 :连接的引脚分别为 RX->TX、TX->RX、GND->GND,该线主要用于 uart 数据传输 (速度较慢)。各串口见下图。
连线效果见下图,注意 RX 与 TX 不要接反了。
连接 E-Port 同轴线 :同轴线的 typeC 插入 E-Port 开发板的 E-Port 接口,B 标识朝上 。
最终连线效果 :将 E-Port 开发板的开关拨至 ON,USB 主/从设备切换拨至 device,M300 无人机做 Device 从设备,开发板做 Host 主设备,仅能通过此方式,不要搞成官网教程上的了。启动无人机后,开发板的指示灯会发出绿光,若没亮,检查开关是否拨至 ON。
E-Port 开发板接入 M300 无人机 :同轴线另一端的 A 标识朝无人机内部插入 OSDK 端口。PSDK 3.x 版本集 OSDK,PSDK 功能与一体,比 OSDK 4.1 版本要轻量很多,而且结构更加清晰易懂。这就是为啥我们使用 PSDK,会连接在 OSDK 接口上。而 psdk 接口通常用于接入专用的 PSDK 负载,比如 Skyport 这种。
使用 TypeA-TypeC 数据线,连接 E-Port 开发板与树莓派 :该线主要用于 bulk 数据传输 (高速)。TypeA 端接入树莓派的 USB2.0 接口,TypeC 端接入 E-Port 开发板的 USB2.0 接口。
使用 XT30 转 TypeC 线连接树莓派 :该线主要用于树莓派供电。树莓派 4B 通常使用 5V/2A 电源供电,E-Port 开发板的 5V/2A 输出接口连接 XT30 转 TypeC 线。
将 XT30 转 TypeC 线接入树莓派 4B 的 TypeC 电源接口。
至此硬件连线完成,后面我们会在软件部分对线路连接是否成功进行验证。
2. 软件准备 PSDK 连接模式 :DJI_USE_UART_AND_USB_BULK_DEVICE
注 :连接 M300 无人机最高只能用 psdk3.11.0,再往上的版本就无法正常获取相机码流了。
2.1 环境下载
树莓派系统 :Raspberry PI OS(64-bit)。通过官方烧录工具 Raspberry Pi Imager 正常烧录即可。
sudo apt-get install libusb-1.0-0-dev
sudo apt install libgtk2.0-dev pkg-config
unzip opencv-3.4.15.zip
cd opencv-3.4.15/
mkdir build && cd build/
cmake ../
make -j4
sudo make install
opencv_version
opencv 打包和安装时间较长,请耐心等待。另外 gcc 版本过高的话,打包 opencv 时会出现源代码语法错误,去源文件修改一下重新打包就行了。
tar -zxvf ffmpeg-4.3.2.tar.gz
./configure --enable-shared
make -j4
sudo make install
tar -xzvf opus-1.3.1.tar.gz
cd opus-1.3.1/
autoreconf -f -i
./configure
make -j4
sudo make install
sudo apt-get install automake
sudo apt-get install libaio-dev
sudo apt install gcc g++ -y
gcc -v
sudo apt-get update
sudo apt-get upgrade
2.2 开启树莓派 USB 能力 Linux 设备往往是通用性设备,没有专门为某个功能设计的 USB 驱动芯片,因此需要通过软件实现 UDC 功能。Linux USB gadget 是 Linux 环境下的 UDC 实现。在树莓派中启用 USB Gadget,可以让树莓派充当 USB 设备。
修改树莓派 USB device 配置文件
修改 /boot/firmware/config.txt,在文件末尾添加:
注:原有的 dtoverlay=vc4-kms-v3d 不要删除,会导致图形化界面无法启动。
修改 /boot/firmware/cmdline.txt,在 rootwait 后面加上:
重新编译 start_bulk 程序
压缩包包里有一个 start_bulk 可执行程序,但并不是所有系统都能使用,因此需要用户自己重新编译一个。
cd usb-bulk-configuration-reference
make clean
make
关于编译 startup_bulk.c 文件,有些平台编译可能会报错 htole32, htole16 没有,按照下面的方式进行解决:
sudo apt install libaio-dev build-essential
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define cpu_to_le32(x)(x)
#define cpu_to_le16(x)(x)
#else
#define cpu_to_le32(x) ((((x)&0xff000000u)>>24)|(((x)&0x00ff0000u)>>8)|(((x)&0x0000ff00u)<<8)|(((x)&0x000000ffu)<<24))
#define cpu_to_le16(x) ((((x)>>8)&0xffu)|(((x)&0xffu)<<8))
#endif
c. 在 startup_bulk.c 顶部引入头文件
sed -i 's/\bhtole32\b/cpu_to_le32/g; s/\bhtole16\b/cpu_to_le16/g' startup_bulk.c
此时应该会出现一个新的 start_bulk 可执行文件,在之后的脚本中会调用该程序。
下载官方 start_bulk 包
传入树莓派中,并使用 unzip 指令进行解压。
unzip usb-bulk-configuration-reference.zip
注:上述配置修改完成后,重启树莓派刷新配置!!!**
编写 raspi-usb-device-start.sh 脚本 ,用于配置 gadget。
#!/bin/bash
net_ip=192.168.42.120
net_mask=255.255.0.0
enable_vcom=0
enable_rndis=0
enable_bulk=1
startup_bulk_dir=$(dirname "$0 " )
startup_bulk_exe=${startup_bulk_dir} /startup_bulk
echo startup_bulk_exe
if [ ! -d /sys/kernel/config/usb_gadget ]; then
if ! $(grep -q dtoverlay=dwc2 /boot/firmware/config.txt) ; then
echo -e "\n\n\n## customized\n# for op-sdk enable USB device RNDIS\n[all]\ndtoverlay=dwc2" >> /boot/firmware/config.txt
init 6
fi
if ! $(grep -q modules-load=dwc2 /boot/firmware/cmdline.txt) ; then
sed -i 's/rootwait /&modules-load=dwc2 /' /boot/firmware/cmdline.txt
init 6
fi
if ! $(grep -q libcomposite /etc/modules) ; then
echo -e "\n\n\n## customized\n# for op-sdk enable USB device RNDIS\nlibcomposite" >> /etc/modules
init 6
fi
exit 1
fi
modprobe g_ether
rmmod g_ether
sleep 1
if [ ! -d /sys/kernel/config/usb_gadget/pi4 ]; then
mkdir -p /sys/kernel/config/usb_gadget/pi4
cd /sys/kernel/config/usb_gadget/pi4
echo 0x2ca3 > idVendor
echo 0xF001 > idProduct
if [ ${enable_vcom} -eq 1 ]; then
echo 0xF002 > idProduct
fi
if [ ${enable_rndis} -eq 1 ]; then
echo 0xF003 > idProduct
fi
if [ ${enable_bulk} -eq 1 ]; then
echo 0xF001 > idProduct
fi
echo 0x0001 > bcdDevice
echo 0x0200 > bcdUSB
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol
mkdir -p strings/0x409
echo "psdk-rpi4b" > strings/0x409/serialnumber
echo "raspberry" > strings/0x409/manufacturer
echo "PI4" > strings/0x409/product
cfg=configs/c.1
mkdir -p "${cfg} "
echo 0x80 > ${cfg} /bmAttributes
echo 250 > ${cfg} /MaxPower
if [ ${enable_rndis} -eq 1 ]; then
cfg_str="${cfg_str} +RNDIS"
func=functions /rndis.usb0
mkdir -p "${func} "
ln -sf "${func} " "${cfg} "
echo 1 > os_desc/use
echo 0xcd > os_desc/b_vendor_code
echo MSFT100 > os_desc/qw_sign
echo RNDIS > "${func} /os_desc/interface.rndis/compatible_id"
echo 5162001 > "${func} /os_desc/interface.rndis/sub_compatible_id"
ln -sf "${cfg} " os_desc
fi
if [ ${enable_vcom} -eq 1 ]; then
cfg_str="${cfg_str} +ACM0"
func=functions /acm.gs0
mkdir -p "${func} "
ln -sf "${func} " "${cfg} "
fi
if [ ${enable_bulk} -eq 1 ]; then
mkdir -p /dev/usb-ffs
cfg_str="${cfg_str} +BULK1"
mkdir -p /dev/usb-ffs/bulk1
func=functions /ffs.bulk1
mkdir -p "${func} "
ln -sf "${func} " "${cfg} "
mount -o mode=0777,uid=2000,gid=2000 -t functionfs bulk1 /dev/usb-ffs/bulk1
cfg_str="${cfg_str} +BULK2"
mkdir -p /dev/usb-ffs/bulk2
func=functions /ffs.bulk2
mkdir -p "${func} "
ln -sf "${func} " "${cfg} "
mount -o mode=0777,uid=2000,gid=2000 -t functionfs bulk2 /dev/usb-ffs/bulk2
fi
mkdir -p "${cfg} /strings/0x409"
echo "${cfg_str:1} " > "${cfg} /strings/0x409/configuration"
fi
if [ ${enable_bulk} -eq 1 ]; then
if [ ! -f ${startup_bulk_exe} ]; then
cd ${startup_bulk_dir}
make && ( $? != 0 ) && ( exit 1 )
cp startup_bulk ${startup_bulk_dir} /startup_bulk
cd -
fi
${startup_bulk_exe} /dev/usb-ffs/bulk1 &
sleep 1
${startup_bulk_exe} /dev/usb-ffs/bulk2 &
sleep 1
fi
udevadm settle -t 5 || :
ls /sys/class/udc > UDC
if [ ${enable_rndis} -eq 1 ]; then
/sbin/brctl addbr pi4br0
/sbin/ifconfig pi4br0 ${net_ip} netmask ${net_mask} up
/sbin/brctl addif pi4br0 usb0
/sbin/ifconfig usb0 down
/sbin/ifconfig usb0 up
fi
exit 0
使用 TypeA-TypeC 数据线,连接树莓派的电源 typeC 接口,然后接入电脑的 USB 接口。
配置脚本自启动
由于每次启动都需要启动脚本来开启 bulk 功能,因此建议配置一个脚本自启动服务。
sudo systemctl enable bulk-gadget
然后重启树莓派,再次进行上面第五步或第六步的验证,查看脚本是否执行即可。
写入下列内容 ExecStart 的值为 raspi-usb-device-start.sh 所在的路径,请根据实际情况修改。
[Unit]
Description =Start PSDK USB bulk gadget
After =sysinit.target
DefaultDependencies =no
[Service]
Type =on eshot
RemainAfterExit =yes
ExecStart =/home/pi/program/start_bulk/raspi-usb-device-start.sh
StandardOutput =journal
StandardError =journal
User =root
[Install]
WantedBy =sysinit.target
sudo nano /etc/systemd/system/bulk-gadget.service
使用 VID 和 PID 查看 USB 详细信息 ubuntu 虚拟机执行指令
sudo lsusb -d 2ca3:f001 -v
电脑上开启 ubuntu 虚拟机,并扫描树莓派设备 ubuntu 虚拟机执行指令
chmod 777 raspi-usb-device-start.sh
ps -ef | grep startup_bulk
2.3 验证线路连接 完成 1.1 的硬件连接后,启动无人机,并将开关拨至 ON,USE 主/从切换至 device,再连接树莓派,进入终端。
验证 TypeA-TypeC 数据线,连接 E-Port 开发板与树莓派
若出现了 /dev/ttyACM0 则说明 USB-TTL 线连接成功。
若出现了 /dev/ttyUSB0 则说明 USB-TTL 线连接成功。
3. 启动 PSDK 下载 psdk3.11.0 压缩包,将压缩包传入树莓派中并完成解压。
本教程以 c++ 样例代码为例,若想启动 c 代码,将 sample_c++ 修改为 sample_c 即可。
先在 大疆开发者网站 上进行注册,申请成为 PSDK 开发者,并创建应用,获取应用信息。
注 :app 名称不要太长,我最开始的应用名长度为十七个字,启动应用时会提示报错信息过长,改为四个字后才正常运行。
3.1 配置用户信息 修改 samples/sample_c++/platform/linux/manifold2/application/dji_sdk_app_info.h
#define USER_APP_NAME "your_app_name"
#define USER_APP_ID "your_app_id"
#define USER_APP_KEY "your_app_key"
#define USER_APP_LICENSE "your_app_license"
#define USER_DEVELOPER_ACCOUNT "your_developer_account"
#define USER_BAUD_RATE "921600"
将开发者网站上的应用信息填入上述位置,USER_DEVELOPER_ACCOUNT 就是你的登录邮箱。
关于 USER_BAUD_RATE 的选择,使用 921600 即可,可适用于所有无人机型号。
无人机 串口波特率/bps M350 RTK 11520、230400、460800、921600、1000000 M300 RTK 11520、230400、460800、921600、1000000 M30/M30T 11520、230400、460800、921600、1000000 M3D/M3TD 921600 M3E/M3T 921600
3.2 配置硬件连接方式 修改 samples/sample_c++/platform/linux/manifold2/application/dji_sdk_config.h
本文主要以 DJI_USE_UART_AND_USB_BULK_DEVICE 模式为主,其余模式请自行查询资料,另外 M300 OSDK 端口仅支持 DJI_USE_ONLY_UART、DJI_USE_UART_AND_USB_BULK_DEVICE。
#define DJI_USE_ONLY_UART (0)
#define DJI_USE_UART_AND_USB_BULK_DEVICE (1)
#define DJI_USE_UART_AND_NETWORK_DEVICE (2)
#define DJI_USE_ONLY_USB_BULK_DEVICE (3)
#define DJI_USE_ONLY_NETWORK_DEVICE (4)
#define CONFIG_HARDWARE_CONNECTION DJI_USE_UART_AND_USB_BULK_DEVICE
3.3 修改 UART 配置文件 修改 samples/sample_c++/platform/linux/manifold2/hal/hal_uart.h
#define LINUX_UART_DEV1 "/dev/ttyUSB0"
#define LINUX_UART_DEV2 "/dev/ttyACM0"
3.4 修改 bulk 配置文件 修改 samples/sample_c++/platform/linux/manifold2/hal/hal_usb_bulk.h
#define LINUX_USB_BULK1_EP_IN_FD "/dev/usb-ffs/bulk1/ep1"
#define LINUX_USB_BULK1_EP_OUT_FD "/dev/usb-ffs/bulk1/ep2"
#define LINUX_USB_BULK1_INTERFACE_NUM (0)
#define LINUX_USB_BULK1_END_POINT_IN (0x81)
#define LINUX_USB_BULK1_END_POINT_OUT (0x01)
#define LINUX_USB_BULK2_EP_IN_FD "/dev/usb-ffs/bulk2/ep1"
#define LINUX_USB_BULK2_EP_OUT_FD "/dev/usb-ffs/bulk2/ep2"
#define LINUX_USB_BULK2_INTERFACE_NUM (1)
#define LINUX_USB_BULK2_END_POINT_IN (0x82)
#define LINUX_USB_BULK2_END_POINT_OUT (0x02)
#define LINUX_USB_VID (0x2CA3)
#define LINUX_USB_PID (0xF001)
3.5 编译运行 if (USE_SYSTEM_ARCH MATCHES LINUX)
add_definitions(-DSYSTEM_ARCH_LINUX)
add_subdirectory(samples/sample_c/platform/linux/manifold2)
add_subdirectory(samples/sample_c++/platform/linux/manifold2)
endif()
cd Payload-SDK/
mkdir build && cd build
cmake ../
make -j4
sudo ./dji_sdk_demo_linux_cxx
[Logs/latest.log] -> [DJI_0009_20251210_16-34-36.log]
[0.024][core]-[Info]-[DjiCore_Init:107) Payload SDK Version : V3.11.0-beta.0-build.2206 Mar 12202512:41:40
...
以上错误信息是正常情况,这是因为 M300 RTK OSDK 接口仅有 psdk 中的部分功能,有些功能无法使用,因此报这个错误,不影响其他功能的使用。
之后就可以向官方教程那样使用样例程序里面的功能啦,飞行控制的话,可以使用数据线通过无人机调参接口将无人机与电脑直接相连,然后启动 DJI Assistant 2 (Enterprise Series) 2.1.20 中的模拟飞行,来进行测试。
常见问题 (1)如果串口性能不佳,有可能出现'protocol frame crc8 error'警告。少量的警告可以忽略。如 果该警告大量出现,可以使用性能更强的 USB-TTL,或者更换质量更好、长度更短的串口线。
(2)如果提示'DjiAccessAdapter_IsUartConnect,returnCode=236'错误,说明负载端的串口设备 连接存在问题,可以尝试检查串口功能是否开启,USB-TTL 设备是否正常。
(3)如果提示'Try identify UART0 connection failed.Probably because SDK adapter or aircraft not finish init or UART connect error.'错误,说明无人机端的串口设备连接存在问题,可以检查无人机 是否开机、E-Port 等转接板是否开机,以及接线是否正常。
(4)若出现无法订阅相机码流功的情况,【成功运行了 c++ 示例程序,并且功能 0 可以成功订阅到一些数据显示出来,但是关于视频的功能 c→0→1,无法像文档中展示的那样弹出一个显示视频画面的窗口,停留在终端等待按 q 退出】,降低 psdk 版本即可,一开始我使用的 psdk3.14.0 一直无法成功订阅,在降低到 psdk3.11.0 之后就可以正常订阅了。
附录 相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online