View previous topic :: View next topic |
Author |
Message |
Levism
Joined: 02 Aug 2015 Posts: 3
|
PWM Generation-Help |
Posted: Sun Aug 02, 2015 12:15 pm |
|
|
Hello Gentlemen,
I am trying to create a program that allows a PIC16F876 to receive 0-5v from a 10k potentiometer through RA0. It converts this to a 1khz pwm signal that comes out of CCP1 and can have its duty cycle changed from 0 to 100% depending on the voltage received in RA0. I am very new to programing, having only a few class code samples and my recent studies to rely on. Below is the code I have come up with so far. When I test the .HEX on Proteus the Hz reading I get does not vary much from 252 Hz at all times, even when I tinker with the potentiometer. I would very much appreciate any insight as to how I can accomplish my goal.
Thanks in advance.
Code: |
#include <16f876.h>
#device ADC=8
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP
int conta=0;
int resultado=0;
long int ciclo=0;
int conv=0;
//--------------------------------------------------------------------
#INT_TIMER0
void trata_t0() {
resultado = read_adc( );
conv=resultado/4;
set_timer0(get_timer0());
conta++;
if (conta==31) {
conta=0;
}
}
//---------------------------------------------------------------
void main (){
SETUP_ADC_PORTS(RA0_ANALOG);
setup_ADC(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
setup_timer_2 (T2_DIV_BY_16, 61, 1);
setup_ccp1 (ccp_pwm);
set_pwm1_duty ( 0 );
while(true){
for (ciclo=0; ciclo<conv; ciclo++){
set_pwm1_duty (ciclo);
delay_ms(50);
}
delay_ms(1000);
}
} |
_________________ Life is but dust. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Aug 02, 2015 1:18 pm |
|
|
Quote: |
the Hz reading I get does not vary much from 252 Hz at all times, even
when I tinker with the potentiometer
|
set_pwm1_duty() does not change the PWM frequency. It changes
the duty cycle. Example:
http://d32zx1or0t1x0y.cloudfront.net/2011/06/atmega168a_pwm_02_lrg.jpg
The frequency is constant but the duty cycle (pulse width) changes. |
|
![](templates/subSilver/images/spacer.gif) |
Levism
Joined: 02 Aug 2015 Posts: 3
|
Yes |
Posted: Sun Aug 02, 2015 1:34 pm |
|
|
Thank you for pointing that out for me sir!
Now I realize that I need to get this frequency up to 1khz, for some reason I was mixing frequency with cycle in my mind. To do this I need to change the period in timer 2 correct?
setup_timer_2 (T2_DIV_BY_16, 61, 1);
I will try to measure the cycle and see what I got. _________________ Life is but dust. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Sun Aug 02, 2015 1:40 pm |
|
|
Change the prescaler. If you change the period value, the PWM resolution will change. |
|
![](templates/subSilver/images/spacer.gif) |
Levism
Joined: 02 Aug 2015 Posts: 3
|
Thanks for all the help! |
Posted: Sun Aug 02, 2015 2:03 pm |
|
|
I got it guys, changed a few things as recommended!
Below is my final code:
Code: |
#include <16f876.h>
#device ADC=8
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP
int conta=0;
int resultado=0;
long int ciclo=0;
int conv=0;
//--------------------------------------------------------------------
#INT_TIMER0
void trata_t0() {
resultado = read_adc();
set_timer0(get_timer0());
conta++;
if (conta==31) {
conta=0;
}
}
//---------------------------------------------------------------
void main (){
SETUP_ADC_PORTS(RA0_ANALOG);
setup_ADC(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
setup_timer_2 (T2_DIV_BY_4, 61, 1);
setup_ccp1 (ccp_pwm);
set_pwm1_duty ( 0 );
while(true){
for (ciclo=0; ciclo<resultado; ciclo++){
set_pwm1_duty (ciclo);
delay_ms(50);
}
delay_ms(1000);
}
}
|
Thanks again for the great tips! _________________ Life is but dust. |
|
![](templates/subSilver/images/spacer.gif) |
|