最近因为项目需要实现一个通过pixhawk串口收发自定义数据的功能。搜索发现,博客上大神们FantasyJXF、FreeApe的博文已经详细介绍了通过pixhawk串口读取自定义数据,这部分功能实现后就可以将自己开发或者px4暂不支持的传感器嵌入到px4的代码中;考虑有些传感器是触发式的需要不断向传感器发送命令数据才可以返回测试数据,这篇博文添加了通过串口发送自定义数据功能,主要介绍一下在调试过程中遇到的坑。。。
首先参考大神FantasyJXF的博文,复现了telem2串口的数据读取功能,过程很顺利。在测试串口发送代码时就相当不顺利了—_—~,
下面介绍工具,开始选择/dev/ttyS2对应的TELE2实现串口二次开发功能。经过测试TELE2的RX引脚可以正常收数据,而TX引脚不能正常发送数据,可能被其他地方调用,改用SERIAL4串口/ttyS6。
连接硬件如图所示,连接飞控的SERIAL4端口与模块的TTL端口,SERIAL4端口从左至右的接口依次为:+5V(红色)、TX#4(绿色)、RX#4(黄色)、TX#5(棕色)、RX#5(灰色)、GND(黑色)。
下面来一一阐述遇到的坑:
1、坑1—串口配置问题
首先直接在循环里,利用write()函数通过SERIAL4串口发送数据,形式与read()函数相同。
send_data[0]=0x08;
send_data[1]=0x09;
send_data[2]=0x0A;
send_data[3]=0x0B;
send_data[4]=0x0C;
write(serv_uart,&send_data,5);//发送数据
结果如下图所示。
发现存在问题,线程开启后,只发出一条数据,而后只有read后才会write数据。根据与frsky_telemetry.c文件对比,它在uart_init()函数中添加配置串口选项O_NONBLOCK。
int serial_fd = open(uart_name, O_RDWR | O_NOCTTY| O_NONBLOCK);
该选项意思是去掉阻塞等待,如不添加该选项,在进入线程主函数serv_sys_uart_thread_main()函数的while循环里,如果没有接收到数据,则read(serv_uart,&data,1);会一直处于读的状态,占用了串口所以发送不出去。添加完该选项之后,启动线程,会一直通过串口发送数据。
2、坑2—线程优先级问题
测试后发现,串口每次只会发送第一个字节,如上图,并且影响到了串口的接收,接收数据会发生错误,考虑是直接在循环里面添加的write函数,发送的频率太快。所以将数据改成用for循环一次发送一个字节。并且将整个线程通过读取系统时间设置成了10Hz。(事后证明这个方法很占用CPU时间)
测试过程中还发现了死机的情况,发现是将新的线程的优先级设置的太高了造成的,优先级设置成了SCHED_PRIORITY_MAX – 5,与看门狗是一个级别,系统会优先调用该线程,该线程还一致占用着串口的中断,会导致系统死机。采取的策略是降低新建线程的优先级,根据Firmware->src->modules->platform->px4_tasks.h文件中定义了其他进程的优先级:
#pragma once
#include <px4_tasks.h>
/* SCHED_PRIORITY_MAX */
#define SCHED_PRIORITY_FAST_DRIVER SCHED_PRIORITY_MAX
#define SCHED_PRIORITY_WATCHDOG (SCHED_PRIORITY_MAX - 5)
#define SCHED_PRIORITY_ACTUATOR_OUTPUTS (SCHED_PRIORITY_MAX - 15)