Adventures in STM32 land
I decided to start experimenting with the STM32 line of microcontrollers. I have a Nucleo-F401RE board I got gifted by ST themselves when I visited their stand at the MakerFaire Rome in 2023 (I think it was my second year of uni), alongside a sound shield/HAT/whatever they call them. They were giving boards away like candies and I really can’t complain.
I also have a BluePill F103C8 which I think I stole from my dad with the intention to use “later”.
I followed their getting started guide and an unhealthy dose of videos from Phil’s Lab. I really like the guy, he makes great content.
It seems I have to install three different software packages:
- STM32CubeMX which is like a launcher. It includes examples and a configurator which generates code on the background to reflect the configuration of the interfaces. Looks cool.
- STM32CubeIDE is the actual IDE and is based on Eclipse (ah, my memories of writing crappy minecraft mods come back all of a sudden). You have to import projects from STCubeMX once they are generated. I don’t know if they can be modified after being generated. I would guess so, especially when using evaluation boards like my Nucleo.
- STM32CubeProg I still don’t actually get what it does. I think something related to USB drivers and firmware updates for the programmers?
I installed everything in distrobox, ubuntu 22.04, then used distrobox-export to create desktop entries for my host.
At first I generated a project from the example GPIO_Toggle, which shows how to blink a LED. I managed to modify this to also read a push button on my Nucleo and turn the LED On when the button is pushed. I basically just read the documentation in the corresponding HAL file.
Everything seems decently high level: simple functions to interface with the Hardware (comparable to Arduino, at least for now) are defined in HALs (Hardware Abstraction Layers) which feature drivers and configurations according to the setup in STCubeMX.
For this project I need:
Reading ADC to read current values from the DRV8251/INA240, ideally with DMA at a fixed rate (needs timer!)
2x PWM outputs for the motor driver, ideally up to 200kHz which is the maximum supported by the DRV8251
PID Controllers
- The uC onboard the nucleo has a FPU for precise floating point computations and support DSP instructions
- The CMSIS framework also has support for optimized PID controllers (TODO: link to CMSIS)
- I can make one on my own, if previous options all fail
In STM32CubeMX:
Pinout & Configuration to select which pin does what and relationships between all peripherals (ADC, DMA, Timers, digital GPIO…)
Has a clock configurator to generate proper settings for all clocks/prescalers/etc. I left this untouched, my board doesn’t have a quartz oscillator soldered on, so I left the internal 16MHz RC oscillator active. By default the max frequency is set to 84MHz. I will probably have to come back to this for the various timers for PWM etc.
In Project Manager I simply entered the Project Name and Location and set the Toolchain as STM32CubeIDE with “Generate under root” flag check, left everything else as is.
In Tools it has CAD models (symbol, footprint, 3d) for different CAD, KiCad included! It seems to be powered by Component Search Enginer, which I use already.
Then File>Save Project and then Generate Code. It will generate a project with the chosen name under the chosen directory. It seems to have generated it as a C project by default, I didn’t catch any setting for that.
In STM32CubeIDE
I imported the project in STM32CubeIDE using File>STM32 Project Create/Import and selecting the Project Directory. The project should import automatically if selecting the option in CubeMX, but I have not linked the importer properly between host and distrobox.
PWM
The Nucleo has a connector compatible with that of the Arduino UNO R3. From bottom to top, pin D3 is Channel 2 of Timer 2. In CubeMX, Pinout&Configuration>Timers>TIM2. I selected the clock source as the internal clock (as it seems to be the only available, and set Channel2 to PWM Generation CH2. Left the other options as is because I don’t know what they are (yet).
In Parameter Settings I only enabled Fast Mode, then re-generated the code. I guess I will have to play with prescaler and counter period values to chose the PWM frequency. For now I want to see what it is by default. With the internal RC oscillator, I do not expect the frequency to be extremely precise.
After a couple of days of messing about, I learned that the same function can be associated to multiple pins (in terms of timers, gpio ports, adc, etc). In CubeMX it’s important to check that the pin that is selected by default for a given function is the physical pin where e.g. a connector is wired into
CMSIS-DSP libraries
Followed mostly this guide: https://community.st.com/t5/stm32-mcus/how-to-integrate-cmsis-dsp-libraries-on-a-stm32-project/ta-p/666790
- Download the CMSIS-DSP repo
- Copy Source, Include, PrivateInclude to new subfolder in “Drivers”
- Add Include, PrivateInclude to project path/includes
- Delete all unnecessary functions (I kept only basic and fast math + PID)
- Comment out every “#include “whatever.c” line from Major .c files (like BasicMathFunctions.c, FastMathFunctions.C) in src.
- Comment out deleted folders from “arm_math.h” and the likes
References
- https://community.st.com/t5/stm32-mcus/stm32cubeide-2-0-0-workflow-tutorial/ta-p/864831#toc-hId--1415362376
- https://wiki.st.com/stm32mcu/wiki/STM32StepByStep:Step1_Tools_installation#Install_STM32CubeProg
- https://arm-software.github.io/CMSIS_6/latest/General/index.html
- https://www.st.com/en/evaluation-tools/nucleo-f401re.html#