主控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

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

  1. Koa项目搭建过程详细记录

    2019独角兽企业重金招聘Python工程师标准>>> Java中的Spring MVC加MyBatis基本上已成为Java Web的标配.Node JS上对应的有Koa.Expre ...

  2. caas k8s主控节点如何查询_k8s中部署prometheus监控告警系统prometheus系列文章第一篇...

    前言 本篇文章主要介绍k8s集群中部署prometheus,并且配置prometheus的动态.静态服务发现,实现监控容器.物理节点.service.pod等资源指标,配置prometheus的web ...

  3. k8s中部署prometheus监控告警系统-prometheus系列文章第一篇

    前言 本篇文章主要介绍k8s集群中部署prometheus,并且配置prometheus的动态.静态服务发现,实现监控容器.物理节点.service.pod等资源指标,配置prometheus的web ...

  4. 跟我学spring security系列文章第一章 实现一个基本的登入

    文章目录 指定依赖 安全配置 添加controller测试代码 测试 源码地址: https://github.com/pony-maggie/spring-security-learn 指定依赖 s ...

  5. K8S大规模集群优化方案系列文章-第一篇

         ▲ 点击上方"DevOps和k8s全栈技术"关注公众号 Kubernetes 自 v1.6 以来,官方就宣称单集群最大支持 5000 个节点.不过这只是理论上,在具体实践 ...

  6. keil debug如何在watch直接修改变量值_python日志记录系列教程,内置logging模块(一),直接使用logging模块的基础日志记录

    前言:成熟的软件开发不可避免的要进行日志记录,python内置模块logging提供了强大的日志记录能力,本文将从多个角度,由浅入深的介绍logging的常见使用方法和一些基本概念,本此系列文章分为两 ...

  7. cassss服务未启动_不要再本地启动项目调试了,试SpringBoot远程调试你会发现新大陆!...

    前言 上周末一个朋友庆生,无意间听他说起了近况,说公司项目太多了,每天一堆BUG需要修复,项目来回切换启动,真是挺烦的. 随着项目越来越多,特别是身处外包公司的朋友,每天可能需要切换两三个项目,难道一 ...

  8. 信息化项目实施过程管理的解读(一)

    序言 信息化项目实施过程管理是一个非常复杂的课题,本次主要就过程中几个大项的重点内容的实战经验和大家交流一下,希望能达到抛砖引玉的效果. 信息化项目的实施服务和家电的服务完全不是一个概念,家电服务讲究 ...

  9. 腾讯在线教育互动课堂——Demo调试过程记录

    官方文档地址:https://cloud.tencent.com/document/product/680/17888 "Demo调试"不像集成使用,不需要完全按照文档一步步处理, ...

最新文章

  1. 使用DPM2007备份还原Exchange2007邮箱数据库
  2. python学习-条件语句
  3. Android多媒体开发-- android中OpenMax的实现整体框架
  4. 【BZOJ 2753】 2753: [SCOI2012]滑雪与时间胶囊 (分层最小树形图,MST)
  5. c#如何识别一张图片的格式
  6. 高等数学下-赵立军-北京大学出版社-题解-练习10.3
  7. 无法获取 vmci 驱动程序版本: 句柄无效
  8. 编写高质量代码的50条黄金守则-Day 04(首选字符串插值)
  9. eclipse每次闪退后都提示查看\workspace\.metadata\.log
  10. 啊哈算法——第一章第一节:桶排序
  11. Oracle获取日期大全(当月的第一天/后一天/上一天/最后一天/上个月这一天)
  12. QQ、微博、陌陌:社交难逃社交命
  13. yuyu终于考完了!我提前过生日了!(两者好像没有关联嘛^_^)
  14. P1359 租用游艇(dijkstra不优化)
  15. 35. 我用Compose开发了一款音视频处理app
  16. 亚马逊SP-API对接实践
  17. python 情感分析实例_基于Python的情感分析案例
  18. Windows下动态内存分配方式http://whx.tzgt.gov.cn/newOperate/html/7/71/711/3938.html
  19. 因果推理(八):工具变量(Intrusmental Variables)
  20. HDU 3031 ToBe Or Not To Be(模拟)

热门文章

  1. 编写一个函数判断一个整数是不是素数c语言,编写函数判断一个整数是否为素数....
  2. 知名插画师走尺,带你走进“薪”世界
  3. 插画师的配色灵感分享
  4. C++动态分配new(C++ primer,P320)
  5. HDU 6656 Kejin Player
  6. 一语中的丨高对抗重实战攻防视角下,企业安全运营到底该怎么做?
  7. python3进阶篇(二)——深析函数装饰器
  8. 布林通道参数用20还是26_boll参数20还是26好 股市的布林线的三根线是什么
  9. 187、商城业务-检索服务-页面排序功能
  10. TCP 包完整性检验