|
|
View previous topic :: View next topic |
Author |
Message |
reddyysnr
Joined: 15 Apr 2013 Posts: 6 Location: India
|
Software PWM 40KHz with variable duty cycle |
Posted: Sun Jun 30, 2013 10:44 am |
|
|
Hi all,
I'm new to PIC and have worked with the basics on PIC. I am trying to explore features like Timers, software PWM etc.
I'm using 16F677 running at 8MHz internal clock. I am trying to generate a software PWM of frequency 40KHz. I have seen methods which use
Code: | output_high(pin);
delay_us(13);
output_low(pin);
delay_us(12); |
Repeating it multiple times can generate what I require. However I need to achieve the same without using delays; by using Timers. One reason why no delays because I could use that time to work with other devices.
I also require control over the duty cycle(could be anything between 5-95%) Is this even possible? If yes, kindly point me into the right direction..
Another general question: Can we access the data stored in the Timer registers.? i.e: The 8 bit data in Timer0 or the 16 bit data in Timer1, if yes, again kindly point me into the right direction
Thank you.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Sun Jun 30, 2013 12:37 pm |
|
|
Not possible.
Just too fast.
It takes _time_ to setup timers, read timers, detect timers have expired. 40KHz, is a total cycle of just 25uSec. Just 50 processor cycles.
Even using the delays approach, you could only do a very limited range of cycle durations.
Seriously, the whole point of hardware PWM's, is to allow frequencies above what software can handle and allow reliable operation while the processor is doing other things.
Best Wishes |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 30, 2013 1:49 pm |
|
|
Sit down and do the maths.
(With the data sheet if you need it)
You want 40kHz frequency with an 8MHz clock.
That defines your range of duty cycles using the PIC's built in hardware PWM.
With your posted code you've totally ignored the time taken to perform the output_xxx(pin) functions.
Mike |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 30, 2013 1:56 pm |
|
|
I suspect you want to make an IR TV remote transmitter. If that's what
you want to do, you should tell us. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Jun 30, 2013 11:50 pm |
|
|
PIC16F677 can do hardware PWM for a single half- or full bridge. Modulation schemes are limited to basic 2-level, however. |
|
|
reddyysnr
Joined: 15 Apr 2013 Posts: 6 Location: India
|
|
Posted: Mon Jul 01, 2013 6:59 am |
|
|
@Ttelmah,@Mike Walne
Correct me if I'm wrong.
At 8MHz, every instruction cycle takes 0.5uS. (I read on some page that 1/(clock/4) gives the time period of one instruction cycle)
If we need to generate something which has a duty cycle of 25uS, why wouldn't that be enough?
Even with the approach of
Code: | output_high(pin);
delay_us(delay);
output_low(pin);
delay_us(delay);
|
if we calculate the time taken for output_xx(pin) and change delay accordingly, why wouldn't it work?
If not possible, what would be the maximum achievable frequency and how do I calculate it?
@PCM programmer: At this point, I haven't thought about an IR transmitter. I'm just experimenting to learn.
Quote: | PIC16F677 can do hardware PWM for a single half- or full bridge. Modulation schemes are limited to basic 2-level, however. |
@FvM: I don't seem to understand. Could you explain a bit. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Mon Jul 01, 2013 8:00 am |
|
|
You said this in your first post. Quote: | Repeating it multiple times can generate what I require. However I need to achieve the same without using delays; by using Timers. One reason why no delays because I could use that time to work with other devices. | Using delays can be made to work, but there are two problems, (1) it ties up the PIC (2) resolution is limited to 500ns at best.
With the hardware PWM you free up the PIC and get 125ns resolution.
Mr. T. and I are trying to point you in the right direction.
Quote: | If not possible, what would be the maximum achievable frequency and how do I calculate it? | This question is simply moving the goal posts.
I believe maximum frequency achievable is 2MHz with your 8MHz clock, but it's not terribly helpful.
The calculations are shown in the data sheet.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Mon Jul 01, 2013 8:47 am |
|
|
First understand that a single C instruction is lots of PIC instructions. Something like a multiply, _hundreds_. However even something simple like reading a timer register, for a 16bit timer, has to select the bank used, read an eight bit byte, select another bank, and write this to a RAM location, then do the same for the second byte. Just loading a timer, with a value from a variable, will take something like ten machine instructions. 0.5uSec/instruction, is only 50 instructions in 25uSec. Yes, you could generate a 40KHz pulse, but using two variable widths, no. Using a timer, and setting/reading it, will just take too long. You could have two delay based routines, giving two different pulse widths, and switch physically between these.
delay_us(variable), has a minimum time it can generate (just the time needed to access the variable and test), and a minimum 'step size'. Minimum time, for your processor will be 5uSec, and 1.5uSec 'step'.
Then simply outputting a level will take typically four instructions. So, you could have a couple of routines to develop say a 35% duty cycle, and a 65% duty cycle, adjust all the timings to work, and switch between them, but how are you then going to find the time to do this switch?.
Seriously, play with the hardware PWM, that is what it is _for_.
With this, the hardware generates all the timings once told, so you can do the jobs like making a decision to change pulse width....
Now, there are ways of being 'ingenious', and getting close, Primarily (funnily), using Timer2. Alone of the 'standard' timers, it can handle generating short timings, with automatic resetting. It's designed this way, to drive a PWM.....
Code: |
#USE FAST_IO(A) //speed up pin I/O
#bit T2IF=getenv("BIT:TMR2IF") //Timer 2 interrupt flag
void main(void)
{
int8 val;
output_low(PIN_A1); //set latch low
output_drive(PIN_A1); //set the pin to drive
disable_interrupts(GLOBAL); //Make sure interrupts are off
val=5;
setup_timer_2(T2_DIV_BY_1,49,1); //Timer2 will now run at 40KHz
do
{
clear_interrupt(INT_TIMER2);
output_high(PIN_A1);
delay_us(val);
output_low(PIN_A1);
while(T2IF==0) ; //wait for timer2
} while(TRUE); //and loop
}
|
Now this is just about as close to optimal as you can get. First the loop is automatically timed by Timer2, which interrupts 40000 times per second. When this happens T2IF is set, which then terminates the loop. No changing or reading it's value, just poll the interrupt flag.
Then the port is used in 'fast_io' mode, where you control the TRIS, and so just one instruction is needed to set or clear a pin (plus bank switching).
Now, with val=0, you get a pulse of 6uSec. You get the same 6uSec all the way to val=8. Then at val=9, it jumps to 9.5uSec, with the same for val=10, then every other 'val' value, gives different times up to val=22. After this it starts running out of time, and the output frequency drops.
As a general comment, get MPLAB, and start experimenting in it's simulator. This way you can see how long things take.
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Jul 01, 2013 4:36 pm |
|
|
WHAT are you actually trying to DO !!!
unless your goal is to simply get a good grade,
with knowledge of your specific design task,
much more help could come your way.
but with the opaque presentation so far- not so likely
|
|
|
reddyysnr
Joined: 15 Apr 2013 Posts: 6 Location: India
|
|
Posted: Tue Jul 02, 2013 2:10 am |
|
|
@Ttelmah: That was pretty helpful. Though I didn't understand a few things, I'll use them as pointers to try and explore. I use Proteus to simulate; I'll try out MPLab..
@asmboy: There's nothing at all to be hidden.. I'm not working on any secret project. Like I said, I'm just trying to experiment with software PWM. 40KHz was a number I found interesting because I see it's used in IR Protocols, Ultrasound Transceivers and also some AC lamp dimmers.. If I succeed, I MIGHT take up and any of those in the future.. and if 40KHz isn't possible, my goal is to achieve the maximum possible frequency.. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Jul 02, 2013 3:55 am |
|
|
asmboy is not suggesting you are purposely hiding anything.
Your questions are so vague we can't figure out what you are trying to do.
You learn by having a play with REAL hardware.
FORGET PROTEUS. It will cause more problems than it solves.
If you must simulate, use MPLAB.
Like I said before the answers to your PWM questions are all in the data sheet.
Ttelmah has explained the software PWM limitations.
If you want to work at 40kHz with an 8MHz clock the hardware PWM is the sensible way to go.
That's a 25us period.
The duty period resolution will be 125ns.
So you will be able to go from duty period of zero, through 125ns, 250ns in 125ns steps.
All the way to 24.750us, 24.875us and 25us.
That's 201 steps or ~0.5% each.
If you want more resolution:-
(1) you use a faster clock for 40kHz PWM or
(2) accept lower frequency PWM.
Mike |
|
|
reddyysnr
Joined: 15 Apr 2013 Posts: 6 Location: India
|
|
Posted: Tue Jul 02, 2013 5:24 am |
|
|
Thanks Mike.. I'm on it.. Sorry for being vague.. Next time I have a doubt, I'll post clearly.. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|