B-G431B-ESC1: Beginner guide + I2C guide

Hi @Lukas_Pfitscher ,

I’m not sure what you’re exactly doing, but be careful!

How thick are your wires? Was it the board that was smoking? Could you have a short-circuit somewhere?

1 Like

You literally short circuited your mosfets through the arduino board, if I understand correctly what you did. It’s really difficult to understand or debug without some schematics or a picture of the setup.

Please don’t get hurt and use eye protection and gloves. The chips when over-stressed will explode and the hot ceramic epoxy will get into your eyes. Bad way to lose an eye.


1 Like

I used thick 16AWG wires, they don’t get hot. My setup is a simple: power supply, ESC, motor (300kv big drone motor)

If i directly short the motor with my power supply it will pull 10A and the voltage will drop to 2V. Motor can handle it for some time (20s before getting hot). But i somehow figured it out: I measured the phase resistance wrong (its 2V/10A = 0.2Ohm). So somehow the ESC would not let me pull more than 2A, or it has some under voltage protection… i don’t know really…

But one problem still remains open why my ESC burned with analog write 50 to pin PC13, and PA12 set to High and motor connected. And it was the chip itself. the mosfets were not warm. It took just a sec

Man, that’s a bummer! We’d have to check bu aren’t those pins both low-side ones? Did you set the state of all the other pins for the driver?

1 Like

From looking at the schematics, I can’t see how this could kill anything but the MOS FETs. The gate driver chip should even prevent you from enabling high and low side FETs simultanously and the CPU should be completely decoupled from that. Killing the MOS FETs is easy however, I noticed that already…

1 Like

Did today again some testing, connected 2 phases to a power resistor (8 Ohm). Supply voltage is 20 V, sou current could not exceed 2,5 Amps. But again when i open the MOSFET the board gets instantaneously really hot (the resistor not even a bit). My code is below. I also tested the circuit with a single MOSFET (IRF3205) and the MOSFET stayed cool and the resistor got hot how it should be.

The board consumes about 1.2 watts and gets a bit warm on standby. I think its around the voltage regulator so maybe its normal.

#include <Arduino.h>
void setup() {
pinMode(PC13,OUTPUT);digitalWrite(PC13, LOW);
pinMode( PA8,OUTPUT);digitalWrite( PA8, LOW);
pinMode(PA12,OUTPUT);digitalWrite(PA12, LOW);
pinMode( PA9,OUTPUT);digitalWrite( PA9, LOW);
pinMode(PB15,OUTPUT);digitalWrite(PB15, LOW);
pinMode(PA10,OUTPUT);digitalWrite(PB10, LOW);

digitalWrite( PA8, HIGH); //1PhaseH
digitalWrite(PA12, HIGH); //2PhaseL
digitalWrite( PA8, LOW); //1PhaseH
digitalWrite(PA12, LOW); //2PhaseL
void loop() {}

So keep in mind this is supposed to be a drone ESC, so in tis intended use-case it is always subject to forced air cooling just by the drone’s flight and propeller wind… When using it a “stationary” scenario, you should really put a heat-sink on it…

performance RC-Car ESCs typically have heat-sinks and little fans for cooling.


First of all, thanks a lot for the tremendous help offered in this forum, it got me started really fast!

Since my experience with power electronics is close to zero and my application is stressing the board pretty much as far as the heat dissipation goes, I have some questions to the experienced experts here. I use the B-G431 board together with a ACT-BLF01 motor, planning to go for a stronger motor (BLF03) pretty soon. The current motor has 2 Ohms, is rated at 24V and 5.7A max. In most cases, heat is not an issue and the current actually used is pretty low (overall power consumption is <10W). There are cases however, when I need to issue a much higher torque for a few seconds, in which case the MOS FETS heat up quickly. I use the onboard NTC to detect overheating and switch of the drivers if it gets too hot. I already attached tiny heatsinks to the MOS FETS and a small 35mm fan is already ordered.

Now the questions:

  1. Since the NTC is sitting next to the MOS FETS and not measuring the junction temperature, at which measured temperatur would you switch off? I want to be on the safe side, the board is cheap, but getting harder to order…

  2. The motor is rated at 24V, but I used it at 12V only so far. How would going up to 24V affect the heat dissipation?

  3. Up to which continous current would you trust the board equipped with the tiny heatsinks and a small fan?

Thanks a lot for any help!

  • Chris

I am trying to run the B-G431-ESC1 board with Arduino IDE 1.8.10. But the project is not going. Gives errors. What could be the problem?

C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp: In function 'int findIndexOfFirstPinMapEntry(int)':
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp:409:10: error: 'PinMap_TIM' was not declared in this scope; did you mean 'PinMap_PWM'?
  409 |   while (PinMap_TIM[i].pin!=NC) {
      |          ^~~~~~~~~~
      |          PinMap_PWM
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp: In function 'int findIndexOfLastPinMapEntry(int)':
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp:421:10: error: 'PinMap_TIM' was not declared in this scope; did you mean 'PinMap_PWM'?
  421 |   while (PinMap_TIM[i].pin!=NC) {
      |          ^~~~~~~~~~
      |          PinMap_PWM
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp:422:45: error: 'ALTX_MASK' was not declared in this scope
  422 |     if (   pinName == (PinMap_TIM[i].pin & ~ALTX_MASK)
      |                                             ^~~~~~~~~
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp: In function 'int findBestTimerCombination(int, int, int*, PinMap**)':
C:\Users\Alexey\OneDrive\���������\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\stm32_mcu.cpp:449:36: error: 'PinMap_TIM' was not declared in this scope; did you mean 'PinMap_PWM'?
  449 |     searchArray[index] = (PinMap*)&PinMap_TIM[i];
      |                                    ^~~~~~~~~~
      |                                    PinMap_PWM

Are you using the arduinostm32 framework?

These includes are defined in framework-arduinostm32/cores/arduino/stm32/PinNames.h. There must be something wrong with your IDE setup.

1 Like

Thanks for the answer. The problem was indeed in the Arduino IDE. I removed the IDE, as well as installed libraries and boards, reinstalled and everything worked.

Work in progress, but what do you mean “no SPI support”? :wink:

1 Like

They don’t call them Micro-Electronics for no reason, that’s some snug soldering!

Looking forward to what you find out (hopefully it doesn’t knock out the temp sensor or anything)

I’ve got SPI3 wired up, minus MOSI (which is otherwise occupied). The pins I used were the button and CAN disable (PC10+11) which are SPI3 CS and MISO, with the PWM input pin as CS, as well as 3.3V and gnd. The AS5047 can run in unidirectional mode (MISO only), but so far the Arduino core’s SPI implementation is hanging on clocking out the SPI data (possibly since it isn’t configured for unidirectional SPI). The other possibility is that the button’s de-bounce or pull-up passives are mucking with SCK, but I’ll dive into that tonight (or whenever I get back to this) with an oscilloscope and logic analyzer to double check the IOs, and then probably a direct stm32 LL SPI function to get to the bottom of things.

You have amazing soldering skills! What you did there requires far more than just good tools. You should channge your nickname to something like GodOfSoldering.

1 Like

Time will tell if it was enough. I do have to recommend watching youtube videos on PCB trace repair (they do some truly crazy stuff), and making frequent use of IPA wash, dry, flux, do one thing, then repeat. Getting the two tiny leads tinned and soldered took a half dozen tries, and 2-3 bridges and repairs. My setup is better than most amateurs, but not super expensive ($50 hakko soldering station, $30 USB microscope, a $2 14x14" ceramic floor tile, a variety of very cheap soldering tips, and most importantly a lot of patience and creative hand bracing since at this scale even the steadiest hands are too shaky). Dollar store clear epoxy as well, instead of proper UV cure solder mask. Don’t tell the actual electrical people at my work :wink:

OK… SPI guide (not very beginner friendly :confused: )

Step 1: Finding free SPI

The stm32g431cb has 3 SPI ports (spi1/2/3).

I wanted to see if it was possible to expose one of them to hook up an as5047 SPI encoder.

What do we need? Well, as per some versions of its data sheet, the as5047 can run in two modes:

  • Bidirectional mode (The one implemented in MagneticSensorSPI), using MOSI to set the register it’s reading, then MISO the read the value
  • Unidirectional mode, when is enabled by tying MISO to VCC (3.3V in this case)

This means that in theory, all we need from the SPI port is SCK, and MISO. The CS pin can be done manually using any old GPIO, and MOSI in theory isn’t needed at all in this unidirectional mode.

Focusing first just on MISO and SCK in the stm32g431cb datasheet, and crossreferencing the pin allocation in um2516 (the B-G431B-ESC1 user manual):

  • SPI1_SCK is PB3 (USART2_TX, so maybe) or PA5 (Curr_fdbk2_OPAmp-, so nope)
  • SPI1_MISO is PA6 (OP2_OUT, nope), PB4 (USART2_RX, so maybe)
  • SPI2_SCK is PB13 (NC, so that’s tough) or PF1 (OSC 8Mhz, nope), PF2 (not a pin in this package) PF9 (not a pin in this package)
  • SPI2_MISO is PA10 (TIM1_CH3), PB14 (Temperature feedback)
  • SPI3_SCK is PB3 (USART2_TX, so maybe) or PC10 (BUTTON… bingo!)
  • SPI3_MISO is PB4 (USART2_RX, so maybe), PC11 (CAN_SHDN,TP2)

I face the choice: Sacrifice CAN+the button, which I’m not planning on using (by repurposing CAN_SHDN and the button input) for SPI3, or get rid of USART2, which I was planning on using for debugging unlocking either SPI1 or 3.

I decided that SPI3 via PC10/11 was the best choice.

Step 2: Soldering the B-G431B-ESC1 SPI wires

I loaded the board files from ST’s website onto the free Online PCB Viewer to Visualize and Share Electronics Design Projects | Altium 365 Viewer to look through the traces.

PC11 (our new SPI_MISO) is exposed on the bottom layer here (in dark blue):

The test point pad is the easiest target.

This brings us to our problem pin, PC10.

It’s only exposed in dark blue for a short little trace on the bottom layer, then it hides in the middle layers and wanders off the board. I could have tried just soldering to the side of the stlink board button (in red), but I plan to remove the STLink board at some point along this project, so I needed to try to solder to the bottom layer.

This is where things got dicey.

I used needle point tweezers to gently scrape the solder mask off above the via (viewing through a cheap USB microscope), then used (IPA scrub->flux->reapply solder) more or less in a loop 5-6 times until it worked and had a decent tin coating on both the TP2 pad, and the revealed via beside it, without any solder bridges.

Once things were tinned, applied pre-tinned the yellow 28 gauge wire to the test point (PA10), and the copper 38 gauge enameled wire to the tinned via. I then tested continuity with my multimeter (and microscope) to verify things seemed OK, and then coated the connections with a bit of clear epoxy.

Once the epoxy cured, I cut the magnet wire down to ~1cm, stripped it a bit, and soldered blue 28 gauge wire to it. I then heat-shrunk the blue and yellow wires together to provide strain relief.,



The top side is much simpler:

We now have all 5 wires needed for unidirectional SPI!

Step 3. Wiring up the AS5047

Back to nice 0.1" pitch stuff!

I wanted to run everything on 3.3V, which meant jumping the 5V and 3V3 pins in JP1 (why are there pre-populated headers on the wrong side!), so desoldered the headers with ceramic tweezers that made pulling the pins out super easy without wicking heat from them, and then re-soldered a bit of one of the pins as a jumper.

R1 needed to be moved to R2 as part of 3.3V mode (not sure why they have jumpers if you need to resolder resistors too…)

3V3 needed a jumper wire to MOSI to enable unidirectional mode on the AS5047 (red wire)

Step 4. Arduino Core Changes

You need to update C:\Users\ your_username \.platformio\packages\framework-arduinoststm32\variants\STM32G4xx\G431C(6-8-B)U_G441CBU\PeripheralPins_B_G431B_ESC1.c (or equivalent arduino location):

Step 5. PlatformIO Config

Only HAL_SPI_MODULE_ENABLED is super important here, but I’m including it all for completeness.

platform = ststm32
board = disco_b_g431b_esc1
framework = arduino
monitor_speed = 115200
build_flags =
lib_archive = false
    askuric/Simple FOC @ ^2.0.2
Step 6. SPI Tribulations

At first, I hoped that MagneticSensorSPI would just work, and defined the normal arduino SPI3 definition, passing in parameters. I had toggled all the pins I wanted to use with digitalWrite, so I knew the wiring was correct, but this just didn’t work. It would hang waiting on an output buffer flag.

I ended up trying both the stm32 LL api, and the HAL, and getting it to work eventually with HAL.

It turns out that unidirectional mode flags and SPI_DIRECTION_2LINES_RXONLY are actually just a trap (the SPI clock just runs continuously and this causes the read to essentially give you your bytes with a random offset, or crashes the SPI device in some case. I’d call that a silicone bug, but… that’s just my opinion. Undesired bonus functionality maybe.

As a result, a lot of time was wasted between the default configuration hanging the processor and the most logical configuration producing garbage data.

In the end, simply telling the device to operate in bidirectional mode (which “lets” the SCK pin toggle as expected), with a stripped down HAL based SPI init+read seems to work fine.

Step 7. Working Code
#include <Arduino.h>
#include <SPI.h>
#include "pinconfig.h"
#include <SimpleFOC.h>

// Bringing online unidirectional SPI for AS5047 encoder
// 3.3V from the SWD pads
#define AS5047_SS PA15  // PWM pin, used as SPI CS pin, exposed on the pad 2nd from the VDC+ pad
#define PIN_SPI_MISO PC11  // CAN shdn isn't needed, SPI3_MISO. Exposed on TP2 pad by the STM32G micro silkscreen
#define PIN_SPI_SCK PC10   // the button, SPI3_SCK
#define PIN_SPI_MOSI NC  // No MOSI

// Todo: Add unidirectional mode support?
//MagneticSensorSPI sensor = MagneticSensorSPI(AS5047_SS, 14, 0x3FFF);

SPI_HandleTypeDef spi3_handle;
SPI_TypeDef *spi3;
void init_spi3(){
  // the following is mostly just a stripped down version of spi_com.c's spi_init
  spi3 = (SPI_TypeDef*)SPI3;
  spi3_handle.State = HAL_SPI_STATE_RESET;

    // 170Mhz / 16 ~= 10.625Mhz, which seems to work OK, despite being over 10
  spi3_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;

  // no SSEL defined in the HAL
  spi3_handle.Init.NSS = SPI_NSS_SOFT;

  spi3_handle.Instance               = spi3;
  spi3_handle.Init.Mode              = SPI_MODE_MASTER;
  spi3_handle.Init.Direction         = SPI_DIRECTION_2LINES;  // we're only actually using one

  // SPI mode 1
  spi3_handle.Init.CLKPhase          = SPI_PHASE_2EDGE;
  spi3_handle.Init.CLKPolarity       = SPI_POLARITY_LOW;
  // more settings
  spi3_handle.Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
  spi3_handle.Init.CRCPolynomial     = 7;
  spi3_handle.Init.DataSize          = SPI_DATASIZE_16BIT;
  spi3_handle.Init.FirstBit          = SPI_FIRSTBIT_MSB;
  spi3_handle.Init.TIMode            = SPI_TIMODE_DISABLE;
  spi3_handle.Init.NSSPMode          = SPI_NSS_PULSE_DISABLE;

  // init pins
  pinmap_pinout(digitalPinToPinName(PIN_SPI_MISO), PinMap_SPI_MISO);
  pinmap_pinout(digitalPinToPinName(PIN_SPI_SCK), PinMap_SPI_SCLK);
  // from arduino spi_com.c
  uint32_t pull = (spi3_handle.Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
  pin_PullConfig(get_GPIO_Port(STM_PORT(digitalPinToPinName(PIN_SPI_SCK))), STM_LL_GPIO_PIN(digitalPinToPinName(PIN_SPI_SCK)), pull);

  // enable SPI clock

  // init HAL peripheral

void setup() {
  pinMode(AS5047_SS, OUTPUT);
  digitalWrite(AS5047_SS, HIGH);
  pinMode(AS5047_SS, OUTPUT);

  // init magnetic sensor   
  Serial2.println("Init Done");


uint16_t read_as5047() {

  digitalWrite(AS5047_SS, LOW); // SS low
  uint16_t value = 0;
  HAL_SPI_Receive(&spi3_handle, (uint8_t *)&value, 2, 1000);
  digitalWrite(AS5047_SS, HIGH);  // SS high

  // trim the extra 2 bits off the 14 bit value
	value = ( value ) & (0xFFFF >> 2);  // Return the data, stripping the non data (e.g parity) bits
  return value;

void loop() {
  digitalWrite(LED_BUILTIN, millis()%2000>1000);



  • Submit the SPI pin line change to the arduinostm32 repo.
  • Solder up the power and phase leads and see if the ESC functionality still works!



  • I’d strongly urge anyone considering doing this to look into just using the USART2_TX+USART2_RX (PB3/4) pins to do the same thing I did here. They’re broken out on that nice 0.1" pin header along with PWM which you can still use as CS. This does create a bit of a headache controlling the device, but CAN and SWD are still available, as well as maybe repurposing H1+H2 as USART1_TX/RX.
  • ST, if you ever find your way to this post, just break out all the IOs on your dev boards!
  • Chip Quick No clean flux in a syringe, and a $30-50 microscope if you don’t have them. There’s absolutely no reason why reworking 0402 components shouldn’t be easy! This is a more extreme example but with the right tools, you just need patience.
  • Just try things! That via is 0.2-0.25mm diameter, and the trace is thinner. I’m glad I didn’t check before trying or I’d have said it couldn’t be done.

The SPI data was super noisy, which went away with a tweak (changing 8 bit to 16 bit SPI mode). I think something funky was going on between the two 8 bit halves, which is now gone. I also set the clock the DIV_16, which provides 10.64Mhz, vrs 128, which was 1.33Mhz.

chart (10)
(spinning m motor unevenly by hand)

Update 2:
The sensor now is wrapped in a SimpleFOC Sensor class. Something might still be a bit fragile about the SPI code. Calling the angle read back to back seems to crash the CPU.
The project repo is now on github here:


Hey @Magneon,

thanks a lot for your most valuable input! I implemented it as well, but as you were sugesting, using SPI3 on PB3/4, which is definitely much easier than using the pins you are using. I also managed to use USART1 now for debugging purposes. The hardest part was finding out how to modify the software and I haven’t found a really nice way yet, but ok, it works. As far as SPI goes, I attached an AS5147 to it, used your code, enabled SPI3 on the alternate pins in variant_B_G431B_ESC1.h and I recieve “something”, which changes as I turn the motor shaft. The problem is that the position jumps back a lot when I turn the shaft (like a reset every few rad). Do you (or anybody) else have any ideas, what could be wrong? I reduced the baudrate already, but it did not help either. Also, is there documentation on using the sensor in SSI mode somewhere available? I could not find any.

For all others that might be interested, here the changes I implemented:

A) Disconnect USART2 and connect USART1
1. Remove R23 and R24 (on the daughter board, easiest to cut them in the middle and then desolder)

B) Connect USART1 if you intend to use the serial port 1:
1. Solder thin wires to the now free pins of R23/24 (the pads closer to U3, further away from the USB port)
2. Secure the wires with some hot glue.
3. Connect the wire from R23 to the pad for hall sensor 2.
4. Connect the wire from R24 to the pad for hall sensor 1.

C) Fixes required in arduino-STM32 (only if you intend to use the serial port 1)
1. In file  …..\variants\STM32G4xx\G431C(6-8-B)U_G441CBU\variant_B_G431B_ESC1.h, change line 205ff:

#define SERIAL_UART_INSTANCE    1 //Connected to ST-Link
// Default pin used for 'Serial' instance (ex: ST-Link)
// Mandatory for Firmata
  #define PIN_SERIAL_RX         PB7   // PB4
  #define PIN_SERIAL_TX         PB6   // PB3

Save this explicitly!!!  NOTE: You will need to revert this change if you want to use USART2 again for debugging!

2. In ……\variants\STM32G4xx\G431C(6-8-B)U_G441CBU\PeripheralPins_B_G431B_ESC1.c  enable line 188 and 205.

Line 181ff:
WEAK const PinMap PinMap_UART_TX[] = {
  //  {NC,        NP,      0}

WEAK const PinMap PinMap_UART_RX[] = {
  {NC,        NP,      0}

Save this explicitly!!! -> Make sure you are not using HALL_1 or HALL_2 for sensors etc. in your code anymore now!

Best regards,

Good news, I have a full fledged SPI3 running on the B-G431B-ESC1 board. It takes away the ability to perform BEMF measurement, but that’s not supported by SimpleFOC anyway. Also, you cannot attach hall sensors anymore, but at least I don’t need them if I have the SPI interface now. I tested with an AS5147 sensor on a broken board only (unfortunately I have a few of them…) so far, but I see no reason, why it should not work on a functional board too, however, that’s yet to be proven. Here is how it works:

Follow the instructions from the previous posts to use SPI3 in SSI mode. Next, you need to solder a wire connecting the BEMF sensing pin of the CPU to your sensor’s MOSI pin. I attached it to the cathode of D15. It is a very small pad to solder, but well accessible at the edge of the board. I first fixed the wire with some hot glue near the pad and then soldered it under a microscope (my hands are everything but steady). It took me some attempts, but worked.

In the code you will have to enable the pin as SPI_MOSI in …\variants\STM32G4xx\G431C(6-8-B)U_G441CBU\PeripheralPins_B_G431B_ESC1.c.In my case it looks like this (starting round line 240):

WEAK const PinMap PinMap_SPI_MOSI[] = {
  {NC,        NP,   0}

Note that I copied the PB_5_ALT1 line and renamed the pin to PB_5, since otherwise I ran into problems.

Now we still have the issue, that the BEMF sensing circuitry is still attached to PB5. This should not matter, if you pull all the BEMF control outputs low, before using SPI somewhere in your code:

  // BEMF outputs
  pinMode(A_BEMF1, OUTPUT);
  pinMode(PB0, OUTPUT);
  pinMode(A_BEMF3, OUTPUT);
  digitalWrite(A_BEMF1, LOW);
  digitalWrite(PB0, LOW);
  digitalWrite(A_BEMF3, LOW);

That’s it! All together well doable. Tomorow I’ll try with my last fully functioning board and a motor attached.



Ok, SPI is running on a functional board with motor attached as well. I tested it with the alignment_and_cogging_test example. No extensive testing so far, but looks ok.