Problem changing PwmOut on the fly

18 Feb 2013

Hi all,

I oiginally posted this in the questions area but it seems that does not get a lot of "foot traffic" so I'm reposting here. PLease excuse me if I'm comitting a no-no by cross posting!

I am currently utilizing a PWM pin to be a "simulator" for some hardware that I am going to build. Basically I am going to use the PWM to drive a stepper driver (from Pololu) and I'm using an opto-interrultor connected to a pin on the mbed and that pin is configured as an interrupt. This way I can count the interrupt time and be certain that the motor is actually moving at the RPM expected.

In the meantime I have the PWM directly driving the interrupt pin. (I'm only counting a "pulse" every 200th interrupt since the stepper takes 200 steps per revolution.)

The problem I am having is that when I go to change the period of the pulses on the PWM, the interrupts stop happening.

Below is a snippet of my code. I have tried both with a pointer tp PwmOut and a delete/new pair trying to "kickstart" things and with just a regular PwmOut member variable:

    motorSim = new PwmOut(p21);
    motorPulse.rise(&revolution);
    motorSim->period_us(1000);
    motorSim->pulsewidth_us(2);
    wait(10);
    char buf[1024];
    int ptr = 0;
    //pc.printf("\r\n\r\n"); //Position to where input will be
    displayUpdater.attach(&updateDisplay, 1.0);
    delete motorSim;
    motorSim = new PwmOut(p21);
                motorSim->period_ms(2000);
                motorSim->pulsewidth_us(2);

So once I get input on the serial line and convert it into a number I calculate and change the period using period_ms(); but when that happens my interrupt code stops firing. So I am assuming that my change to the period is stopping the PWM output.

Any suggestions as to how I can change the period without killing the PWM?

Thanks in advance!

18 Feb 2013

Could you post whole program?
I'll do a hardware-test.

EDIT: Just did, tested what I thought could be useable:

#include "mbed.h"

DigitalOut myled(LED1);
PwmOut motorSim(p21);
InterruptIn motorPulse(p22);
char buf[1024];
int i = 0;

//int ptr = 0;
//pc.printf("\r\n\r\n"); //Position to where input will be
//displayUpdater.attach(&updateDisplay, 1.0);
//delete motorSim;
//motorSim = new PwmOut(p21);
//motorSim->period_ms(2000);
//motorSim->pulsewidth_us(2);

void revolution(){
    myled = !myled;
}

int main()
{
    motorSim.period_us(1000);
    motorSim.pulsewidth_us(2);
    motorPulse.rise(&revolution);
    while(1) {
        wait_ms(2500+i);
        motorSim.period_ms(i+2000);
        
        i++;  
    }
}

This keeps inverting the state of LED1.
Which means the program works.


Lerche

18 Feb 2013

Hi,

Incase it is just a typo, you use _us() for three of the settings, and _ms() for one (ie your second setting is 2000x longer, when maybe it is meant to be 2x longer)

If that is not it, hope someone can help you track it down - as lerche says, if ypu can post the code to mske it repeatable that'll help too.

Simon

18 Feb 2013

Let's do a simple test:

#include "mbed.h"

DigitalOut myled(LED1);
DigitalOut L2(LED2);
PwmOut motorSim(p21);
InterruptIn motorPulse(p22);
char buf[1024];
int i = 0;

//int ptr = 0;
//pc.printf("\r\n\r\n"); //Position to where input will be
//displayUpdater.attach(&updateDisplay, 1.0);
//delete motorSim;
//motorSim = new PwmOut(p21);
//motorSim->period_ms(2000);
//motorSim->pulsewidth_us(2);

void revolution(){
    myled = !myled;
    i++;
}

int main()
{
    motorSim.period_ms(20);
    motorSim.pulsewidth_ms(2);
    motorPulse.rise(&revolution);
    while(1) {
        wait_ms(250+i);
        motorSim.period_ms(i+20);
        //i++;  
        //L2 = !L2;
        if(i > 1000){
            i = 0;
        }
    }
}



This works if you put a jumper between p21 and p22.
LED1 will keep blinking slower and slower.

Lerche

18 Feb 2013

Thanks to all who replied!

Totally my mistake! It was the usage of peroid_ms(2000); That combined with my only counting every 200th pulse meant that my code where I indicated interrupt activity would only execute every 6.66 minutes! Changing it to period_us(2000); worked perfectly!

Glad it was my mistake!

Thanks for pointing out my stupidity! Onward and upward now!

18 Feb 2013

Tim Borland wrote:

Thanks to all who replied!

Totally my mistake! It was the usage of peroid_ms(2000); That combined with my only counting every 200th pulse meant that my code where I indicated interrupt activity would only execute every 6.66 minutes! Changing it to period_us(2000); worked perfectly!

Glad it was my mistake!

Thanks for pointing out my stupidity! Onward and upward now!

Glad it worked out for you! Not stupidity, just staring yourself blind into the software.

Lerche