NUCLEO-U545RE-Q板卡评测(第二弹)U545移植TMC_API 一、前言这篇文章的编写耗费了一些时间。因为U5是一个完全不同的架构,我尝试了TrustZone的方式编写程序,发现对其中的一些概念还有些模糊。U5很牛的LPBAM也还没有玩转,所以架构部分的分享可能要稍晚一些再做。 这次趁着手边有TMC22xx的开发板,刚好自己也正在设计开发一个STM32G0系列的开发板。那就顺便以U5作为载体,先验证TMC_API的移植。目前移植的过程我分成了两步,先编写基础的BSP部分,以实现LOG打印和步进电机的传统控制(STEP/DIR/EN);然后移植TMC_API。 当然可能有人不了解TMC22XX,我在这里简单介绍一下。TMC2208/TMC2209是常见的静音步进电机驱动,很多3D打印机会使用这种驱动实现比较好的步进控制。它的厂家是Trinamic,先是在20年被Maxim并购,接着巨无霸ADI又把Maxim并购。所以现在Trinamic是ADI的一部分。上半年Trinamic似乎还有自己的网站,现在被ADI整合。整合后很多资料都不好找了。不像以前那样产品分类井井有条,资料也很容易找。 二、U5的X-CUBE-AZURERTOS在哪里?在刚开始接触U5的时候,我最初其实以为U5还没有移植threadx。但我想U5已经发布一年多了应该不会吧。像其它系列那样我移植在官网、社区寻找 X-CUBE-AZURERTOS-U5可是苦苦寻找不到。在查看x-cube-u5的文档的时候发现架构里面明明是有threadx的。后来查看UM288(Getting started with STM32CubeU5 for STM32U5 Series)时看到了一幅图: ThreadX赫然放在中间层(Level 1),除了ThreadX之外当然还有FileX/LevelX,USBX,NetX Duo等。这时我就在思考为什么U5没有将X-CUBE-AZURERTOS独立成一部份,是不是因为上层(Level 2)的某些组件是需要依赖于ThreadX的呐?目前还没有答案,有知道的朋友请不吝赐教。 三、GPDMA和LOG的实现有开发经验的朋友都知道,传统的printf其实非常的低效。每次都是一个字节一个字节输出的。对于有DMA的设备这样用UART其实非常的低效。所以在开发时往往会自己编写一个使用DMA传输的printf。如果你还用RTOS,那么可以结合queue来将需要发送的信息索引放入缓冲栈中,然后再由一个线程在相对空闲时将需要发送的信息通过UART的MDA形式发送出去。 至于需要发送的信息怎么放入,当前使用的时RTOS的mempool的形式。每条信息都需要占用一个固定的长度。这种方式在消息比较少时还可以。在连续多条时很快就会将会内存池占用完,这就会导致信息的漏发。后面准备开发一个RingBuffer来管理不需要分条发送的信息,这种信息(比如dump信息)可以使用RingBuffer开发送。这样可以避免漏发的问题。 这部分代码暂不公开了,可以查看我的github的项目UART_Receive_WithIdle了解类似的代码。这里用的板卡是Nucleo-H723ZG,大同小异。后面等U5的这部分程序完全开发完毕,再公开项目到github.具体信息看本次评测的后续情况。 这里需要重点说明的是U5的DMA开发过程完全不一样,U5有GPDMA1和LPDMA1两组DMA。前者在Main Domain,后者在SDR Domain。外设和SDRAM的选择非常重要,否则可能会导致hardfault或者DMA的效率底下。GPDMA功能非常强大,除了普通模式还支持链表模式。之于GPDMA的使用其实可以单开一篇文章。这篇文章的重点不是将GPDMA,所以就简单说明一下。 感兴趣的朋友可以查看<font color=red>AN5593-如何对STM32U575&585微控制器使用GPDMA</font>.这篇文章对GPDMA有很好的讲解,从通道的配置到不同外设的注意事项都很详尽。这一必须再款将一下ST,我觉得ST的技术支持工作真的很好。非常方便个人开发者自学和深入。 四、OC功能和步进电机的控制4.1 STEP/DIR/EN控制介绍步进电机的传统控制方式经常使用STEP/DIR/EN引脚来控制。STEP需要产生一个需速度匹配的脉冲;DIR和EN都是普通的输出信息。DIR的高低电平分别代表步进电机的方向(或者说A+,A-,B+,B-的电平变化顺序),EN,有的叫ENN,用高电平或者低电平取使能步进电机的输出。步进电机不像其它普通的电机,当输出Enable时,电机会被锁死在固定位置。直到step将它移动到下一个位置。现在大部分的步进电机驱动器都支持MicroStep技术(微步技术)。那么什么是微步技术,你可以想象成段誉的凌波微步(不是),或者戏剧舞台上的鬼步。就是将一大步分成无数的小碎步。比如现在常见的电机是1.8°的,就是一圈是200步。当然也有更精密的0.9°步进电机,一圈就是400步。微步就是将一步分成4步、8步、16步、64步甚至128步或者256步。拿TMC2209为例: 可以看到它有8,16,32,64微步技术。比如如果我将MS1和MS2是内部下拉的,如果将它们悬空,那么电机要走一大步就是要走8小步,step必须给8*200=1600个脉冲,电机才能转一圈。微步如果越是大,电机就越是平滑。当然带来的坏处是,电机的“冲力”就小。可以想象一下你大跨步冲上陡坡和用小碎步冲上陡坡。不过这通常影响不大一般我们还是选择大一点的微步,这样电机带来的抖动会大大降低。再结合RAMP技术,就会带来非凡的体验。 步进电机的控制其实也可以用FOC,不过这里就暂时不去深究这一部分。有兴趣的朋友可以在这一部分多加了解。 4.2 STEP信号的产生其实步进电机传统控制最关键的是STEP信号的产生。对于脉冲的产生,我们通常会想到的方式是PWM方式。当然也可以用定时器去定时反转IO引脚。但是前者如果要改变速度你就需要改变两个量,一个是Period的计数值一个是Duty的计数值。后者需要CPU参与去反转。其实有一种更好的配置是OC(Output Compare)方式。输出比较切换模式提供了在保持占空比固定的情况下的,只改变Period的可能。这样可以尽可能少的占用CPU的负载。 至于OC的使用,有兴趣的朋友可以看ST社区发布的一篇文章LAT1155 使用输出比较模式产生相移信号.其实我记得还有一篇介绍,但是苦于找不到。 这里说他一个小插曲。正如LAT1155里面的示例所显示的那样CCRx寄存器实际是用来改变相位的。要改变period其实要改变的是CNT值(ARR寄存器)。但是我最初改变的是CCRx的值,这就导致了无论怎么搞周期始终不变。 其实这一步还有一个很trick的地方是怎么开启DMA。因为我们要改变的是周期,所以正如上文所说其实需要改变的是CNR或者AAR寄存器。如果你使用HAL_TIM_OC_Start_DMA去开启DMA传输,但是GPDMA其实链接的是TIM_UP,会进入hardfault。而你不能错误的将DMA通道链接到TIM_CCRx上。因为这其实改变的是触发的相位而非周期。这就需要你自己编写一个开启OC同时开启DMA的方法。 具体怎么做其实也不复杂:
在描述的最后献上测试视频: 第一个视频是:多个速度和正反转控制 TMC_API移植准备之一:步进电机测试_哔哩哔哩_bilibili <iframe src="https://player.bilibili.com/player.html?aid=963670709&bvid=BV1AH4y127qv&cid=1340402023&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> 第二个视频是:加减速测试 <video src="https://www.bilibili.com/video/BV1ou4y1L7hc/?spm_id_from=333.999.0.0">你的网站不支持video标签</video> <iframe src="https://player.bilibili.com/player.html?aid=918631946&bvid=BV1ou4y1L7hc&cid=1339959530&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe> 4.3 INDEX信号TMC有个index信号用来记录波形的数量,这个信号如果引出可以用一个TIMER的计数模式去记录,这样就可以"伪闭环"的方式记录已经发出的脉冲数量,这样可以进一步去停止或者改变下一步的波形。 但如果没有index信号,也可以将将OC的trig信号输出,然后通过计数模式去记录发出去的波形数量。同时可以用DIR信号去控制计数是递增还是递减,这样也从某种意义上实现了一个“软编码器”。当然这个“软编码器”实际是个假的编码器。 4.4 RAMP步进电机的加减速过程其实非常重要。我们常用的时Linear加减速。但是实际上如果考虑时间因素的话,很多加减速难以计算。具体可以查看这篇文章 对于更复杂的S-RAMP它的计算就更复杂了,这一部分我也在仔细研究。暂时没有什么好分享的。 五、TMC_API的移植终于来到我们最关键的TMC_API的移植。在移植之前我们肯定需要了解的是为什么移植。 5.1 TMC_API是什么,我为什么要移植TMC_API这里是TMC_API的简单介绍:
我自己之所以选择要移植TMC_API除了好奇之外,还是想在使用TIMER实现繁琐的RAMP实现之外,尝试使用UART/SPI等总线自由的配置它的参数。自己在根据手册,去hardcore每种芯片的驱动显得吃力不讨好。 目前预想的结果是移植之后,TMC的多数芯片我都可以实现通过总线控制。这样我甚至可以省下一些硬件成本(比如不用电位器去手动调节电流大小,比如微步的设置也可以全部从软件实现就节省了拨码开关的成本。) 更加理想的是可以下一步对接TMCL_IDE,通过电脑界面简单配置驱动器。 5.2 TMC_API移植分析我们以TMC2209.h和TMC2240.h 下面是TMC2209.h的几个核心函数:
下面是TMC2240.h的几个核心函数
分析后发现上面的几个函数都是应用函数,那么需要移植的函数在哪里? 我们查看TMC2209.c会发现
同样的TMC2130.c中有:
但是在TMC2240.c中,略有不同:
通过上面的分析我们大概能否明白怎么移植,至于更细节的部分可能要结合具体实现来了解。 其实TMC_API工程的ReadMe也有简单的介绍,只是不够准确:
上面的中文和标签是我自行修改的。方便大家理解。 另外需要说明的是移植工程时只需要将工程的<span style="color:red; font-weight:bold">tmc目录所在的路径</span>包含进去即可。因为所有的TMC_API的header都是以tmc/...include进去的。 5.3 深入分析TMC_API的功能TMC_API的tmc下包含了三个目录:helpers, ic和ramp.
5.4 移植过程编写移植的函数。按照上面的分析主要时读写函数的移植、CRC的移植(如果有必要),然后编写初始化函数,周期性调用tmcXXXX_periodicJob。 这里涉及的具体工作很多,具体不再赘述。 [坑比较深,正在移植...] 5.5 移植TMCLTMCL如果实现可以使用TMCL-IDE来控制。 [正在移植...] 5.6 实现移植的效果[敬请等待...] |
【STM32H7S78-DK评测】-5 LVGL&DMA2D DEMO测试
【STM32H7S78-DK评测】步进电机控制介绍一与tensorflow安装与测试
【STM32H7S78-DK评测】XIP模板问题处理与电机控制
【STM32H7S78-DK评测】开发板初识与工程模板创建
STM32U5 系列使用 LPBAM 进行功耗优化
【NUCLEO H533RE评测分享】高性能和低成本双Buff加持的NUCLEO H533RE
【NUCLEO-H533RE评测】+09 低功耗测试
【NUCLEO-H533RE评测】+08 初识FreeRtos
【NUCLEO-H533RE评测】+07 IIC调试
【NUCLEO-H533RE评测】+06 ADC调试
移植效果有了么哈哈
期待一下移植效果,这个还没玩过呢。学习学习
已经尝试移植了,TMCL尝试了握手部分,已经可以被TMCL-IDE识别了。但是手边的项目忙,预计要忙完之后再接着移植。
感谢关注