cancel
Showing results for 
Search instead for 
Did you mean: 

6-step commutation with hall-effect sensors not updating PWM in v6.4.1

jovijuan
Associate III

I was testing a BLDC motor with Hall-effect sensors at very low speed. This worked ok with v6.3.2, but with v6.4.1, if the speed reference is low, the motor don't even start.

If I manually move the motor, sometimes it starts and sometimes it throws an overcurrent error.

It looks like the PID is integrating, but not actual PWM's are being sent to the motor.

I checked that, when movement starts, HALL_ReadState (called via multiple functions from TSK_MediumFrequencyTaskM1 when State is CHARGE_BOOT_CAP) sets pHandle->SensorIsReliable = false because the hall state was the same as previous call to ReadState so I modified ReadState so that, when the state is the same as before, it was not labeled as unreliable, but motor still doesn't start.

I'm going to dig deeper on it. 

3 REPLIES 3
jovijuan
Associate III

Ok, it was quick. It looks like the bridge PWM is only updated on movement start and, later, on Hall-effect sensor commutations. So if initial duty cycle is low, the motor never starts unless it is manually moved.

But this is wrong even at higher speeds, as duty cycle calculated in control loop is not updated into PWM until the next Hall-sensor state change.

This is actual code for State == RUN inside TSK_MediumFrequencyTaskM1() in mc_tasks_sixstep.c file:

        case RUN:
        {
          if (MCI_STOP == Mci[M1].DirectCommand)
          {
            TSK_MF_StopProcessing(M1);
          }
          else
          {
            /* USER CODE BEGIN MediumFrequencyTask M1 2 */

            /* USER CODE END MediumFrequencyTask M1 2 */

            MCI_ExecBufferedCommands(&Mci[M1]); /* Exec the speed ramp after changing of the speed sensor */
            SixStepVars[M1].DutyCycleRef = SDC_CalcSpeedReference(pSDC[M1]);

            if(!IsSpeedReliable)
            {
              MCI_FaultProcessing(&Mci[M1], MC_SPEED_FDBK, 0);
            }
            else
            {
              /* Nothing to do */
            }
          }
          break;
        }

 

 

If I just add:

PWMC_SetPhaseVoltage(pwmcHandle[M1], SixStepVars[M1].DutyCycleRef);

right under the line where DutyCycleRef was calculated, the motor starts correctly.

I'm not sure if this is the best way to fix it, though.

It still bothers me that, when the motor is completely stopped, the reported speed is still 30 rpm.

Hi @jovijuan first, I apologize for the delay.

One significant difference between the 6-step implementation of the MCSDK 6.3.2 and 6.4.1 is the removal of the high-frequency task SIX_STEP_HighFrequencyTask in the latest implementation. As mentioned, with MCSDK 6.4.1, the PWM update is performed only at each new HALL interruption. In the previous implementation, this task was handled by the high-frequency task, which executed the job multiple times per HALL interruption and was particularly useful for starting at very low speeds. One solution, as pointed out, is to use the TSK_MediumFrequencyTaskM1 for this purpose, which performs the job at each 1 ms tick.

Regarding the reported speed of 30 rpm, it should be just a MecSpeedUnit computation precision. In the HALL_CalcAvrgMecSpeedUnit function, at the end of the function, we just need to set this line of code:

if (pHandle->BufferFilled < pHandle->SpeedBufferSize)
{
MecSpeedUnit = (int16_t)(((int32_t)pHandle->_Super.speedConvFactor) / pHandle->SensorPeriod[pHandle->SpeedFIFOIdx]) ;
}
else
{
/* Average speed allow to smooth the mechanical sensors misalignement. */
MecSpeedUnit = (int16_t)((int32_t)pHandle->_Super.speedConvFactor /
(pHandle->ElPeriodSum / (int32_t)pHandle->SpeedBufferSize)); /* Average value. */
}
}

if( 0U == pHandle->BufferFilled) MecSpeedUnit = 0;

bReliability = SPD_IsMecSpeedReliable(&pHandle->_Super, MecSpeedUnit);
pHandle->_Super.hAvrMecSpeedUnit = MecSpeedUnit;
#ifdef NULL_PTR_CHECK_HALL_SPD_POS_FDB
}
#endif
return (bReliability);

 

 

Best regards.

Fabrice

Regarding the PWM update frequency, I think updating it inside TSK_MediumFrequencyTaskM1 is correct because it would be updated right after the control PID calculation. Updating PWM on Hall-effect sensors update makes control behavior dependent on motor speed.

Regarding the patch for the reported speed when motor is not moving:

  • That modification actually shows speed zero when not running
  • But as soon a the motor is not moved for 150ms (it can happen in a slow start or when reducing speed reference to a low value), the hall sensor is flagged as non reliable (because logic inside Hall_ReadState doesn't allow a hall sensor to stay non-moved or in the opposite direction of the requested movement) and it doesn't move anymore as no commutation happens.

I've been testing a solution where, in parallel with the array SensorPeriod[HALL_SPEED_FIFO_SIZE]; there is a similar one, int8_t SensorPosDelta[HALL_SPEED_FIFO_SIZE]; that gets values +1/0/-1 when the hall sensor changed forward, stayed, went backward. And the speed calculation would sum also the hall steps.

This way, negative movements are allowed and correctly computed even when reference is positive and viceversa.

The implementation is not very elegant, but it is trying to follow the handling of SensorPeriod array.

The diff file is included.