Setting up SimpleFOC with Storm32

Hello, I decided to take a dive into playing with FOC control and stumbled up on this community. I purchased some BLDC motors with AS5048A Encoders and a Storm32 BGC V1.32 board to start a project. However, I am having trouble understanding how to upload code to the board. Do I need to use a bootloader with something like ST-Link V2 to flash different firmware in order for it to accept my code? I am using platform IO in visual studio code like I have seen in some tutorial videos but haven’t seen anything to with the storm 32 board specifically. Also, has anyone had any luck with hooking up the encoders to this board specifically? Let me know if any other clarifications are needed or more info on the hardware!

Hi, never used this boards but seems that you are not the first one trying to use it. Do not know if your searched at the forum but maybe this post can bring you some useful information.

Regards :slight_smile:

Thanks for the response! I took a look at it and looks like a start. Wonder if those hardware changes on the board are necessary or if could you get around it without modifying it. What boards have you had success with when using the simple FOC library?

1 Like

STM32-based development boards (Blue Pill, STM32F405RGT6, STM32F407VGT6). I never used your board, but it is not a “exotic” board and surely someone else will be able to help you :slight_smile:

1 Like

Hi and welcome DGAQ!

I have gotten 2 out of 3 of my storm boards working. It’s good you have the v1.32 version, I didn’t have much luck with v1.31.

If you want to use the AS5048A’s SPI, you will have to modify the board as described, soldering a line to one of the LEDs. If you are happy to use the PWM signal of the encoder (a bit less accurate), you should be able to use the board without hacking it. I’ve only tried the SPI, but PWM should work.

IIRC the Storm32 has an STM32F103, like the BlueBill. You can use the “Generic F1” support in PlatformIO. I will go to my workshop PC later and check my platformio.ini for you.

To program it, you will probably need to use a STLinkV2 on the SWD lines. I don’t think it can program via USB, at least I never got it to work.
One of the boards I had would not program until I removed the “write lock” using STM32CubeProgrammer.

SimpleFOC can be run on a huge number of MCUs, including most STM32 MCUs, SAMD21/51 (like Arduino MKR boards), ESP32 boards, RP2040 boards (Rasperry Pico) and of course the venerable ATMega like the Arduino UNO and Nano.

In terms of motor drivers, there are a few options, see:
More boards are being made every week it seems, and you can search for “SimpleFOC” on AliExpress if you’re feeling adventurous :smiley:

What’s your application if you don’t mind me asking? If you tell us a bit about what you are doing, people might have some good suggestions for you…

1 Like

Here’s my PlatformIO.ini:

platform = ststm32
board = genericSTM32F103RC
framework = arduino
build_flags =
  -D USBD_VID=0x0483
  -D USBD_PID=0x5740
  -D USB_PRODUCT="\"Storm32_SPM\""

And here some code that intializes stuff:

#include "Arduino.h"
#include "Wire.h"
#include "SPI.h"
#include "SimpleFOC.h"

#define V_PSU 10
#define V_LIMIT 10
#define V_INIT_LIMIT 10

MagneticSensorSPIConfig_s AS5048 = {
  .spi_mode = SPI_MODE1,
  .clock_speed = 1000000,
  .bit_resolution = 14,
  .angle_register = 0x3FFF,
  .data_start_bit = 13,
  .command_rw_bit = 14,
  .command_parity_bit = 15

// Note: Storm32 SPI2 is PB13 == LED1 == CLK, PB14 == AUX0 == MISO, PB15 == AUX1 == MOSI
// Solder CLK line to PB13, which can be found on the 2k2 resistor R7 (see schematic) in the LED1 path

// top ring motor
#define SENSOR1_CS PC2 // POT2     //PA15  // AUX2
MagneticSensorSPI sensor1 = MagneticSensorSPI(AS5048, SENSOR1_CS);
BLDCMotor motor1 = BLDCMotor(7);
BLDCDriver3PWM driver1 =  BLDCDriver3PWM(PB1, PB0, PA7);

// middle ring motor
#define SENSOR2_CS PC1 // POT1         // PC9	// RC2-2
MagneticSensorSPI sensor2 = MagneticSensorSPI(AS5048, SENSOR2_CS);
BLDCMotor motor2 = BLDCMotor(7);
BLDCDriver3PWM driver2 =  BLDCDriver3PWM(PA6, PA3, PA2);

// bottom ring motor
#define SENSOR3_CS PC0 // POT0        // PC8	// RC2-1
MagneticSensorSPI sensor3 = MagneticSensorSPI(AS5048, SENSOR3_CS);
BLDCMotor motor3 = BLDCMotor(7);
BLDCDriver3PWM driver3 =  BLDCDriver3PWM(PB9, PA1, PB8);
Commander command = Commander(Serial);

float target1, target2, target3;

void initMotors() {

	digitalWrite(SENSOR1_CS, 1);

	digitalWrite(SENSOR2_CS, 1);

	digitalWrite(SENSOR3_CS, 1);

	driver1.voltage_limit = V_LIMIT;
	driver1.voltage_power_supply = V_PSU;

	driver2.voltage_limit = V_LIMIT;
	driver2.voltage_power_supply = V_PSU;

	driver3.voltage_limit = V_LIMIT;
	driver3.voltage_power_supply = V_PSU;

	motor1.voltage_limit = motor2.voltage_limit = motor3.voltage_limit = V_LIMIT;
	motor1.voltage_sensor_align = motor2.voltage_sensor_align = motor3.voltage_sensor_align = V_INIT_LIMIT;
	motor1.controller = motor2.controller = motor3.controller = MotionControlType::angle;
	motor1.PID_velocity.P = motor2.PID_velocity.P = motor3.PID_velocity.P = 0.1;
	motor1.PID_velocity.I = motor2.PID_velocity.I = motor3.PID_velocity.I = 20;
	motor1.PID_velocity.D = motor2.PID_velocity.D = motor3.PID_velocity.D = 0;
	motor1.PID_velocity.output_ramp = motor2.PID_velocity.output_ramp = motor3.PID_velocity.output_ramp = 1000;
	motor1.LPF_velocity.Tf = motor2.LPF_velocity.Tf = motor3.LPF_velocity.Tf = 0.01;
	motor1.P_angle.P = motor2.P_angle.P = motor3.P_angle.P = 20;

	// TODO store motor initialization params and only re-init if we can't load them (and provide a command to reset them)

	motor1.sensor_offset = motor1.shaftAngle();
	motor2.sensor_offset = motor2.shaftAngle();
	motor3.sensor_offset = motor3.shaftAngle();
	target1 = target2 = target3 = 0.0;


void setup() {
	pinMode(PB12, OUTPUT);
	digitalWrite(PB12, 1); // switch on lED for initialization

	while (!Serial);


	Serial.println("SPM motor initialization...");
	Serial.println("SPM motor initialization complete.");
1 Like

And finally, if you do use SPI, until we fix a bug regarding the MagneticSensorSPI for STM32, please also take a look at this thread:

So, all in all it’s not the simplest board to get working with SPI sensors :slight_smile:

1 Like

Awesome, good to know if I hit a wall can cant figure it out might try some of the development boards you recommended!

First off, thank you for the very in depth responses! I appreciate you taking the time to do so.

A few rookie questions since this is all new to me. When you say the encoders SPI what does SPI mean?? Haven’t heard of that before. I was planning on using the PWM just to get started initially but if I need more accuracy down the line I will probably switch to that. For the PWM control do I just hook my signal line from the encoder to the RC2 pins on the Storm32?


Also, I was testing the encoder on an Arduino to see what kind of values they outputted but was running it on 5v but I did read that the Storm32 runs on 3.3v. If I power the encoder with 5v and run the signal to the Storm32 will this cause issues?

I was reading around and saw that some boards had “write lock” and how can I tell if mine has that on and need to remove it? Also, do I need to flash it with a bootloader (stm32duino) similar to the method in the post that JorgeMaker pointed out to me?

Originally I was looking into just using motor drivers without the built in STM32 but decided for my application it would be nicer to have an all in one board.

As for my application this was mainly intended to be a learning experience on using BLDC motors (because of how smooth they run) and FOC because of the constant torque at low speeds. I am planning on building a gimbal like camera system similar to this:


(Obviously not trying to build the exact thing but mainly replicating how it can rotate 360 in on axis and 180 in the other to be able to see all around it). Like I said more of a learning experience but will build on it as I go on and will want to do another project using some control systems eventually.

SPI = Serial Peripheral Interface


It is a 4-wire protocol [MISO, MOSI, SS, SCK] that is used to communicate µControllers such as SMT32 with chips that perform specific functions. Suchs chips act as external peripherals in slave mode. In this case, the magnetic encoder is in charge of carrying out the angle measurement and communication with the µController is done using the SPI protocol.

There are many with different characteristics, pros and cons. If you are going to choose to use one, I recommend that you always choose one that, apart from SPI, also has PWM output as it facilitates debugging the hardware by knowing if it works independently of the SPI interface. The following link is an example of the many there are:

Make sure each input pint to your µController do not exceed 3.3V … some pins are 5v tolerant but if is not the case you can damage your µController.

For SPI protocol can you multiple devices to the same 4 lines? I am trying to use 2 encoders for the job.

In case you have more than one device connected to the SPI bus, you need a dedicated SS / CS line to each device that is the device selected for a particular transaction, this is how the SCLK, MOSI and MISO lines are shared without conflicts between slaves.

For example you can have 2 magnetic encoders attached to MISO, MOSI and SCLK and one dedicated SS line for each encoder.

1 Like

I will try this out once I get things running! Appreciate the help.

1 Like

SPI requires some hardware desoldering on these boards.

You can use rc ports or pot0, pot1 and pot2 ports

When coding the board what are the pin values called in the program?

Hey, I strongly recommend using the pin-names like PA2, PB12 etc… it will be much easier than trying to use Arduino pin numbers.

pot0, pot1 and pot2 are pins PC0, PC1, PC2 according to the schematic I have. It’s worth checking these things though, a simple test-program where you set the pin to ON with digitalWrite(PC0, HIGH) and then check with your multimeter will do the trick.

1 Like

Download the software “STM32CubeProgrammer” from ST-Micro. It will let you check and remove the write-lock (in the “OB” tab), and you can also use it to flash a new boot-loader. Really that probably won’t be necessary though, if you can program it via SWD (STLink) and see the serial output on the USB cable then you’re done and probably don’t need to bother with a new boot loader.

1 Like

Hey runger! Really appreciate your help. Got an STlink in the other day and I am now able to upload programs to the board.

Regarding this, where did you find the schematic with all the pin names? Like, are the pin names on the schematic the same ones you would read from in the code? ex: Pot-0 pin on the schematic is POT0 in the code?

To clarify the question above I see the the POT-0 pin an POT-1 pins are PC0 and PC1 respectively. Is there a document that I can reference to find the rest of the pin names or is there another method?

@DGAQ, check out this thread that has a schematic with pin names for storm32

1 Like