Set PWM Timer

Discussions and support about ChibiOS/HAL, the MCU Hardware Abstraction Layer.
JSStabl
Posts: 78
Joined: Tue Feb 25, 2020 4:06 pm
Has thanked: 3 times
Been thanked: 2 times

Set PWM Timer

Postby JSStabl » Wed Feb 10, 2021 5:10 pm

Hello together,

I want to control a current by switching 4 MOSFETs and therefore use a soft-PWM.
PWM config:

Code: Select all

static PWMConfig pwmcfg = {
        (125000U),                                /* goal: 15,625kHz PWM */
        8U,                                       /* PWM period width is 8 ticks. With the frequency of 125000 Hz from above this gives the desired 15,625kHz */
        pwmZero,                                  //on counter overflow --> callback to function pwmZero
        {
                {PWM_OUTPUT_DISABLED, pwmSet},           //on output compare of channel 0 --> callback to function pwmSet, no GPIO function
                {PWM_OUTPUT_DISABLED, NULL},             //all other channels not used
                {PWM_OUTPUT_DISABLED, NULL},
                {PWM_OUTPUT_DISABLED, NULL}
        },
        0,                                        // cr2 register - usually zero
        0                                         // dier register - usually only for DMA
};

The functions pwmZero() and pwmSet() set the MOSFETs:

Code: Select all

static void pwmZero(struct PWMDriver *pwmDriver) {
    (void)pwmDriver;
    setSwitches(MOS_LOW);
}

Code: Select all

static void pwmSet(struct PWMDriver *pwmDriver) {
    (void) pwmDriver;
    setSwitches(MOS_POS);
}


I use the PWM like this:

Code: Select all

static uint8_t pwmIsActive = 0;
if(pwmValue != 0){
    if(pwmIsActive == 0){
        pwmStart(&PWMD8, &pwmcfg);
        pwmEnableChannel(&PWMD8, 0, 8-pwmValue);  //enable PWM channel 0; 8-pwmValue to invert the PWM
        pwmEnableChannelNotification(&PWMD8, 0);  // enable interrupt on output compare channel 0
        pwmEnablePeriodicNotification(&PWMD8);  //enable interrupt on counter reset
//           osalSysLock();
//           PWMD8.tim->CNT = 7;  // maybe set the CNT value?
//           osalSysUnlock();
        pwmIsActive = 1;
    }else{
        pwmEnableChannel(&PWMD8, 0, 8-pwmValue);
    }
}else{  // pwmValue == 0
    if(pwmIsActive == 1){
        stabl_deactivatePwm();
        pwmIsActive = 0;
    }else{/*no statement*/}
}

When a new PWM value comes in and the PWM is not active jet, it is started. Else, just the PWM value is activated by calling pwmEnableChannel().
If the PWM value is 0, I deactivate the PWM (calling pwmEnableChannel(&PWMD8, 0, 8) caused a strange PWM output)
the output now looks like this:
PWMDelay.png
PWMDelay.png (13.87 KiB) Viewed 1960 times

The blue signal is the TIM8 conter which is used for th PWM and the yellow signal is the battery voltage, which is set by the PWM.
You can see, how the first Timer period after starting the PWM does not produce a PWM output.

To solve that, I had two ideas:
1. is there a way, to preset the PWM value before starting the PWM so that it directely generates a PWM output with the first Timer counter period?
2. how can I edit the PWMD8.tim->CNT register? I thought about directely setting the CNT to 7, so that the counter overflow happens straightaway and uses the new PWM value

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Set PWM Timer

Postby Giovanni » Wed Feb 10, 2021 5:58 pm

Hi,

I think that it is skipping the 1st cycle because the STM32 timer takes then new comparators values on the next update event (when the counter reaches its maximum value and returns to zero, see the ARPE bit in CR1 which is enforced by the driver).

You should not change the counter yourself, if you want to enforce an immediate update then you may use the UG bit in DIER register.

Giovanni

JSStabl
Posts: 78
Joined: Tue Feb 25, 2020 4:06 pm
Has thanked: 3 times
Been thanked: 2 times

Re: Set PWM Timer

Postby JSStabl » Mon Feb 15, 2021 11:54 am

Hi Giovanni,
thanks a lot for the fast answer!
I changed the UG bit in the EGR register and it updates immedeately (at least the output looks like that).
So I now change the pwm Value and reset the UG bit afterwards:

Code: Select all

pwmEnableChannel(&PWMD8, 0, pwmValue);
PWMD8.tim->EGR =1U << 0;


Return to “ChibiOS/HAL”

Who is online

Users browsing this forum: No registered users and 8 guests