|
|
View previous topic :: View next topic |
Author |
Message |
itsbasix
Joined: 23 May 2012 Posts: 8
|
16f628a PWM and internal osc |
Posted: Fri Jul 19, 2013 8:05 am |
|
|
hi , I'm using the following code to generate a pwm signal using pic 16f628a and its internal clock at 48KHz, switching duty cycle by pressing a button.
The circuit involves only the pic, a resistor to put MCLR high and a button connected between 5v and RB0.
I need this signal in order to drive a PS3 fan, but the fan doesn't move...i can't understand if the signal is "well-generated". By running a simulation in proteus i get weird behaviour of the PWM signal, but i know that simulator may show different outputs from the real ones.
Thank you and sorry my bad english.
Code: |
#include <16F628a.h>
#include <math.h>
//////// Fuses: LP,XT,HS,EC_IO,NOWDT,WDT,NOPUT,PUT,PROTECT,NOPROTECT
//////// Fuses: BROWNOUT,NOBROWNOUT,NOMCLR,MCLR,NOLVP,LVP,INTRC,RC_IO
//////// Fuses: INTRC_IO,RC,NOCPD,CPD
#fuses NOWDT,NOPROTECT,NOLVP,INTRC_IO,MCLR
#use delay(clock=48000)
#define PERIODO 0.02
int count=-1;
int16 getvalue(int DUTY);
#INT_EXT
void RB0_INT()
{
count++;
if(count>=7)
count=0;
}
void main()
{
setup_oscillator(OSC_48KHZ);
setup_timer_2(T2_DIV_BY_1,239,1);
setup_ccp1(CCP_PWM);
set_pwm1_duty(1024);
//set_pwm1_duty(getvalue(70));
delay_ms(2000);
enable_interrupts(INT_EXT);
enable_interrupts(global);
while(TRUE)
{
if(count==0)
set_pwm1_duty(getvalue(40));
else if(count==1)
set_pwm1_duty(getvalue(50));
else if(count==2)
set_pwm1_duty(getvalue(60));
else if(count==3)
set_pwm1_duty(getvalue(70));
else if(count==4)
set_pwm1_duty(getvalue(80));
else if(count==5)
set_pwm1_duty(getvalue(90));
else if(count==6)
set_pwm1_duty(getvalue(100));
}
}
int16 getvalue(int DUTY)
{
float TH=0;
int16 val;
TH=(DUTY/100)*PERIODO;
val=floor((48000*TH)+0.5);
return(val);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Jul 19, 2013 8:31 am |
|
|
If the simulator is showing it working, then it shows the problems with simulators....
Take duty=50.
What will:
TH=(DUTY/100)*PERIODO;
give?.
50/100 = 0, using integer arithmetic. Since both numbers are integers, integer arithmetic will be used.
Same applies with everything except duty=100.
So the function will give zero for every input value<100...
The maths is also 'foul'. Seriously, a floating point multiplication, at 12000mips, will take about 1/10th second. It's also 'not needed'.
Think for a moment. You know what duty value is needed for 100% ((239+1)*4)-1 = 959. Say 960. so 10% needs 96. Just take (duty/10)*96. No floating point, just int16. Probably about 50* faster, and smaller as well....
Code: |
int16 getvalue(int DUTY)
{
return(((duty/10)*96);
}
|
Best Wishes |
|
|
itsbasix
Joined: 23 May 2012 Posts: 8
|
|
Posted: Fri Jul 19, 2013 8:50 am |
|
|
thank you for your answer!
I changed that function and saved a lot of ROM space, but it still doesn't work and i can't get why... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Jul 19, 2013 9:59 am |
|
|
First thing is 'int count=-1'. An integer is unsigned by default....
You should really only be changing the PWM duty, when count changes, not every loop.
However key thing is have you actually verified the chip is running?. A simple 'flash an LED' program and verified it flashes at the right speed.
I'd be very suspicious of noise problems round the PIC, since you don't mention any decoupling.
Best Wishes |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Jul 19, 2013 11:36 am |
|
|
Code: |
#use delay(clock=48000)
|
is this for real?
if so you have a .012 MIPS processor flaming away |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Jul 19, 2013 12:49 pm |
|
|
That is the slow speed option on this particular PIC. If you calculate his PWM 50Hz, so 'makes sense'.
I'd suspect either his PWM, is momentarily going on. The power supply is glitching, and the PIC is resetting, or the chip is not running at all.
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Jul 19, 2013 1:54 pm |
|
|
You can also simplfy the program further by getting rid of the 'getvalue() function and just 'hard coding' the set_pwm1_duty() values. This eliminates all the bad math,floats,etc.
You should be careful about 'switch bounce' on the switch input ! It's very easy to get 3,4,10 or more 'closures' with simple mechanical switches.
Just search for 'debounce' here and you'll get a few dozen hits.
hth
jay |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Sat Jul 20, 2013 4:58 pm |
|
|
Boy, everyone's got something to say, haven't they.
My contribution is that I don't like the sound of "a button connected between 5v and RB0". What is the normal state of RB0? I don't see how it can ever be anything but high.
If you connect the switch to Gnd and enable the pullups on PortB, I'd be a lot happier.
Oh yes, and bouncing in the switch. I believe you'd be much better off not using an interrupt for the switch at all: an easy alternative is to just set up TMR1 to run at some slow rate and in your main() loop, poll the overflow flag. Any time the flag is found to be set, clear it and read the switch.
It looks as if a prescaler value of 1 gives a wrap rate of 15Hz with the internal oscillator, but if that's too slow, just add some amount to TMR1H at the same time as clearing the interrupt flag. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sun Jul 21, 2013 3:28 am |
|
|
Agreed.
I had missed the lack of mention of any resistor on the input, because the post talks about a resistor immediately before this part, but this is the one pulling up MCLR.....
As you say, much simpler, to have the button pulling down, and enable the weak pull up on RB0, and set the interrupt to trigger on the falling edge.
In fact 'falling' is the default setting for this interrupt, so if the pin floats high, the button will never be seen. Count will then sit at 255 (since it is unsigned, and this is what -1 codes as if put into an unsigned int8), and none of the PWM settings will ever be called. The output will just sit high and never change....
Best Wishes |
|
|
|
|
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
|