STM32 - ESC : Problem with my BEMF

Welcome to StackExchange! Well done first post.

You are correct, your forcing voltage is out of phase with your motor.

Looks to me like you are sampling in the incorrect location during your PWM cycle. Ensure that your ADC sample occurs at the center of the PWM cycle when the PWM cycle is high. There may be a minimum duty cycle required in order to get a proper sample, but that may not be the case as 900Hz is a pretty low frequency.

It is difficult to surmise from your scope screenshots, but it appears that the phase is negative going on the low side of your PWM and positive-going on the up-side of your PWM... so your code is likely doing exactly what you are telling it to do, but in the wrong place in the cycle.

I like to check my interrupt timing (roughly) by setting up a pin to turn on when the ADC interrupt starts and turn off when the ADC interrupt ends. I can usually gather good information from that.

If you verify/fix your ADC sample time, and the problem persists, then post a screenshot of one phase as it is rising, full-scale Y-axis.

Stick with it! Problems are solved by putting your head down and working at it. But remember to walk away and get some sleep. Problems look very different in the morning!


edited to add

Based on your comments, I am getting the sense that there may be some basic misunderstandings (I may be wrong).

Calculating Neutral Voltage

First off, you don't need to measure a neutral voltage. This is a wasted ADC module. You can calculate your neutral voltage: neutral = (phaseA + phaseB + phaseC) / 3;. Recommend you convert that to a fixed-point notation for speed, but the math is correct. Now that is one less ADC that you require!

Your neutral looks pretty much correct. If you mentally do the math that I just described, you will see that the neutral voltage is indeed the average (or very nearly) of the phase voltages.

Configure Registers to do the Work

Next, if you configure your TIM1 and ADC12 registers in center-aligned and triggered at the peak of counter mode, then no calculation is necessary to sample correctly.

When to Commutate

In your comment, you wrote

if the floating phase - the virtual ground = 0. If it's true, then I theoretically know the duration to wait before commutating the next phase to high

This is true only half the time and I just want to word it with clarity. Note that the BEMF phase is alternating between rising on one phase and falling on another.

if(phaseIsRising){
    if(phaseVoltage > neutral)
        commutate();
}else{
    if(phaseVoltage < neutral)
        commutate();
}

If you correctly implement the above code, you will be able to operate the motor, but 30 degrees advanced. Believe me, it will look much better than it does in your screenshots.

Further Work

If you get this far, I will leave it to you to determine how to shift the commutation event by 30 degrees.