10 years, 4 months ago.

FastPWM and Frequencies on KL25Z

Howdy. I was looking into using KL25Z to create a PWM signal with at a relatively high frequency. I can't seem to get it to operate at the right frequency.

Using the FastPWM library and the first block of code (not commented out), I get pulsewidths of 20ns, 518ns, 1043ns, 15624ns and 0ns (always low), but with PWM frequency of 1.1295Khz. The pulsewidths seem accurate, but the period is wrong.

Using the second block of code, where period is set in us, I get pulsewidths of 0.2ms, 5ms, 10ms, 15ms, 19.8ms, but with a PWM frequency of 50Hz. Both pulsewidth and period are wrong, but at least they scale.

Using the third block of commented out code using the PwmOut library, I get the desired frequency of 200Khz, but 1% and 99% pulsewidths are missing. This is not desired, and I assume it's due to overhead.

Am I doing something wrong? Or maybe I don't understand what's supposed to be happening here. Any comments would be welcome.

include "mbed.h"
#include "FastPWM.h"

PwmOut b(LED_BLUE);
PwmOut d(PTA13);


int main() {
 
   // uint32_t pulsewidth_ticks;
    uint32_t period_ticks=100;
    int steps=5;
    uint32_t pw[5] = {1,25,50,750,99};
    
    //initFastPWM();
        
    FastPWM d(PTA13,1);
    FastPWM b(LED_BLUE,1);  
    d.prescaler(1);
    b.prescaler(1);
    
    // define period of pwm...
    d.period_ticks (period_ticks);
    b.period_ticks (period_ticks);
    
    while (1){
        // cycle through steps of pwm resolution...
        
        for (int i= 0; i < steps+1; i++) {
            b.pulsewidth_ticks( pw[i] ); 
            d.pulsewidth_ticks( pw[i] ); 
            wait (1);
        }
    }


/* this didn't work either.

   // uint32_t pulsewidth_ticks;
    int period_us=5;
    int steps=5;
    double pw[5] = {.01,.25,.50,.75,.99};
    
    //initFastPWM();
        
    FastPWM d(PTA13);
    FastPWM b(LED_BLUE);  
    d.prescaler(1);
 //   b.prescaler(1);
    
    // define period of pwm...
    d.period_us (period_us);
  //  b.period_us (period_us);
    
    while (1){
        // cycle through steps of pwm resolution...
        
        for (int i= 0; i < steps+1; i++) {
            b=( pw[i] ); 
            d=( pw[i] ); 
            wait (1);
        }
    }
*/

// try OutPWM again...

 /*
 
    int period_us=5;
    int steps=5;
    float pw[5] = {.01,.25,.50,.75,.99};
    
    //initFastPWM();
        
    PwmOut d(PTA13);
    PwmOut b(LED_BLUE);  
    
     
    // define period of pwm...
    d.period_us (period_us);
    b.period_us (period_us);
  
    
    while (1){
        // cycle through steps of pwm resolution...
        
        for (int i= 0; i < steps+1; i++) {
            b=( pw[i] ); 
            d=( pw[i] ); 
            wait (1);
        }
    }
*/
}

Question relating to:

Erik - / FastPWM Featured
Library that allows for higher resolution and speed than standard mbed PWM library using same syntax (drop-in replacement). pwm, resolution, Speed

1 Answer

10 years, 4 months ago.

Hey,

Thanks for the bugreport. So you are doing something wrong, and I was doing something wrong (I only looked at your first piece of code). If you use regular PWM you get 1us resolution, so the period works at 5us, but you can't make very exact steps in your pulsewidth.

Now for FastPWM.I removed the initial PwmOuts from the code, probably shouldn't hurt, but bit questionable. Then you have a typo in your pulsewidths (750), and your loop goes to steps+1, since you start at zero correctly, you only need to do it until steps, now you also put some random memory location on the output.

Then my fault. This code works fine. For only one of the two outputs. I used a method to store the location of the prescale register that apparantly isn't allowed, at least it stored it globally for only one of the outputs, while I thought it would store it for each FastPWM object. Learned something there, fixed it. Click on your FastPWM lib, then at the right side on update, and it should work properly.

I got a 24MHz logic analyzer, so can't check exactly the pulsewidths at 48MHz, but it seem to be correctish. And to really make it correct, I found out that:

Quote:

The EPWM period is determined by (MOD + 0x0001)

In other words I have to substract 1 from the given period ticks to get the correct period. That is also updated now in the FastPWM lib. As I said, my logic analyzer can't 100% guarantee it is correct at those speeds now, but I am pretty sure it is, and errors cant be larger than one clock cycle.

So check it out, and report back if it works now for you :)

Accepted Answer

Thanks for the prompt response.

I'll fix the two errors you found in my code, update the lib and let you know the result in about 12 hours.

posted by eric j 27 Jun 2014

Thanks! Very clean, precise output from the KL25Z.

posted by eric j 27 Jun 2014