既然 ROS 中和嵌入式(单片机)硬件打交道的示例多数是基于 Arduino的,又有开源的资源支持用STM32 作为 Arduino 的 MCU,那当然应该考虑将 Arduino 环境作为小车控制器的开发平台了,这样可以充分利用网上的共享资源,少走弯路。
而且,可以将精力集中于应用层,而非消化那些工具或相对晦涩的硬件手册,向“与硬件无关的编程模式”更接近一步。
实际上嵌入式应用开发应该是将时间和精力放在对现实问题的需求分析、构思解决方案、编写程序构架及相应的算法;最好无需消耗精力去学习开发工具的使用和编写芯片驱动程序,从而可以充分发挥人的创造性思维能力。
芯片厂家已经在做相应的努力了,STM32 的最新库就命名为 HAL(Hardware Abstraction Layer 硬件抽象层),目的就是将开发人员对芯片手册的依赖降低到最小。
Arduino 又进行了一次封装,使单片机的软件开发更接近于纯软件的编写。为何不去充分的享用这些资源带来的福利呢?
前面初步尝试了用 ST 的 Nucleo STM32F103RB 开发板在 Arduino下编程,可以实现,自我感觉是既享用了基于 Arduino 开发的便捷性,又能用到 STM32 的强大性能;即便是最普通的 STM2F103RB,也有 20K RAM 和 128K FLASH ROM,这是原来 Arduino 所用的 Mega328 无法比拟的,如果算上 STM32 丰富的外设资源,那就更不用说了,何况还可以支持基本上是全系列的 STM32 芯片,从 F0 到 F7,可以说不用担心硬件资源不够的问题了。彻底消除了 Arduino 硬件资源不足的槽点(Arduino 官方也出了使用 arm cortex-M 内核的板子,但价格和市场上丰富的 STM32 板无法比)!
但使用 Nucleo 板作为小车或其它用途的控制器还是有些不足,其一是价格略贵,因为其集成了STLink(剩余部分实际上就是个核心板)。其二是电源、地线插针不够,虽说将 MCU 所有的引脚都引到插针上,可如果用杜邦线接外设模块,就会发现电源和地线无法接,还得动烙铁,这对学习者是个麻烦,尤其是在校的那些不具备焊接条件的学生。
在消化 STM32duino 的过程中,发现它不止是支持 ST 的 Nucleo 板,还支持了其它的板子,其中有“Generic STM32F1 series”,包含的板子中有一个“ BluePill F103C8”,在网上一搜,原来就是我目前用来做“USB无线适配器”所用的 STM32F103C8 核心板:
既然这个可以,那成本就很低了,这款核心板淘宝上很多,只有十几元。
它和 Arduino Nano 大小差不多,外形是按照 DIP40 芯片设计的,引脚尺寸和 DIP40 一样。由此联想到以前所做的那个用 nano 作为下位机的手机控制小车:
上面用了一块nano扩展板:
它设计得挺巧妙:外形尺寸按照 UNO,并设计了 UNO 的插针位置。中间设计了 nano 插座,可以将nano 转换为 UNO。
其最让我满意的设计是:将 nano 的每个 IO 都单独设计成一组 3针插座 —— G V S,按照舵机插头的顺序排列。这样连接舵机十分方便,等于附带了丰富的电源和地线插针,可以很方便的通过杜邦线连接其它外设,比 UNO 板好用!
小车上用的“轮式驱动单元”设计就是用杜邦线作为连接端,使用这个扩展板很容易就接好了,十分方便!蓝牙模块也是通过杜邦线连接的。
受这个扩展板启发,我何不也设计一个类似的扩展板?用 BluePill F103C8 代替 nano,布线按照STM32Duino 库中的定义,这样不是可以得到一个使用方便的、基于 STM32 的 Arduino 控制板了?!
说干就干,首先设计一个PCB,暂且称其为 —— BluePill扩展板PCB:
基于此构成一个 BluePill F103C8 扩展板:
为了PCB排线方便,将BluePill核心板设计为元件面向下安装,插针焊接在元件面:
两者结合,一块基于 STM32F103C8 的 Arduino 控制板诞生了:
首先使用 Arduino 最基础例程 Blink(类似于C语言学习中的Hello World程序)测试,选择 STLink 下载。程序不用修改,即可完美运行!
注:我安装的是 Arduino 1.88 版本,此版本的 Blink 程序已经改进过,程序中 LED 引脚不是直接使用13,而是使用了符号常数:LED_BUILTIN,使得不同的板子对应的库可以定义到实际接 LED 指示灯的引脚上。BluePill F103C8 板的 LED 引脚实际是:PC13,对应 Arduino IO 的定义应该是17。
关于 BluePill F103C8 板的Arduino 引脚定义说明详细见以下目录中的文件:
C:\Users\用户名\AppData\Local\Arduino15\packages\STM32\hardware\stm32\1.5.0\variants\BLUEPILL_F103XX
这个是 Arduino 安装后对应的工作目录,里面有相应的STM32引脚和Arduino引脚的对应定义,还有所有的STM32 的 Arduino 库函数,完全开源的,可以在其中查找通过 STM32 实现 Arduino 编程的细节,并可以从中改善某些性能。
接着又测试了示例程序:ASCIITable,因为 ROS 需要使用 Serial(UART),这个例程是通过 Serial输出 ASCII 表。同样是无需修改即可运行!唯一和标准 Arduino 不同的是:Arduino 标准板是用板上集成的USB转串口实现 Serial,用 BluePill 需要外接一个 USB转TTL电平串口的模块,实质是一样的。
光使用例程还不够,需要自己编写一个可以解决实际问题的程序验证一下,看看使用基于 STM32 的Arduino 板有什么不同。
懒得再构思需求了,直接将原来单轮小车用的 Arduino 程序移植过来。
原来是编写了一个用于驱动轮式驱动单元的库。参考网上的示例,将库转换为C++程序的类定义,放在Arduino程序同一目录下,形成类似于“工程”的方式。
Arduino和Processing一样,在同一目录下的文件,均自动关联,这比C语言的工程构建简单多了。
按照 STM32Duino 的硬件特征,将原来写的库函数略作修改,作为 C++ 的类定义。STM32 的资源比 AVR 的 Mega328 强多了,中断可以有16个,舵机输出没有那么多限制,PWM 也很灵活。重新定义原来的输出IO,并修改相应的函数后,原来的功能实现了^_^:
发现用类定义的方式不错,一是可以学习 C++ 的编程思路,这对于玩单片机的人来说是比较缺乏的;二是可以根据需要,编写一些基于 STM32 标准库的函数,封装为自己特殊的应用函数,以提高程序的性能,简化程序的设计。
至此,基于 STM32 的 Arduino 开发软、硬件环境构建完成了,下一步尝试引入 ROS Serial,看看效果如何。
注:程序附在 QQ 群 32438885 的共享文件夹中,供参考。