Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

External Sync signal issue in PIC16F676 using mikroc.

Status
Not open for further replies.

djc

Advanced Member level 1
Joined
Jan 27, 2013
Messages
402
Helped
3
Reputation
6
Reaction score
2
Trophy points
1,298
Location
India
Activity points
4,554
Hi,
I have written a code for PIC16F676 and mikroc where i have to drive an H bridge. Where one IGBT in upper half of the bridge will be ON for 10ms and corresponding diagonally opposite IGBT will get switched with PWM pulses to generate half cycle of sine wave. similarly for next 10ms of remaining sine wave another IGBT in upper half of another wing will be ON and corresponding diagonally opposite IGBT will be switched with PWM pulses. PWM is generated by Timer0 with 2Khz frequency and 10ms interrupt is generated by Timer1. This is all done. Now there is an external sync pulse of 50Hz on external interrupt pin i.e. RA2. I have configured it as rising edge interrupt. Whenever timer1 interrupt will occur timer0 interrupt starts and timer0 interrupt will stop when complete half cycle of sine wave is done. Code is as follows.
Code:
#define channel_1 PORTC.B0
#define channel_2 PORTC.B1
#define channel_3 PORTC.B2
#define channel_4 PORTC.B3

unsigned char OnPulse = 0;
unsigned char OffPulse = 0;
char TOG = 0,Flag=0,Tenms=0,Sync=0,valid=1;
unsigned int i = 0,j=0,i_1=0,n=0;
bit k,m,k_1,m_1;

const unsigned char sine2[22]={2,22,42,75,100,115,140,150,160,170,182,185,183,180,165,140,115,100,75,42,22,2};
const unsigned char sine3[22]={2,22,42,75,100,115,140,150,160,170,182,185,183,180,165,140,115,100,75,42,22,2};

Port_Control(){
CMCON        = 0x07;
OSCCAL       = 0b11111100;
ANSEL         = 0;
TRISA         = 0b00000100;  //PortA as output
TRISC         = 0x00;           //PortC as output
PORTC        = 0x00;           //Initial value on PortC
INTE_bit      = 1;
INTEDG_bit   = 1;
}
Timer0_Control(){
T0IF_bit = 0;
TMR0     = 0;
T0CS_bit = 0;
PSA_bit  = 0;  //Prescaler is assigned to Timer0 module
PS0_bit  = 0;  //TMR0 rate 1:2
PS1_bit  = 0;
PS2_bit  = 0;
}

Timer1_Control(){
INTCON        = 0b11000000;
PIR1.TMR1IF   = 0;
TMR1GE_bit    = 0;
T1CON.T1CKPS0 = 0;          //1:1 prescale value
T1CON.T1CKPS1 = 0;          //1:1 prescale value
T1CON.TMR1CS  = 0;           //Internal clock Fosc/4
T1CON.TMR1ON  = 0;
PIE1.TMR1IE   = 1;
TMR1L         = 0x00;
TMR1H         = 0xc8;
T1CON.TMR1ON  = 1;
}

void interrupt(){

     if(INTF_bit){            //50hz square wave
     INTF_bit = 0;
    
     if(Sync==3){
     INTCON = 0b11000000;
     INTE_bit= 1;
     Sync=0;
     }
     }

 
     if(PIR1.TMR1IF){          //10ms on/off
     PIR1.TMR1IF = 0;
     Sync=Sync+1;
     if(Sync==3){INTCON  = 0b10000000;INTE_bit= 1;}
     Tenms = Tenms+1;
              if(Tenms  ==1){
              INTCON   = 0b11100000;  //timer0 on
              T0CS_bit = 0;
              channel_1 = 1;
              channel_3 = 0;

              channel_2 = 0;
              channel_4 = 0;
              k=1;
              m=0;
              }
              else{
              INTCON   = 0b11100000;//timer0 on
              T0CS_bit = 0;
              //INTE_bit= 1;
              Sync=0;
              channel_1 = 0;
              channel_3 = 1;

              channel_2 = 0;
              channel_4 = 0;
              Tenms = 0;
              k=0;
              m=1;
              }
     TMR1L = 0x00;
     TMR1H = 0xc8; //c8,e4
     }

if(INTCON.T0IF){           //PWM Signal,2Khz
     TMR0 = 0;
     Flag=1;
     //channel_1 = ~channel_1;
     if(k==1){
     if(TOG==1){
     Tmr0 =  OffPulse;
     channel_2= 1;
     Tog=0;
     }

     else{
     Tmr0 =  OnPulse;
     channel_2 = 0;
     Tog=1;
     }
     }
     
     if(m==1){
     if(TOG==1){
     Tmr0 =  OffPulse;
     channel_4= 1;
     Tog=0;
     }

     else{
     Tmr0 =  OnPulse;
     channel_4 = 0;
     Tog=1;
     }
     }
   T0IF_bit = 0;
    }
}

void main() {
     Port_Control();
     Timer0_Control();
     Timer1_Control();

                 while(1){
                 
                 if(Flag==1){
                 if(k==1){
                  OnPulse = sine2[j++];
                 OffPulse = 255-OnPulse;
                 Flag=0;
                 if(j>21){T0CS_bit = 1;/*INTCON = 0b11000000;*/ j =0;}    //Timer0 off
                 }
                 
                 if(m==1){
                  OnPulse = sine3[i++];
                 OffPulse = 255-OnPulse;
                 Flag=0;
                 if(i>18){T0CS_bit = 1;/*INTCON = 0b11000000;*/i =0;}     //Timer0 off
                 }
                 }
                 }
}

Now my problem is i want to switch off both the timers when complete sine wave is generated for both the wings and turn it ON back when external sync signal reappears, which is a zero crossing detection signal. If no external sync is there system should remain OFF. Here 'Sync' variable doesn't seems to be working. means when Sync is equal to 3 it means that a complete sine wave for both cycle has been created and shut all the interrupts off with INTE_bit = 1; enabled for external sync signal to be only active. Now when external sync is there turn all the interrupts on again.But in my code either sine wave gets distorted or external sync doesn't affect at all.Where is the actual mistake. Can anybody plz guide me.
 

Firstly, any variable that is altered within an ISR should be declared as volatile.
In your ISR, you should always check for BOTH the IE and IF bits and not just the IF bits.
The reason is that you have a single ISR in that MCU. Also the IF bit for an interrupt source can be set even if the IE bit is not. The ISR is triggered only by a source with both the IE and IF bits set.
Imagine the case where (say) timer 1 is running and has its IE bit set. Also Timer 0 is running but has its IE bit clear. At some time, Timer 0 is going to roll over from 0xff to 0x00 and therefore set its IF bit. However because its IE bit is clear the ISR will not be called.
Now, when the Timer 1 rolls over from 0xffff to 0x0000, it will set its IF bit. In this case, because its IE bit is set, the ISR will be triggered.
So, at the start of the ISR bit Timer 0 and Timer 1 will have their IF bits set.
The way you have written the ISR, you will execute the code for BOTH Timer 0 and Timer 1. To stop the Timer 0 code being incorrectly executed, you need to test both the IE and IF bits.
As an aside, why do you not use a device with a PWM peripheral built in? Let the hardware do all of the hard work for you.
Finally, I would suggest that you don't keep playing with the whole of the INTCON register. Set the GIE and PEIE as part of your initialisation code and then turn on and off the IE bits of the various peripherals as you need them.
Regardless, you should never alter the GIE bit (or the PEIE bit for that matter) in an ISR. The hardware will control this bit around the ISR for you and you should not interfere with this.
Susan
 
  • Like
Reactions: djc

    djc

    Points: 2
    Helpful Answer Positive Rating
Thanx susan

Playing with IE bits instead of GIE and PEIE bits seems to be working. Sync variable is made volatile. Now it is working with the external sync signal. But one more issue is there. Sine wave of one wing is little straight at the starting then takes a little dip and start increasing again. So for that i decreased sine table values for another wing. Means if for first wing sine array is 21, for another wing i kept it 18. That helped in decreasing starting straightness of first sine wave. But i still want to make it a complete sine wave.
 

Are you eventually going to have different values ion 'sine2' and 'sine3'? If not the why not simply use the same array.
Looking at your sine table, it should be symmetric (i.e. the number 'n' in from the left should be the same as the number 'n' in from the right) but it is not in the middle (150,160,170,182,185,183,180,165). This will cause some distortions.
What you can do is to generate the numbers for a quarter of the cycle and then, using a technique very similar to the one you already do, just scan the index pointer back and forwards - forward for the first quarter cycle, back for the second and so on.
As a general comment, be very careful of consecutive statements that change different bits in the same PORT register. This can leave very easily to the 'read-modify-write' problem (RMW). A better way on these old MCUs (which don't that LAT registers that overcome this for you) is to have a variable that you update and then write the whole thing to the PORT register - this is referred to as a shadow register in some of the RMW descriptions.
I've not tried to understand the logic you are using but I get the suspicion that it is more complex than it needs to be and this might be what is behind the asymmetry you are seeing.
Try setting things up for just one signal and get that right. Then you can extend what you have to the other signal(s) that you want.
Susan
 
  • Like
Reactions: djc

    djc

    Points: 2
    Helpful Answer Positive Rating
Hi susan.
Thanx again for your valuable guidelines. I did indexing the sine array back and forwards. It seems to be working till now(coz ADC has to be incorporated.) Now no glitch is there in any of the sine wave. Both are symmetric and external sync is also working. Thanx a lot. Code is as follows.
Code:
const unsigned char sine4[11]={2,40,80,105,130,150,160,170,180,185,190};

if(Flag==1){
                 if(k==1){
                 OnPulse = sine4[j];
                 OffPulse = 255-OnPulse;
                 Flag=0;
                 if(up==1){
                 j++;
                 if(j==10){up=0;}
                 }
                 else{
                 j--;
                 if(j==0){T0CS_bit = 1;up=1;}
                 }
                 }

                 if(m==1){
                 OnPulse = sine4[i];
                 OffPulse = 255-OnPulse;
                 Flag=0;
                 if(down==1){
                 i++;
                 if(i==10){down=0;}
                 }
                 else{
                 i--;
                 if(i==0){T0CS_bit = 1;down=1;}
                 }
                 }
                 }
                 }

Sine table is different for this code. Yes i thought of using different sine tables for each incoming external sync signal however single sine table for both the wings at one time. That i did in this code. Now channel_1 and channel_3 which are PORTC.B0 and PORTC.B2 are getting turn ON and OFF alternately at each 10 ms interrupt of timer 1. Now though i took care of switching all the port pins OFF after every timer interrupt, somehow any of the two port pins i.e. either channel_1 or channel_2 remain ON whenever i remove external sync signal. All this testing is done on EasyPic5 development board.Why port pin is remaining high?
 

If you are using the same code in the ISR, then you need to look at my comments about RMW which I suspect could cause port pins to not be set to the value you expect.
Susan
 

Hi susan,
Thanx for your valuable guidance. I switched off the port pins in the end of timer 1 interrupt instead of starting. That solved the issue.

Regards
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top