PWM program

09 Mar 2012

Hello, what I am trying to do is to send 10000 pulses out, increase the pulse width, send out another 10000 pulses, etc. The purpose is for the LED to be on at a low brightness for one second, then a little brighter for another second, etc. The problem is that my "reps" variable does not track the period in microseconds. The period must be 100 microseconds - that is not negotiable. Any help appreciated.

#include "mbed.h"

PwmOut l_out(LED1);
PwmOut out(p21);

int main() {

int i;
float pw;  // signal pulse width from 0 to 1
int reps;  // pulse repetitions
float level[]= {0, 0.2, 0.4, 0.6 }; 

out.period_us(100); 

while(1){
      for(i=0; i<=3; i+=1){
      pw = level[i];      // pulse width steps of 0, 0.2, 0.4, and 0.6
           for(reps=0; reps<=10000; reps+=1){  // for visual delay
           out.write(pw);
           l_out.write(pw);
           }
      }
  }
  }

10 Mar 2012

Just,

Your loops seem to be built on the assumptions that each 'write()' starts one pulse (on each output), and that the calls somehow automaticly delay the loop from repeating until (both) pulse periods time-out without one output delaying the other. When looked at that way I think you can see that the delay assumptions are at least self-contradictory. In fact, I don't think the 'write()' functions behave anything like you may wish.

What might work better is to set-up a periodic interrupt (with a 100 us interval) linked to an interrupt service routine that counts the pulses (counts retained in global variables), then sets the new pulse width(s) and triggers the 2 (one-shot) pulses.

10 Mar 2012

Fred, thank you for the suggestions. I can't really understand from the handbook what the PmwOut class does exactly. It's a bit terse. 1) Does the statement "out.period_us(100);" by itself generate a bit stream? 2) If so, what is the default pulse width? 3) Then do the "out.write(pw)" statements modify the bit stream to set the pulse width? That's basically all I am trying to do. regards jk

10 Mar 2012
10 Mar 2012

Out.period() starts the pulsestream but default pulsewidth is 0. So as soon as you select a non-zero pulsewidth the bitstream appears. It will continue forever without any further required action. You can change the pulsewidth or period at any moment by making the appropriate calls. An interrupt based timer could for example change the pulsewitdh every second. Without additional measures it will difficult to get an exact number of pulses before you switch to a new pulsewidth.

10 Mar 2012

Hi,

reading your original post, is counting the pulses etc etc really what you want to do ? you say you want to brighten an LED at 1 second intervals.

If that's true, I think you are not quite getting just how easy PWM is to use...

set a pin tp PWM. set it's pulsewidth to give it a frequency. i.e. 10kHz. (100ms)

set the duty cycle to say how much it is on and how much it is off. change the duty cycle at 1 second intervals using a timer, or ticker.. or for proof of concept, a loop !

(disclaimer, quick and nasty code)

I've just loaded this code on an mBed and it runs fine ;-)

#include "mbed.h"
PwmOut myled(LED1);
float duty=0;

int main() {
  
  myled.period(1.0/10000);   //10 kHz

  while (1) {

   duty=duty+0.1;  // 0 - 1 value. 10% jumps
   if (duty>1) (duty = 0); // if you get over 100%, zero it.
   myled.write(duty);
   wait(1); //wait a second before adding 10% to the duty cycle

  }

}

10 Mar 2012

Wim Huiskamp wrote:

Out.period() starts the pulsestream but default pulsewidth is 0. So as soon as you select a non-zero pulsewidth the bitstream appears.

Ahhh, I see. So you do need at least two function calls to generate a visible pulse stream. At least I had that right. :)

Dave Tech wrote:

reading your original post, is counting the pulses etc etc really what you want to do ? you say you want to brighten an LED at 1 second intervals.

The program in my OP was just a test program. In my application I do need to modify the pulse width at precise intervals, as short as a millisecond with 100 uS accuracy. That's why I was trying to count pulses. However, If I can do it with a timer as you suggest, it sounds like that might be easier (and maybe more accurate?).

Dave Tech wrote:

If that's true, I think you are not quite getting just how easy PWM is to use...

Probably true! Thanks wim and kstech for filling in the missing pieces, and thanks for the demo code. I will post a little later when I make some progress with a timer.

10 Mar 2012

Hmm...

I've not quite got it,..

the period IS the length of the pulses. In your first post, you say you want to keep the period constant, yet vary the width of the pulses. I'm afraid that doesn't make sense. They are the same thing.

In my duty cycle example, I've interpreted the application of what you've written, but not looked closely at what you've written, but I'm afraid the application isn't what you were actually after.

(I've done a varying duty cycle at a fixed pulsewidth/frequency)

It now sounds more like, you want to vary the width of the pulses, but you begin by saying you can't ?

I must admit I'm confused. This isn't for something like a 38kHz carrier wave, that you want to send a 600ms "on" over, then a 300ms "off" over or some such is it ? and they are your "pulses". PWM is very easy to use, but you have to have clear thinking about what you actually want it to do.

I always think of it as..

period=frequency. duty cycle = percentage of "on ness" during each cycle in that frequency.

So, if you specify a 10 kHz frequency and a 50% duty cycle, you get a 10kHz square wave. i.e. 10,000 cycles per second, each of them half on and half off.

You can change the duty cycle to 75%. You get 10,000 cycles per second, each cycle is high for 75% of the time, and then goes low for 25% of the time.

So, period gives you the length of the repeating unit, (the frequency), duty cycle gives you the "on ness" during that unit.

100% duty cycle is of course completely on ! 50% duty means it goes high then low 10,000 times a second.

I hope this is all making sense. I'm now not sure of *exactly* what you want to do,

cheers

10 Mar 2012

Dave, I agree with your explanation except for the first paragraph: the period is NOT the pulsewidth but the repetionrate of the pulses. The rest of your explanation also says so. The pulsewidth controls the dutycycle, it canbe varied between 0 and period. Alternatively you can set the dutycycle directly by writing a value between 0.0 and 1.0

10 Mar 2012

Aha.. Many thanks, then my understanding is correct, but my nomenclature is wrong. Thanks for taking the time to put me straight.

So, re reading the original posters question.

He really can just set the period, and then alter the pulse width as needed. (between 0 and period)

It really should be that easy !

12 Mar 2012

i am also trying to generate pwm of varying frequency i.e. from 1Mhz to 30 Mhz. this cant be done with the library so i need to manipulate the hardware registers. i found very useful information in one of the other forum topics but i still do not understand the syntax of the code.

LPC_SC->PCONP |= (1 << 6); PWM1 power on LPC_SC->PCLKSEL0 |= (1 << 12); Divide CCLK by 1 for PWM1 LPC_PINCON->PINSEL4 |= 1; DIP26 = pin P2.0, set to PWM1.1

can someone please explain it to me in very raw terms. im a beginner and do not know much about c++. does (1 << 6) means that 1 is shifted six bits to the left? or bit 6 is turned on?

thank you

19 Mar 2012

Muhammad A Khalid wrote:

i am also trying to generate pwm of varying frequency i.e. from 1Mhz to 30 Mhz. this cant be done with the library so i need to manipulate the hardware registers. i found very useful information in one of the other forum topics but i still do not understand the syntax of the code.

LPC_SC->PCONP |= (1 << 6); PWM1 power on LPC_SC->PCLKSEL0 |= (1 << 12); Divide CCLK by 1 for PWM1 LPC_PINCON->PINSEL4 |= 1; DIP26 = pin P2.0, set to PWM1.1

can someone please explain it to me in very raw terms. im a beginner and do not know much about c++. does (1 << 6) means that 1 is shifted six bits to the left? or bit 6 is turned on?

Muhammad, your question is very different from my original question. I recommend you start a new thread with this question.