CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

16f628a PWM and internal osc

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
itsbasix



Joined: 23 May 2012
Posts: 8

View user's profile Send private message

16f628a PWM and internal osc
PostPosted: Fri Jul 19, 2013 8:05 am     Reply with quote

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: 19504

View user's profile Send private message

PostPosted: Fri Jul 19, 2013 8:31 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 19, 2013 8:50 am     Reply with quote

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: 19504

View user's profile Send private message

PostPosted: Fri Jul 19, 2013 9:59 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Fri Jul 19, 2013 11:36 am     Reply with quote

Code:

#use delay(clock=48000)


is this for real?

if so you have a .012 MIPS processor flaming away Very Happy Very Happy Very Happy
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Fri Jul 19, 2013 12:49 pm     Reply with quote

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: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 19, 2013 1:54 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Jul 20, 2013 4:58 pm     Reply with quote

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: 19504

View user's profile Send private message

PostPosted: Sun Jul 21, 2013 3:28 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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