F7飞控项目调试过程的记录 系列文章第一部分

本文详细讲述了使用STM32F777NIHx主控板与BL电调、SBUS接收机和福特8遥控器的配合,如何通过调整TIM1的PWM输出频率实现精确的电机控制。作者首先验证了APM飞控的PWM频率,然后调整至400Hz以确保在电调工作范围内,并利用TIM1的计时器配置来生成不同周期的PWM信号。文中还涉及了电调解锁、上锁机制的测试,以及如何结合遥控信号进行电机转速的实时调控。
摘要由CSDN通过智能技术生成
主控STM32F777NIHx
BL电调(J-H-20A)
SBUS接收机、福特8遥控器
STM32HAL库

设计/调试记录文档


捕捉下APM飞控输出的PWM波形,可以看出PWM方波的频率为489.2966Hz,证明默认情况下APM飞控确实是以490Hz的速率输出到电调的。

好盈天行者系列电调为例,其最高为速率为432Hz,所以我们把输出速率设置为 402Hz (最好低于最高速率20-30Hz)

pwm输出:
PWM1--------------TIM1–>CH1,
PWM2--------------TIM1–>CH2,
PWM3--------------TIM1–>CH3,
PWM4--------------TIM1–>CH4.

设计50hz脉冲(周期20ms):因为TIM1和TIM8挂载在APB2上,根据下图时钟配置线上主频为216mhz.(其他定时器挂载在APB1上,线上主频是108MHZ)
在这里插入图片描述
所以时钟分频设置为2160分频 ,也就是100000hz,重装载值设置为2000,就会的到50hz(周期20ms)的pwm输出。
在这里插入图片描述

下载验证:实际输出。
在这里插入图片描述
改TIM1->CCRx值改变占空比。

将分频系数Prescaler改到270-1。也就是800000hz,重装载值还是2000-1。得到输出400hz的pwm,如下图

在这里插入图片描述
至此得到400hz的pwm输出频率给电调,通过调整占空比实现电机转速的控制。

-----------------------------------------start------------------------------------------
接收机的波形图(油门通道)

在这里插入图片描述
下图油门最小值
在这里插入图片描述
下图油门最大值
在这里插入图片描述

---------------------------------------------end---------------------------------------

20200922

重新调整pwm周期为14ms(福特8的油门通道输出就是14ms的脉冲,然后其中1ms-2ms的高电平为油门的整个行程)
所以分频系数改为2160,重装载值改为1400。 然后 ccr值占空比变化范围:计算公式1400*(1/14)~1400*(2/14),也就是100 ~ 200。

TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 2160-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 1400-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
 //  user_pwm_setvalue(1000);
 
 
//==========================pwm调试====================================  
// delay_ms(500);TIM1->CCR2=100;//实际测试100也能让电调解锁(电调上电后响一声  然后再长响一声 表示电调解锁完成可以调速了。)
// delay_ms(500);TIM1->CCR2=110;//实际测试110,电机也不转,电调也能解锁,115,电机开始转动。
// delay_ms(500);TIM1->CCR2=115;//如果初始给的这个值大于等于115,电调上电只响一声(听不到长响的声音,说明电调没有解锁。)  然后下面的改动ccr值调速,电机也不会转。
 delay_ms(1000);
 TIM1->CCR2=110;//目前认为  这个值是电调的解锁油门值(在模拟福特8油门通道的频率下,14ms周期脉冲,频率约为71.428hz)
delay_ms(1000);
TIM1->CCR2=115;
delay_ms(500);
TIM1->CCR2=120;
电调声音说明:

1、当侦测到油门信号时,发出一声低沉响声。表示解锁信号序列开始
2、然后,当油门值为0,发出一声明亮响声,代表解锁信号序列结束
3、当在解锁信号序列中,检测到100%油门信号,则电调开始校准油门行程。
4、当电调已经被解锁,但油门在给定时间内保持0油门,每3秒钟发出警报声,下图就是时间的设置,10min后电调会控制电机发出报警音,上一个参数 beacon Volume是报警音的音量大小调节。
在这里插入图片描述

实际测试可知:
给电调最低油门数据(100-110),电调响两声之后,说明电调解锁完成可以调速(封装函数接口,设计电机解锁指令使用)
给电调pwm信号 输出低电平的时候,相当于锁定电调,此时电调只响一声,转速就不能调节了(封装函数接口,设计电机关锁指令使用)

	delay_ms(500); TIM1->CCR2=0;//试验一下电调有没有上锁功能。(验证可以当成上锁用)
	delay_ms(1000);TIM1->CCR2=190;//试验一下电调有没有上锁功能。
    delay_ms(1000);TIM1->CCR2=120;//试验一下电调有没有上锁功能。 

下一步将遥控输入数据 和pwm数据结合控电机转速(先不经过pid控制环路控制,直接驱动试试)

测试保证信号脉宽是1ms-2ms变化,然后改动频率 。

270(2.5ms周期) 800-1600,但是 115 电机也能转 这个明天分析。

540(5ms周期) 400-800

1080(10ms周期) 200-400

2160(20ms周期) 100-200

【转】
PWM信号的频率是通常是没有规定的,可以是50hz、100hz、200hz或500hz等等。控制频率越高,其周期越短,控制间隔也就越短,电调和电机响应速度也就越快。反之,控制频率越低,其周期就越长,控制间隔就越长,电调和电机的响应速度就越慢。早期电调响应PWM	信号的频率是50hz,但随着科技的发展和对控制流畅度的要求,现在多数电调都支持500hz以上的PWM信号,并且电调内部自带滤波器,可以很好的响应并控制电机的转动。

20200923

决定使用400hz的pwm驱动频率

先确定调速范围

delay_ms(1000);TIM1->CCR2=90;
delay_ms(1000);TIM1->CCR2=100; 

测试发现90,100都能解锁电调,但是电机不转

delay_ms(500);TIM1->CCR2=105;
delay_ms(500);TIM1->CCR2=110;
delay_ms(500);TIM1->CCR2=115;

当电机≥115时,电机才开始转动。(可以设计成电机怠速值)

理论上算400hz的频率 值的范围是800-1600,为什么实际测试100-150也可以操作电机?
怀疑是 50hz的pwm 周期是20ms, 现在变成400hz,2.5ms
400hz的条件下 20ms时间里面 有 8个2.5ms ,
当设置ccr=100是,示波器检测高电平是120us。120us*8=960us。
所以在20ms时间内 电调认为是启动解锁了电机 。 这种现象 电调是算20ms内的高电平总和。

经过测试发现 100-150电机虽然能转动,但是过了150电机会异常

所以 还是使用理论值 800-1600(400hz频率值的范围)
验证800个值每单位数值都有速度的变化,值范围对应1ms-2ms的脉冲宽度。配置如下:

计算过程:
216000000/270/2000=400hz,1/400=2.5ms
1/2.5x2000=800 ,2/2.5x2000=1600
所以1ms-2ms的pwm值对应800-1600

void MX_TIM1_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 270-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 2000-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.BreakFilter = 0;
  sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
  sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
  sBreakDeadTimeConfig.Break2Filter = 0;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim1);

}

开启pwm输出

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);

电机解锁指令

void MOTOR_OPEN_CMD(void) //电机解锁指令
{
	 TIM1->CCR1=0;	 	 	 	 	 
	 TIM1->CCR2=0;		 	 	 	 	 
	 TIM1->CCR3=0;	 	 	 	 	 
	 TIM1->CCR4=0;
	 	
	 delay_ms(500);
	 TIM1->CCR1=800;	 	 	 	 	 
	 TIM1->CCR2=800;		 	 	 	 	 
	 TIM1->CCR3=800;	 	 	 	 	 
	 TIM1->CCR4=800;
	 delay_ms(500);
}

电机上锁指令

void MOTOR_CLOSE_CMD(void) //电机上锁指令
{
	 delay_ms(500);
	 TIM1->CCR1=0;	 	 	 	 	 
	 TIM1->CCR2=0;		 	 	 	 	 
	 TIM1->CCR3=0;	 	 	 	 	 
	 TIM1->CCR4=0;
	 delay_ms(500);
}

与遥控通道数据比例融合

计算方法:
遥控通道数据 352-1696,pwm数据 800-1600。
1696-352=1344,1600-800=800,800/1344=0.5952380952380952(比例因子)
实际输出pwm=800+(α)*800/1344 ,(α 为0-1344)
其中α=β-352,(β为实际遥控数据值,352<β<1696),代入
实际输出pwm=800+(β-352)*800/1344 ,(352<β<1696)。
ps:计算可使用浮点数计算,实际输出可以取整。

//结构体指针作为形参
void rc_pwm_ctr_test(struct _att_control *_att_con,struct _RC_SBUS  *_rc)//遥控数据转换为tim1的ccr值 输出pwm给电机
{
	u8 counts;
	if((*_rc).RcPitch<352||(*_rc).RcPitch>1696)//油门值越界不进行处理
	{
		return ;
	}
	for(counts=0;counts<4;counts++)
	{
		(*_att_con).out_pwm_ccr[counts]=800+((*_rc).RcThrottl-352)*800/1344;
	}
}

然后将4个电机并联在一起重新校准一遍电调。运行程序

测试结果是可行的 ,可以直接用遥控器的油门给到f7主控然后经过转换输出 pwm给到电机了 ,实现了电机的调速。接下来就是加入pid反馈控制算法了,动态调节转速。

测试发现可以将这个油门附近的值作为后期飞机怠速使用的功能
在这里插入图片描述

如果用0-1之间的数值规定输出800-1600的范围数据,计算方法如下:
实际输出pwm=800+γ*800 (γ为0-1)

参考:
http://www.doc88.com/p-7505653338402.html
https://zhuanlan.zhihu.com/p/42742897
https://blog.csdn.net/qq_28056277/article/details/91347436
https://wx.renrenso.com/wx/show.php/zKil1Kudk2il1l6nx5uondNnqaFenKillNaVr3WDka22g6KWkMvMpmvIpnvbnKSNzA==
https://blog.csdn.net/moumde/article/details/107620142
https://blog.csdn.net/snail_dongbin/article/details/82803076?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值