Continue to Site

SPWM duty cycle update using CCP1 & TMR1 in pic16C73

codemaster11

Full Member level 2
Full Member level 2
Joined
Sep 2, 2019
Messages
122
Helped
9
Reputation
18
Reaction score
7
Trophy points
18
Activity points
1,276
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?


Capture.JPG
 
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.
 
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
1736096324801.png
 
PIC16F73 is a mid range MCU. When you assign mathematical calculation, it will take considerable time to perform. Using higher frequency XTL causes higher speed in execution of instructions. Hence using lower frequency XTL will cause decrease of PWM Frequency. For such purpose, dsPIC is suitable where a dedicated dsp engine is available that can perform mathematical calculations at very faster speed.
 
Following on from @swapan' comment, on these small MCUs avoid floating point maths at all costs.
Not only does it bring in a lot of floating point library code (you only have 4K FLASH) but that codes takes (lots of) time to execute.
In nearly every case you can instead use scaled integers instead. These still have issues (when you try to use more than 8 bits) but are many times faster that the floating point library code.
(In the code you show I can't see where you use floating point arithmetic - I assume that will come later.)
Susan
 
i tried to implement feedback using Analog pin with 16c73. try it with 300vdc bus input to a ready made transformerless inverter pcb.
it starts with Vout = 250vac to 290vac, continiously fluctuation in this range, show loading with series light without any load.
i shift it from pic16c73 to atmega328 as atmega328 is much faster. still the loading problem arise. below is link to my post
related loading effect of transformer less inverter. this not my own code but an open source. i did't diagnose why my atmega328 also cause loading
effect.

https://www.edaboard.com/threads/tr...ac-inverter-loading-without-real-load.414100/
 


Write your reply...

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top