How do i mesure PWM?

03 Feb 2010

Hi,

I have a square wave of  20ms period from a RC receiver that send me pulses between 1.0ms and 2.0 ms.

i want to know how i must program this in order to know the pulse width in real time.

thx.

03 Feb 2010

Try this.

03 Feb 2010

 

Igor Skochinsky wrote:

Try this.

thx, but it doesn't work.

 

03 Feb 2010 . Edited: 03 Feb 2010

thx, but it doesn't work.

Would be nice if you were to tell us what "doesn't work" The code is correct for what it does. It would also be nice if you could explain in more detail what it is you want to do.

05 Feb 2010

 

Stephen Franklin wrote:

thx, but it doesn't work.

Would be nice if you were to tell us what "doesn't work" The code is correct for what it does. It would also be nice if you could explain in more detail what it is you want to do.

Well, i'm agree with you. I'm going to try explain better what i want to do. I hope be able to speak english correctly.

i have a rc transmitter to send instructions to mbed trough a receiver. Transmitter sends high pulse every 20ms. The high pulse width duration is between 1.0ms and 2.0ms.

What i'm trying to do is send to the computer how long the pulse is high.

 

thanks for your patience.

 

10 Feb 2010

hi again.

I go on without be success.

Code:

 

#include "mbed.h"

DigitalIn radio(p8);
Serial pc(USBTX, USBRX); 
Timer timer;
float duration;

int main() {

    while (1) {
        // pulseIn

        while (!radio); // wait for high

        timer.start();

        while (radio);
        { // wait for low

            duration = timer.read_ms();
            pc.printf("Pulso de: %f ms", duration);

        }
    }
}

and serial port says:

 

Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms
Pulso de: 1.0000 ms 
etc
etc

what's wrong?

 

thx.

 

 

10 Feb 2010

Outl4w - wrote:

hi again.

I go on without be success.

Code:

 

#include "mbed.h"

DigitalIn radio(p8);
Serial pc(USBTX, USBRX); 
Timer timer;
float duration;

int main() {

    while (1) {
        // pulseIn

        while (!radio); // wait for high

        timer.start();

        while (radio);
        { // wait for low

            duration = timer.read_ms();
            pc.printf("Pulso de: %f ms", duration);

        }
    }
}
Hi,

 

Unfortunately I don't have my mbed with me to give a try, but the read function returns an integer, so "duration" would be  better as an integer. This wouldn't give you much resolutions, so maybe you should go with read_us. As long as it doesn't exceed the size of the integer.

 

Also, I'd do a timer.start at the beginning of the main function, and after I'd do a timer.reset instead after your first loop.

 

A better way would be using interrupts, this way you could create a function out of it and use it in a program without stopping the process.

 

PA

11 Feb 2010

If you are just trying to get the ms that the pin is high you need to do

 

while(1)
{
   // pulseIn
   while(!radio); // wait for high
   // once pin goes high
   timer.start();

   while(radio);// wait for low
   // now how long was pin high
   duration = timer.read_ms();
   pc.printf("Pulso de: %f ms", duration);
}
hope that helps

Matthew

11 Feb 2010

Matthew, I was going to ask what was different in your code but after looking at it for a (few) minutes I noticed the curleys were different. It makes sense now.

11 Feb 2010

Stephen Franklin wrote:

Matthew, I was going to ask what was different in your code but after looking at it for a (few) minutes I noticed the curleys were different. It makes sense now.

Yeah sorry I typed that in and posted it before I noticed he had the semi-colon after the while, so his code should be equivalent to mine. This code is basically the same as I used on my PING sensor as mentioned above by Igor. Here is the code I settled on for pulseIn.

// pulseIn
while (!_trigger); // wait for high
_timer.reset();
_timer.start();
while (_trigger); // wait for low
_timer.stop();
_dist = _timer.read_us(); //provides echo time in microseconds

11 Feb 2010 . Edited: 11 Feb 2010

Hi,

I *think* your code is actually working perfectly :)

An R/C control signal is a pwm signal with a high pulse of 1.5ms representing center. It will vary either side of this (e.g. 1.1-1.9ms, maybe further) for contol. Your code is measuring the time in ms, so the result of 1ms is spot on.

The confusion is probably that you want to measure at more than ms accuracy. read_ms() returns the number of ms passed as an integer, so even when assigned to a float it'll still only be accurate to 1ms.

The alternatives are to use read() which is a float representing the time in seconds, but down to us accuracy, or the read_us() function that returns the number of us passed as an integer.

As you are happy treating it as a float, try just using read() instead of read_ms(); I suspect you'll get a result around 0.0015 seconds.

Simon

11 Feb 2010

Good morning.

Thanks a lot, now with read() (in seconds) and /1000 i can see PWM in my computer.

In fact, i know now that my chinese receiver is very bad.

Representing Center:

Pulse Width: 1.7 ms :)

Stick Down:

Pulse Width: 1.1 ms

Stick Up:

Pulse Width: 1.9 ms

Thanks again.

I will go on working with RC in order to make a submarine with Mbed.

You can see the project here:

http://sites.google.com/site/outl4wgeek/

Sorry, it's in Spanish but if somebody are interested i translate whatever you want.

11 Feb 2010

What i don't know now it's how i should program to read 3 signals at the same time. in timer documentation says that i can create any number of timers but if i repeat 3 times what we have programed until now i not receive correct times.

hope i explain well.

thank you very much

12 Feb 2010

Trying to solve the problem of count 3 channels i'm using interruptin but not working.

Code:

 

#include "mbed.h"

Serial pc(USBTX, USBRX);

InterruptIn canal2(p5);
InterruptIn canal3(p6);
InterruptIn canal4(p7);

Timer timer1;
Timer timer2;
Timer timer3;

float duracion1;
float duracion2;
float duracion3;

void cuenta1(){

timer1.start();
while (canal2);
duracion1 = timer1.read() / 1000;
pc.printf("Duracion canal2: %f ms\n", duracion1);

}

void cuenta2(){

timer2.start();
while (canal3);
duracion2 = timer2.read() / 1000;
pc.printf("Duracion canal3: %f ms\n", duracion2);

}

void cuenta3(){

timer3.start();
while (canal4);
duracion3 = timer3.read() / 1000;
pc.printf("Duracion canal4: %f ms\n", duracion3);
}

int main() {
    while(1) {
    
    canal2.rise(&cuenta1);
    canal3.rise(&cuenta2);
    canal4.rise(&cuenta3);
        
    }
}

Serial:

 

Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms
Duracion canal4: 0.000000 ms
Duracion canal3: 0.000000 ms
Duracion canal2: 0.000000 ms

 

 

 

17 Feb 2010

Anybody could tell me if at least i'm going in good direction?

17 Feb 2010 . Edited: 17 Feb 2010

I think the main problem is you are catching the rising edge interrupts, but then blocking for the falling edge interrupt.

Here is an example I just put together using a slightly different strategy (also published, see below):

// Example PwmIn class to detect PWM inputs, sford
//  - Note: uses InterruptIn, so not available on p19/p20

#include "mbed.h"

class PwmIn {
public:
    PwmIn(PinName p) : _p(p) {
        _p.rise(this, &PwmIn::rise);
        _p.fall(this, &PwmIn::fall);
        _period = 0.0;
        _pulsewidth = 0.0;
        _t.start();
    }
    
    void rise() {
        _period = _t.read();
        _t.reset();
    }
    
    void fall() {
        _pulsewidth = _t.read();
    }
    
    float period() { return _period; }
    float pulsewidth() { return _pulsewidth; }
    float dutycycle() { return _pulsewidth / _period; }

protected:        
    InterruptIn _p;
    Timer _t;
    float _pulsewidth, _period;
};

PwmOut x(p21);
PwmOut y(p22);

PwmIn a(p5);
PwmIn b(p6);

int main() {
    x = 0.5;
    y = 0.2;
    while(1) {
        printf("a: pw = %f, period = %f\n", a.pulsewidth(), a.period());
        printf("b: pw = %f, period = %f\n", b.pulsewidth(), b.period());
        wait(2);
    }
}

PwmIn

btw, the PwmOut instances are because I was connecting p5/6 to p21/22 to test (in the loosest sense of the word). Needs work and doesn't cope with all cases, but might help you get started.

Simon

27 Feb 2010

Fantastic Simon, thank you very much, with a bit of work i'm able already to know the pulse width of all channels of the RC transmitter.

04 Dec 2010

Just wondering if there is an updated version of the original work done by Simon.

I am about to start a project to add driving aids to a high performance remote control car (stop on crash, slow prior to turn, etc), and the PwmIn example is exactly what i was looking for.

13 Feb 2017

Example PwmIn class to detect PWM inputs, sford - Note: uses InterruptIn, so not available on p19/p20

  1. include "mbed.h"

class PwmIn { public: PwmIn(PinName p) : _p(p) { _p.rise(this, &PwmIn::rise); _p.fall(this, &PwmIn::fall); _period = 0.0; _pulsewidth = 0.0; _t.start(); }

void rise() { _period = _t.read(); _t.reset(); }

void fall() { _pulsewidth = _t.read(); }

float period() { return _period; } float pulsewidth() { return _pulsewidth; } float dutycycle() { return _pulsewidth / _period; }

protected: InterruptIn _p; Timer _t; float _pulsewidth, _period; };

PwmOut x(p21); PwmOut y(p22);

PwmIn a(p5); PwmIn b(p6);

int main() { x = 0.5; y = 0.2; while(1) { printf("a: pw = %f, period = %f\n", a.pulsewidth(), a.period()); printf("b: pw = %f, period = %f\n", b.pulsewidth(), b.period()); wait(2); } }

That program above, it could be use in LPC1768??

Regards