Important changes to forums
We’re making some changes to the Mbed forums.
From 10th December 2019 all new discussions will take place on our
new forum site.
You can continue to reply to existing threads for the
next two weeks. After that we will archive this forum so
you can return to useful posts in the future.
How do i mesure PWM?
Topic last updated
13 Feb 2017, by
Gustavo Klein.
18
replies
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.
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.
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.
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.
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
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
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.
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
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.
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
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
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
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.
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.
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);
}
}
That program above, it could be use in LPC1768??
Regards
You need to log in to post a reply
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.