Issue with PwmOut on L432KC

Hello! I’m trying to use PA1 as my PWM output. When I run the code, I have no problems until it reaches the ESC.CONTROL(A4956::Forward) on the second iteration of the while loop. At that point it runs the PWM at whatever I’ve set the brake function value to. I don’t understand why this would happen, I explicitly tell it in the class function to write a duty cycle of 100% before resuming the PWM, so why is the brake PWM value bleeding over anyway? Peculiarly, the following ESC.CONTROL(A956ESC::Reverse) works with the correct PWM value. I have put my scope on my PWM line to ensure that the PWM values correspond to my findings. Thanks for any help you can lend me!

#include "mbed.h"


class A4956ESC
{
public:

    enum Direction
    {
        Forward = 1,
        Reverse = 0
    };
    /** Constructor for A4956ESC class, set up pins
    * @param PH Phase control logic, digital out
    * @param MD Mode control Logic, digital out
    * @param EN PWM signal for A4956ESC
    * Data sheet at https://www.digikey.com/en/products/detail/allegro-microsystems/A4956GESTR-T/5809983?s=N4IgTCBcDaIIYBYCcBWAbAcwKYGcAuATgLR4gC6AvkA
    */
    A4956ESC(PinName PH, PinName MD, PinName EN);

    /** Function used to set to reverse or forward 
    * @param dir enum used to determine which direction
    */
    void CONTROL(Direction dir);

    /** Function Used to brake ESC
    * @param PWM pwm pulse value used for braking
    */
    void BRAKE(int PWM);

    /** Function Used for Fast Decay mode
    * @param dir enum used to determine which direction
    * @param PWM pwm pulse in microseconds value used for chop mode
    */
    void EN_CHOP(Direction dir, int PWM);

    void STOP(void);

private:
    PwmOut Enable;
    DigitalOut Phase, Mode;

};
#include "mbed.h"
#include "A4956ESC.h"

A4956ESC::A4956ESC(PinName PH, PinName MD, PinName EN) : Phase(PH), Mode(MD), Enable(EN)
{
    //initalize digital values and pwm
    Enable.period_us(2000);
    Enable.write(1.0f);
    Enable.suspend();
    Phase = 0;
    Mode = 0;

}

void A4956ESC::CONTROL(Direction dir)
{  
    int temp;
    switch (dir) 
    {
        case Forward:
        Enable.write(1.0f);
        // temp = Enable.read_pulsewitdth_us();
        // printf("Pulsewidth in us :%d\n", temp);
        Phase = 1;
        Enable.resume();
        break;

        case Reverse:
        Enable.write(1.0f);
        Phase = 0;
        Enable.resume();
        break;

    }

    
}

void A4956ESC::BRAKE(int PWM)
{
    Mode = 1;
    Enable.write(PWM);
    Enable.resume();
}

void A4956ESC::EN_CHOP(Direction dir, int PWM)
{
    switch(dir)
    {
        case Forward:
        Mode = 0;
        Phase = 1;
        Enable.pulsewidth_us(PWM);
        Enable.resume();
        break;

        case Reverse:
        Mode = 0;
        Phase = 1;
        Enable.pulsewidth_us(PWM);
        Enable.resume();
        break;
    }
}

void A4956ESC::STOP(void)
{
    Enable.suspend();
    Enable.write(1.0f);
    Phase = 0;
    Mode = 0;
}
#include "mbed.h"
#include "KB_Functions.h"
#include "A4956ESC.h"
#include <chrono>
#include <cstdint>
#include <array>


static BufferedSerial           sbusIn(PA_9, PA_10, 100000);            //Buffered serial object for sbus input at baud = 100,000 
static BufferedSerial           pc(USBTX,USBRX,115200);                 

AnalogIn MotorCurrent_1(PA_0);
AnalogIn SupplyVoltage(PA_4);       //12.47V Equates to 0.56 in u16, 9.91V Equates to .5306
AnalogIn MotorCurrent_2(PA_5);

DigitalIn MicroSW_TOP(PB_1);          //UPPER MICROSWITCH
DigitalIn MicroSW_Bot(PA_12);         //LOWER MICROSWITCH
DigitalIn ProxSensor(PB_0);

PwmOut Buzzer(PA_11);
// PwmOut EN_ESC(PA_1);

DigitalOut  polarity_relay(PA_8);
DigitalOut  on_relay(PB_5);

// DigitalOut PH(PA_6);
// DigitalOut MODE(PB_3);

A4956ESC ESC(PA_6, PB_3, PA_1);

char TEST_ARRAY[1] = {0x00};
float voltage_data;

int main()
{
    I2C_GPIO.frequency(400000);
    if(I2C_GPIO.write(GPIO_IC11_ADDR, TEST_ARRAY, 1) == 0 && I2C_GPIO.write(EEPROM_ADDR, TEST_ARRAY, 1) == 0 && I2C_GPIO.write(GPIO_IC11_ADDR, TEST_ARRAY, 1) == 0)
    printf("I2C DEVICES CONNECTED\n");
    else printf("I2C DEVICES ERROR\n");
    MCP23008_Init_IC11();
    Buzzer.period_us(2000);
    Buzzer.write(0.5f);
    Buzzer.suspend();

    while (true) 
    {
        // Buzzer.resume();
        // wait_us(1000000);
        // Buzzer.suspend();
        wait_us(1000000);
        ESC.CONTROL(A4956ESC::Forward);
        wait_us(4000000);
        ESC.CONTROL(A4956ESC::Reverse);
        wait_us(4000000);
        ESC.BRAKE(0.0f);
        wait_us(4000000);
        ESC.STOP();



    }
}

Hello Parker,

The PwmOut related Mbed OS documentation says:

void suspend ( )

Suspend PWM operation.

Control the PWM state. This is primarily intended for temporary power-saving; This call can allow pwm to be temporarily disabled to permit power saving without losing device state. The subsequent function call must be PwmOut::resume for PWM to resume; any other calls prior to resuming are undefined behavior.

However, in the void A4956ESC::CONTROL method the PwmOut's write() method is called before calling resume(). Try to remove the call to the susspend() method from the A4956ESC's constructor and the calls to the resume() method from the CONTROL() method.

1 Like

Good Morning Zoltan,
Thanks so much, you saved me a lot of time. I removed the suspend portion and in its place just wrote 0 duty cycle when I wanted no PWM output. It works as intended now! Have a great day.