记录一下卡了我很久的一个小问题,今天解决了,真的很开心 2022.10.11
看了CSDN上很多人的文章,感谢他们的分享,也超级感谢本科实验室的同学的帮助和指点
问题现象描述:
关于3508电机通过封装的驱动函数,直接给v的值,但是每次给完对应的数值后,电机均会一直加速
硬件条件:
3508电机、C620电调、电调中心板2、硬石stm32f407IGT6
①第一个实现功能的代码
这个代码只用于3508电机的驱动测试,不适合后续添加功能,否则时间轴会乱掉,也是后面的优化方向。下面讲讲思路
通过定时器控制3508按照一定的速度转动一定时间
代码的逻辑结构
这个是用于驱动电机的函数,写在了main.c文件里面
这里是发现的第二个坑,不过只用于当前这种测试情况,即没有把DiPan_Motor_Forward写进定时器里面的情况。
这里需要提到一种情况,就是3508的电机在仅仅通过单片发送can报文到电调的时候,电机会从0一直加速,就不会管你给了多大的报文数据,v=1000,还是700,一直加速到最大速度,而且只要发送的次数越多,这个能够驱动电机的数据大小越小,甚至10,20都能驱动,并让电机一直加速。
第二个坑是,之前的代码一直没写HAL_Delay(2);无意中加入了这个,然后电机就能按照自己设置的速度转动了。在按键实验中,这个的作用是防抖,但是在这里不知道原理是什么,不知道有没有人已经弄清这个原理了。
can报文的读写,以及pid参数初始化,获取电机的状态值都是参考的 RM官方代码和开源的一些代码
主函数的while循环里面加入一个判断,这里把驱动函数写在了判断里面。根据全局变量stop来进行判断,每种stop对应一个速度,分别是0和1000的时候,对应让电机停下,和按照200这个参数对应的速度转动。
再是定时器3部分的内容,即tim.c里的内容
设置定时器的tout为1s
这里其实有一些坑,网上找的判断定时器的那句
if (htim->Instance == htim3.Instance)原本是if (htim == &htim3),导致中断回调函数一直不起作用,进不了
然后在定时器里面加入一个判断,通过Tim_cnt,每隔一段时间,也就是1sXTim_cnt,这样我就可以控制这个电机粗略地转动1sXTim_cnt的时间。当这个计数值达到我设定的值,将计数值清零,stop置1,等到中断服务函数结束,回到主函数循环中,进行if判断,读到stop==1后,电机执行停止动作。
这里要考虑的一个问题是,当还在执行电机驱动函数DiPan_Motor_Forward(1000);时,就进入中断,在中断结束后(假设结束后stop置1),会回到驱动函数继续执行没执行完后驱动函数,电机会最后以这个驱动函数所给的速度转动一段时间,然后再次循环,进入if判断,从而停止电机
这就是所有的代码执行流程,确实能够实现我想要的功能,但是问题在于每次执行的效率很低,每当加入新功能时,定时器的执行周期就会减少或者增加,这个是不确定的,也不符合后期的目标,因此这类代码只用于测试电机的旋转或单个功能的实现。
②在此基础上,我修改了代码的结构,原来的代码其实上把中断和控制的任务刚好反过来了,现在的任务是把这两个换回来,同时还有一点十分重要的是,在定时器里面,不能加入延时函数,否则debug会卡在那里。
优化的地方在于
修改了定时器中的内容,将电机驱动函数DiPan_Motor_Forward放入到中断服务函数里面,Tim_cnt实现的是同样的效果,而且把定时器的tout变成了10ms进一次中断,效率更高,这样一来,每次调用这个功能的时间周期就是固定的
修改了主函数循环中的内容,定义了一个全局变量vel,就是输入到DiPan_Motor_Forward里的参数,通过改变循环中的vel值,来实现功能,实验后实现了我所需要的功能。