Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

23年电赛准备区

备赛问题解决(持续更新)

程序烧录及固件更新

在我们烧录程序时,只需要将飞控用usb跟电脑连接 将编译好的文件中的hex文件粘到U盘中,USB拔插即可。
同理:在更新固件时,把 BootLoader 固件放进
BootLoaderUpdate 文件夹,然后给飞控重新上电。

地面站

  • ACfly-window

    1、查看、配置各种传感器
    2、飞机校准、调参(更改飞机结构、炸鸡后必备操作)
  • 遥控校准
    在校准遥控器时,上方两个按钮校准时要从最大掰到最小。
  • ACflyPC 1.xx

    1、实时查看飞行数据(Debug.cpp
    2、回溯你的飞行记录。(如:炸鸡后查看T265姿态和飞控之间的姿态差异 是由于操作不当导致or双目’寄’)
飞机M35任务模式无法进入问题

(两个地面站中参数都需要写入!!)
1、ACfly-window
地面站中遥控器按键的设置。解锁后模式的设置在两个地面站都可以设置 个人更喜欢这个地面站。。
ACfly-window
2、ACflyPC
此为解锁前模式的设置 根据实际的任务模式选择进行填写。
ACfly-1.30

  • 数传的配置

    选择合适的串口连接后,进行软件上的传感器注册,默认数传接口为串口7,波特率115200 选择串口功能为mavlink通信。(波特率不要随意更改?【未解决】)

    串口可选择不同功能,最多支持配置两个数传串口(mavlink通信),需重启生效。

代码区

  • debug.c文件的用法

1
2
// Debug.cpp
uint8_t port_id = 1; //远程 1 有线 0

port_id作为飞机飞行或地面模式时使用上位机进行观看方式的选择
有线:飞机调试时接入USB使用
无线(较为常用):飞机M35任务模式时可使用数传对实际你进行调试时一些较为重要的数据、参数进行实时观看

1
2
3
4
5
6
7
8
9
10
11
mavlink_msg_debug_vect_pack_chan( 
get_CommulinkSysId() , //system id
get_CommulinkCompId() , //component id
port_id , //chan
&msg_sd ,
"color" , //name
TIME::get_System_Run_Time() * 1e6 , //boot ms
color_x , //参数1
color_y, //参数2
0 //参数3 ...
);
  • 绕杆(EDU-磊哥遗留 ,dp说很不熟 !!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
case 15:
//初始化参数
Kp_delta=1.5;
Kp_distance=0.5;
alpha=8;
delta_now=0;
distance_now=0;
M35_last_yaw=Quaternion_getYaw(get_Airframe_attitude());//记录地理坐标系偏航角 //上一次的偏航角
++Mode_Inf->auto_step1;
Mode_Inf->auto_counter=0;
break;
case 16:
Position_Control_set_TargetVelocityBodyHeadingXY_AngleLimit(0.0f,-8.0f,0.1f,0.1f);//
if(++Mode_Inf->auto_counter==150)
{
Position_Control_set_XYLock();
Attitude_Control_set_YawLock();
Position_Control_set_ZLock();
++Mode_Inf->auto_step1;
Mode_Inf->auto_counter = 0;
}
break;
case 17:
delta_now=SDI_delta_x;
alpha=(-1)*(Kp_delta*delta_now);
distance_now=SDI_poles_distance;
distance_e=distance_now-90;
distance_v=-1*(Kp_distance*(distance_e));
Attitude_Control_set_Target_YawRate(degree2rad(constrain_float(alpha,8)));
Position_Control_set_TargetVelocityBodyHeadingXY_AngleLimit(constrain_float(distance_v,6.0f),-6.0f+(-1)*fabs(degree2rad(constrain_float(alpha,8))*0.9),0.1f,0.1f);
M35_now_yaw=Quaternion_getYaw(get_Airframe_attitude());
if(M35_now_yaw == M35_last_yaw) //转弯完成
{
Position_Control_set_XYLock();
Attitude_Control_set_YawLock();
Position_Control_set_ZLock();
Mode_Inf->auto_counter=0;
}
++Mode_Inf->auto_step1;
if(SDI_poles_distance<=60)//如果小于安全距离 进降落模式
{
Position_Control_set_XYLock();
Attitude_Control_set_YawLock();
Position_Control_set_ZLock();
Mode_Inf->auto_step1=35;
Mode_Inf->auto_counter = 0;
}
break;

绕杆重点就是用离杆距离和摄像头看到的杆与其中心距离来修正由于飞机定位不准以及绕杆时XY轴速度、偏航速度不一致造成的轨迹偏离。
A9飞控中已经为我们写好了获取偏航角的函数供我们调用,有关旋转的函数及四元数类大致分布在
1、姿态函数controlSystem.hpp
2、四元数Quaternion类的定义及解算获取现姿态quaternion.hpp
3、获取集体四元数(偏航对准)MeasuementSystem.hpp

1
2
3
4
5
6
7
8
9
	//获取机体四元数(偏航对准)
bool get_AirframeY_quat( Quaternion* result, double TIMEOUT = -1 );
```
4、例子:`Avoiddancecpp` 里面有获取实时偏航角,也就是有关上面三个文件的实际函数用法
```C
Quaternion quat; //定义一个四元数类的对象
get_AirframeY_quat(&quat);//将这个对象复用到获取机体四元数的函数中获取

double yaw = quat.getYaw(); //定义参数获取姿态
  • 至此,对于编写绕杆具有比较清晰的了解,接下来便是23年暑假期间的实践。
绕杆测试

1、对偏航角的控制
在23年备赛测试期间,我们在使用角度函数,如:

1
2
3
//设定目标Yaw
bool Attitude_Control_set_Target_Yaw( double Yaw, double TIMEOUT = -1 );
bool Attitude_Control_set_Target_YawRelative( double Yaw, double TIMEOUT = -1 );

使用之后,我使用延时的方法来代替判断其旋转是否完成的标准,因为m35任务模式没有像 xyz 轴运动一样对偏航角是否旋转完成的判断函数,因此这里我们直接进行延时来达到对该动作等待的操作。
2、绕杆的完整测试(部分值未完整进行测试,若需使用仍需对distance值进行滤波等处理或是完善 p 值)
完整代码放在组织里了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
case 0:
{ //起飞
Position_Control_Takeoff_HeightRelative(70);
mission_ind ++;
break;
}
case 1:
{
model = mission_ind;
Position_Control_set_XYLock();
Position_ControlMode alt_mode;
get_Altitude_ControlMode(&alt_mode);
if(alt_mode == Position_ControlMode_Position)
{
Position_Control_set_ZLock();
mission_ind ++;
}
break;
}
case 2:
{
model = mission_ind;
if(++ navInf.counter2>= 5*freq)//等待5秒 20*freq == 15s
{
mission_ind ++;
navInf.counter2 = 0;
}
break;
}
case 3:
{ //获取当前偏航角 准备绕杆
model = mission_ind;
Position_Control_set_ZLock();
Position_Control_set_XYLock();
get_AirframeY_quat(&quat);
last_yaw = quat.getYaw();
mission_ind ++;

break;
}
case 4:
{
model = mission_ind;
// if(distance != 0 && color_x != 0)
// {
// kp_distance = (distance - 50);
Position_Control_set_ZLock();
distance_v = 0 + constrain((distance - r)*kp_distance,6.0f);
color_x_v = -10 -(color_x_yidong* 0.1);
Attitude_Control_set_Target_YawRate(degree2rad(yaw_angle));
Position_Control_set_TargetVelocityBodyHeadingXY_AngleLimit(distance_v,color_x_v);
get_AirframeY_quat(&quat);
now_yaw = quat.getYaw();
if( ++ navInf.counter2 >= 5*freq)
{
if(fabs(now_yaw - last_yaw) <= 0.005)
{
Position_Control_set_ZLock();
Position_Control_set_XYLock();
Attitude_Control_set_YawLock();
navInf.counter2 = 0;
mission_ind ++;
}
}
// }

}break;
  • 二维向量使用

1
2
3
4
5
6
//求巡线压线修正速度
vector2<double> d_vel;
d_vel.y = pos_err*cos(angle_err_rad);
d_vel.x = pos_err*sin(-angle_err_rad);
d_vel *= 2.5;
d_vel.constrain(150);
  • 此代码案例是用向量的概念来表示速度和方向,对巡线中修正速度误差。

  • 1、创建一个二维向量d_vel,用于表示巡线压线修正速度。

  • 2、根据巡线误差和角度误差计算出向量在y轴方向和x轴方向上的分量。其中,pos_err表示巡线误差,angle_err_rad表示角度误差(以弧度为单位),cos和sin函数分别用于计算余弦和正弦值。

  • 3、将向量的每个分量乘以2.5,以增加修正速度的大小。这里的2.5是一个系数,可以根据具体情况进行调整。

  • 4、将向量的大小限制在150以内,以避免修正速度过大或过小。这里使用constrain方法对向量进行限制,确保其大小在给定的范围内

  • M35 任务飞行

  • 1、在进行每一个动作的执行前后都要对飞机的XYZ三轴进行控制 否则会使飞机停止任务模式case的执行,进入安全模式(失败)

  • 2、编写函数时,在执行一个动作后,需对姿态进行判断,只有在姿态为Position_ControlMode_Position //位置锁定模式后,再写入动作才能成功 否则将无法完成对应飞行效果。

获取z轴的姿态 get_Altitude_ControlMode(&alt_mode);

1
2
3
4
5
6
7
8
//对z轴控制
Position_ControlMode alt_mode;
get_Altitude_ControlMode(&alt_mode);
if(alt_mode == Position_ControlMode_Position)
{
Position_Control_set_ZLock();
mission_ind = 2;
}

获取XY轴的位置 get_Position_ControlMode(&pos_mode);

1
2
3
4
5
6
7
8
//对XY轴控制
Position_ControlMode alt_mode;
get_Position_ControlMode(&pos_mode);
if(pos_mode == Position_ControlMode_Position)
{
Position_Control_set_XYLock();
mission_ind = 2;
}

3、任务模式中位置锁定延时的编写
navInf.counter2 = 0; //参数名参考具体代码
重点:在进行一次时间延时之后需要把该变量置零!!!
不然你就离炸鸡不远了。

1
2
3
4
5
if(++ navInf.counter2>= n*freq)//等待n秒
{
mission_ind = 3;//作为进入下一个case的依据
navInf.counter2 = 0;
}

4、代码接口中所有位置、速度、加速度数据单位均为 cm 厘米。
5、代码接口中所有角度、角速度、角加速度数据单位均为 rad 弧度。

二次开发

在我们外加传感器时,代码接口的编写就显得十分重要。
传感器接口分为:传感器读取接口 和 传感器注册及更新接口。

其他类型外设编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static bool SDI_DriverInit( Port port, uint32_t param )
{
//波特率115200
port.SetBaudRate( 115200, 2, 2 );
DriverInfo* driver_info = new DriverInfo;
driver_info->param = param;
driver_info->port = port;
xTaskCreate( SDI_Server, "SDI", 1024, (void*)driver_info, SysPriority_ExtSensor, NULL);
xTaskCreate(SDI_Tx_model_contrl , "TX", 1024 ,(void*)driver_info, SysPriority_ExtSensor, NULL);
return true;
}

void init_drv_SDI()
{
PortFunc_Register( 100, SDI_DriverInit );// ‘100’决定了你在地面站定义串口时写入的代号 当你自己新建串口时定义的数字时,需要注意在地面站写入时需要选择高级 然后手动写入参数。
}
// bool PortFunc_Register( uint8_t FuncInd, bool (*init)( Port port, uint32_t param ) )
// {
// if( FuncInd < 8 )
// return false;
// if( init == 0 )
// return false;
// if( PortFuncs[FuncInd].init )
// return false; // PortFuncs[FuncInd].init = init; // return true;
// }

上面两个函数是我们在进行新外设编写的有关.
PortFunc_Register函数中的第一个函数决定你在地面站中的对串口定义的
编写初始化函数时对于xTaskCreate要根据传感器是单项通信还是双向通信为对应函数填入xTaskCreate中.

1
2
3
4
5
6
7
8
	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) //函数定义
//xTaskCreate(SDI_Tx_model_contrl , "TX", 1024 ,(void*)driver_info, SysPriority_ExtSensor, NULL); 根据原有函数编写规则进行编写

  • 接收机

  • 大飞机:PPM

  • 小飞机:SBUS

  • OffBoard模式

  • 即通过遥控器等切入offboard模式,这时候无人机只会听从板载计算机发来的的mavlink消息。
    也就是通过板载计算机控制无人机的方式。

  • 继电器

    继电器:是一种电控制器件,是当输入量的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。继电器具有控制系统和被控制系统,通常应用于自动化的控制电路中,在电路中起着自动调节、安全保护、转换电路等作用。

  • 说白了:继电器就相当于一个开关,接在任意线上,断开状态下线就断开了,没导通,闭合状态下线就接在了一起,导通了。

  • 作用:用于控制电路。

接线
  • 一、输入部分:

  • 1、DC+:接电源正极(电压按继电器要求,有5V、9V、12v和24v选择)

  • 2、DC-:接电源负极

  • 3、IN:可以高或低电平控制继电器吸合

  • 二、继电器输出端:
    1、NO:继电器常开接口,继电器吸合前悬空,吸合后与COM短接
    2、COM:继电器公用接口
    3、NC:继电器常闭接口,继电器吸合前与COM短接,吸合后悬空

  • 三、高低电平触发选择端(有些继电器模块没有):
    1、跳线与LOW短接时为低电平触发
    2、跳线与high短接时为高电平触发

  • 避坑指南

  • 1、port_id一定要改无线,不然你连不了一点。。。。。

  • 2、使用Radio telemetry时波特率使用115200 且mavlink通信最好只设置一个,飞控手册里面写的是用57600,而且说支持配置两个数传串口。
    只能说飞控手册,不一定和实际一致。(信了你就等着bug的出现吧。。。)

  • 3、在设置地面站中电池的电量参数时,要注意在设置低电压警告和低电压降落时出现的问题。
    23年电赛准备期间,将电压设置成正常低电压情况下(3s:11.4V 4s:14.9V) 会出现12v以上就就报警的情况。。。
    原因:经过排查,暂不认为是电流计以及飞控地面站电压显示出现的问题。应该在飞机飞行的时候,功率过大导致电池电压下降。再加上本身电池有虚电的情况,飞机电压判断暂不用此方法。
    解决方案:飞一次测一次电池电压较为保险。

  • 4、新串口的写入介绍。结合上文对二次开发的介绍。

    1
    2
    3
    void init_drv_SDI()  
    {
    }

    (1)此函数需要在drv_main中进行init申明。
    (2)写法看参照原drv_SDI中的通信大体框架进行编写。
    (3)PortFunc_Register()此函数中100决定了你在地面站定义串口时写入的代号。当你自己新建串口时定义的数字时,需要注意在地面站写入时需要选择高级 然后手动写入参数。当然写入的数据不能跟原有的几个模块定义一致。

23年电赛比赛调试ing

起飞飞机自旋角度问题

1、在M35 的 while(1)前面添加记录起飞前偏航角的参数,在起飞后进行负调整

1
2
3
4
5
6
7
8
	double iniYaw;
Quaternion att;
get_AirframeY_quat(&att);
iniYaw = att.getYaw();
````
2、在起飞后的下一个case,将起飞时的偏航旋转回去即可:
```C
Attitude_Control_set_Target_Yaw(iniYaw);

刚起飞偏航起飞点10 - 20cm

mode。cppwhile(1)前面增加以下代码,可在上电后立即进行一次陀螺校准(上电后尽量不要移动飞机,等校准完毕后再移动),如此可消除刚上上电陀螺不准造成的定位偏移

1
2
3
bool temp_user_msg = false;
changMode(11, 0, 0, 0, &temp_user_msg, 0, 0);
os_delay(10);

任务模式二次起飞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
						case 53:
{
model = mission_ind;
bool inFlight;
get_is_inFlight(&inFlight);
if(inFlight == false)
{
mission_ind ++;
}
else
{
Position_Control_set_XYLock();
Position_Control_set_TargetVelocityZ(-15);
}
}break;
/*****************任务二*********************/
case 54:
{
model = mission_ind;
Position_Control_set_ZLock();
Position_Control_set_XYLock();
if(flag >= 4)
{ //按下按键 收到起飞指令 鸣叫后等待20s后起飞
sendbuzzer(LEDSignal_Start2);
if(++ navInf.counter2>= 20*freq)//等待5freq 20*freq == 15s
{ //等待后 马上起飞
sendbuzzer(LEDSignal_Err2);
Position_Control_Takeoff_HeightRelative(170);
mission_ind ++;
navInf.counter2 = 0;
}
}
}break;

关键:判断是否已经落地,避免出现未落地就进入下个case导致飞行飞行混乱

1
2
3
bool inFlight;
get_is_inFlight(&inFlight);
if(inFlight == false)

评论