Funky pc.printf() behavior

29 Apr 2012

Hi,

I'm a newbie, so hopefully some great guru out there will see the obvious answer to this. If I uncomment the pc.printf(...) line in the do{} loop below, the led lights up. If I don't, it remains dark. This is true for any value of epsilon, not just 1.0e-9. Some buffer gets flushed or something? Help?

Thanks.

JAG

#include "mbed.h"

Serial pc(USBTX, USBRX); // tx, rx
PwmOut led(LED1);

int main() {
    pc.printf("\r\nVisual Acuity Tester.\r\n");
    pc.printf("Press any key to begin.\r\n");
    char c = pc.getc();
    led = 1.0;
    float dutyCycle = .5;
    float period = 1.0e-2;
    float epsilon = 1.0e-9;
    led.period(period);
    led.write(dutyCycle);
    do{       
        period += epsilon;
        led.period(period);
        //pc.printf("The period is %f\r\n",period);
        }while(!pc.readable());
    led = 0;
    float frequency = 1/period;
    pc.printf("Frequency at which you detected flicker: %fHz.\n",frequency);
}
29 Apr 2012

I think the printf() is just slowing things down enough that you actually give the PWM hardware time to run before you give it a new setting. Without the printf() in the loop, you are changing the period very quickly. Replace the printf() with something like a wait(0.25f); to give 1/4 of a second to each PWM setting.

01 May 2012

Thanks Adam,

I thought of that, but replacing the pc.printf() call with the wait() call screws with the period.

JAG

01 May 2012

I think the issue is that you are changing the period of the PWM with no synchronization to when the pulse completes a full cycle which would introduce glitches in the output waveform. You can probably skip using PWM altogether and just use wait() calls to get the behaviour that you want and then you will be fully synchronized to the waveform where you don't change the period of one pulse until you complete the previous one.

For example:

#include <mbed.h>

Serial     pc(USBTX, USBRX);
DigitalOut led1(LED1);

int main() 
{
    pc.printf("\r\nVisual Acuity Tester.\r\n");
    pc.printf("Press any key to begin.\r\n");
    char c = pc.getc();
    pc.printf("Test started.\r\n");
    pc.printf("Press any key once you detect flicker.\r\n");
    
    float period = 1.0e-4f;
    float epsilon = 1.0e-4f;
    do
    {
        float halfPeriod = period / 2.0f;

        led1 = 1;
        wait(halfPeriod);
        led1 = 0;
        wait(halfPeriod);
        
        period += epsilon;
    } while(!pc.readable());

    float frequency = 1.0f / period;
    pc.printf("Frequency at which you detected flicker: %fHz.\n", frequency);
}

Hope that helps,

Adam

01 May 2012

edit: Posted twice somehow.

02 May 2012

Thanks, Adam Green. You're a superstar!

Curious though... seems like this solution would not be accurate at higher frequencies due to temporal overhead from variable declarations, assignments, etc. getting in the way. Is it so?

One would need to use pwm there, and there would need to be some way to coherently change the frequency. Am I right? If so, do you know how this is done?

JAG

02 May 2012

James A. Garfield wrote:

Curious though... seems like this solution would not be accurate at higher frequencies due to temporal overhead from variable declarations, assignments, etc. getting in the way. Is it so?

There will be some overhead but it depends on what kind of accuracy you need. If it is just for visual acuity then I don't think the overhead will be that bad. You could have it pulse a pin instead of the LED and connect an oscilloscope to see how much overhead there was. If you switched away from floats, I wouldn't think it would be much more than a hundred or so cycles of overhead (or maybe even less) which is 1 microsecond.

The PWM module is really meant for modulating the width of a pulse that has fixed period. I don't know how easy it would be to use it for what you want. I would probably resort to some assembly language in a timer interrupt to perform this task and then look at the result on an o-scope to see how close it is.

02 May 2012

Agreed, for a visual acuity tester the accuracy is good enough. Being a newbie and all, I was only curious to know if there was some magical function call or pwm member variable that could vary the frequency of a square wave coherently. Would like to avoid assembly hell if possible.

Thanks for your help, AG.

JAG