SPWM duty cycle update using CCP1 & TMR1 in pic16C73

codemaster11

Advanced Member level 4
Joined
Sep 2, 2019
Messages
118
Helped
9
Reputation
18
Reaction score
7
Trophy points
18
Visit site
Activity points
1,262
const unsigned char sine_table [73] = {0, 6, 12, 18, 24, 29, 31, 35, 41, 46, 52, 57, 63, 68, 73, 78, 83,
87, 92, 96, 100, 104, 108, 112, 115, 118, 121, 124, 126, 128, 130, 132, 133, 136, 136, 137,
137, 136, 135, 134, 133, 131, 129, 127, 125, 123, 120, 117, 114, 110, 107, 103, 99, 94, 90, 86, 81,
76, 71, 66, 61, 55, 50, 44, 38, 33, 27, 21, 15, 9, 3, 0};

int duty = 0;
bit P1M1_invert;
float feedback = 1.00; //max dutycycle.----->Duty cycle = 100%
int k = 0; unsigned int ac_volt = 0;
float vAD = 0.0;


void InitTimer1(){
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0xFD;
TMR1L = 0xE8;
TMR1IE_bit = 1;
INTCON = 0xC0;


}







void Interrupt () iv 0x0004 ics ICS_AUTO {

if(TMR1IF_bit) //timer1 overflow ---> 134usec.
{
TMR1IF_bit = 0;
TMR1H = 0xFD;
TMR1L = 0xE8;

duty++;
if(duty >= 73)
{
duty = 0;
P1M1_invert = ~P1M1_invert;
//CCPR1L = 0;
asm nop;
asm nop;

}


if(P1M1_invert)
{

RC0_bit = 1;
RC1_bit = 1;
RC3_bit = 0;
RC4_bit = 0;
PWM1_Set_Duty(sine_table[duty]);
}

else
{
RC0_bit = 0;
RC1_bit = 0;
RC3_bit = 1;
RC4_bit = 1;
PWM1_Set_Duty(sine_table[duty]);
}

}

}


void main()
{
//configure analog channle 4.


TRISC = 0;
PORTC = 0;


PWM1_Init(20000);//initialize at 20KHz
PWM1_Start();

InitTimer1();
//duty = 0;

while(1)
{
//feedback control code flow.


}


}

above mikroC code generate SPWM using only CCP1 with "7408 AND gate ic " making it to work as two CCP.
TMR1 is use to generate 50Hz setting XTAL = 16MHz with interrupt overflow 134usec. here the simulation show 49 or 50Hz fine with
sine_table of 73 values . here a problem of how to update SPWM duty cycle using a variable resistor at analog pin?


 

problem of how to update SPWM duty cycle
Change each and every value in your data table by some percentage (longer or shorter). Realistically you'll multiply every value by some coefficient just before you send a pulse to your output stage.

You probably wish to dial the variable resistor (potentiometer) to change a voltage setting somewhere. Read this voltage and convert it mathematically to a usable coefficient.
 

    codemaster11

    Points: 2
    Helpful Answer Positive Rating
PWM1_Set_Duty(sine_table[duty] x coefficient); <--------- you say to write it as. i tried this method by putting a constant value to check whether
it is changing duty cycle or not but another problem arise that is sine wave frequency drooped to about 10Hz from 50Hz in Proteus simulation by putting
constant value like this PWM1_Set_Duty(sine_table[duty] x 0.8 );
 

An oscilloscope can confirm what's causing the slowdown, whether it's a result of hardware function or of code execution. If it happened to me I'd think I was packing too many calculations in each cycle.
It could be a matter of reducing the number of samples per cycle.
Or taking up some cpu cycles to calculate updated duty values and write them into memory just once.
Or scraping for any and every shortcut that lets you hold to your desired 50 Hz.

Sorry I have no hands-on experience with mikroC.
 

"It could be a matter of reducing the number of samples per cycle."
reducing number of total samples to 34 works keep output sine frequency constant at XTAL = 16MHz but not work at XTAL = 4MHz, 8MHz, or 12MHz
even by calculating interrupt time using mikroC timer calculator. don't know why frequency drop occure while calculating according to above crystal
frequencies
for 73 values for half cycle = 10msec
 

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…