leo.blog();

McFly Cobothon

Joined a robotics hackathon with a coworker. 36 hours of embedded development. The end result was a BLDC motor controller.

Magnetic encoder to motor driver

This is some kind of half-step pattern to drive the motor efficiently.

Param 1Param 2In-WIn-VIn-UPWM1PWM2PWM3
110High
201Low
301Low
110High
210High
301Low
101Low
210High
301Low
101Low
210High
310High
101Low
201Low
310High
110High
201Low
310High

In our sleep-deprived state, we managed to turn it into this lookup-table based code.

static uint8_t EncoderHallState(void)
{
    // Read C6, C7, C8 as digital
    uint8_t c6 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_6);
    uint8_t c7 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7);
    uint8_t c8 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8);

    return (c6 << 2) | (c7 << 1) | c8;
}

bool motor_u_lookup[] = { false, false, true, true, true, false };
bool motor_v_lookup[] = { true, false, false, false, true, true };
bool motor_w_lookup[] = { true, true, true, false, false, false };

uint8_t motor_next_lookup[] = { 4, 5, 1, 3, 2, 6 };

static uint8_t ApplyControl(uint8_t enc, uint16_t pwm)
{
    uint8_t u_val = enc >> 2;
    uint8_t v_val = (enc >> 1) & 1;
    uint8_t w_val = enc & 1;

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, u_val ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, v_val ? GPIO_PIN_SET : GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, w_val ? GPIO_PIN_SET : GPIO_PIN_RESET);

    size_t j = pwm;

    TIM1->CCR1 = u_val ? 0 : j;
    TIM1->CCR2 = v_val ? 0 : j;
    TIM1->CCR3 = w_val ? 0 : j;
}

static void MoveNext(uint16_t pwm, bool backwards)
{
    uint8_t current = EncoderHallState();
    uint8_t i = 0;

    if (backwards)
    {
        for (size_t c = 0; c < 6; c++)
        {
            if (motor_next_lookup[c] == current)
            {
                i = (c + 5) % 6;
                break;
            }
        }
    }
    else
    {
        for (size_t c = 0; c < 6; c++)
        {
            if (motor_next_lookup[c] == current)
            {
                i = (c + 1) % 6;
                break;
            }
        }
    }

    uint8_t next = motor_next_lookup[i];
    ApplyControl(next, pwm);
}

Leave a Comment