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.

PIC18F4431 PCPWM - Signals are not good. Why ?

Status
Not open for further replies.

Okada

Banned
Joined
Jun 16, 2016
Messages
1,159
Helped
129
Reputation
252
Reaction score
129
Trophy points
63
Activity points
0
I am using PIC18F4431 with 16 MHz Crystal and using its PCPWM module to generate 3 Phase SPWM signals but signals are not good. Please see attached Simulation Video for Signals. Also Proteus file is included.

This is the code. The only doubt that I am having is ISR code is taking more than 62.5us to execute once but even if this is true then PWM0, 1, 2, 3 should be good but they are also not good.

I see signal shifting and when signals reach PWM duty 0 it suddenly becomes pwm duty 100%.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* 
 * File:   main.c
 * Author: Okada
 *
 * Created on March 1, 2017, 4:51 PM
 */
 
#define _XTAL_FREQ 16000000
 
#include <xc.h>
#include <p18f4431.h>
#include <stdio.h>
#include <stdlib.h>
 
#pragma config OSC      = HS                    
#pragma config FCMEN    = ON
#pragma config IESO     = OFF
#pragma config OSC      = HS
#pragma config DEBUG    = OFF                   
#pragma config LVP      = OFF                   
#pragma config PWRTEN   = ON                    
#pragma config WDTEN    = ON                    
#pragma config WDPS     = 2048
#pragma config WINEN    = OFF
#pragma config MCLRE    = ON                    
#pragma config BOREN    = ON                     
#pragma config BORV     = 42
#pragma config PWMPIN   = OFF                   
#pragma config LPOL     = HIGH                  
#pragma config HPOL     = HIGH                  
#pragma config T1OSCMX  = OFF
#pragma config STVREN   = ON
#pragma config CP0      = OFF
#pragma config CP1      = OFF
#pragma config CPB      = OFF
#pragma config CPD      = OFF
#pragma config WRT0     = OFF
#pragma config WRT1     = OFF
#pragma config WRTC     = OFF
#pragma config WRTB     = OFF
#pragma config WRTD     = OFF
#pragma config EBTR0    = OFF
#pragma config EBTR1    = OFF
#pragma config EBTRB    = OFF
 
/*
 * pwm resolution = log((1*FOSC)/Fpwm) / log(2)
 */
 
unsigned int sine_table[32] = {
                                0,9,37,83,144,218,302,394,490,586,678,762,836,897,943,971,
                                980,971,943,897,836,762,678,586,490,394,302,218,144,83,37,9
                              };
 
unsigned int TBL_POINTER_NEW[3]   = {0, 0, 0};
unsigned int TBL_POINTER_OLD[3]   = {0, 0, 0};
unsigned int TBL_POINTER_SHIFT[3] = {0, 0, 0};
unsigned char DUTY_CYCLE[3]       = {0, 0, 0};
unsigned int SET_FREQ = 410;
 
//Timer2
//Prescaler 1:1; Postscaler 1:1; TMR2 Preload = 249; Actual Interrupt Time : 62.5 us
void InitTimer2() {
  T2CON = 0x04;
  PIE1bits.TMR2IE = 1;
  PR2 = 249;
  INTCON = 0xC0;
}
 
void interrupt isr(){
  if((PIE1bits.TMR2IE) && (PIR1bits.TMR2IF)) { 
      //Enter your code here
      
      //SET_FREQ = 65536 / (32 * 5) = 410
      //Required AC Frequency = 50 Hz
      //PWM frequency = 16KHz
      //Tpwm = 1/16KHz = 62.5us  (Timer2 Interrupt Period)
      //62.5us * 32 * 5 = 10ms (for 180 degrees)
      //10ms * 2 = 20ms
      //AC frequency = 1/20ms = 50.0Hz
 
      TBL_POINTER_NEW[0] = TBL_POINTER_OLD[0] + SET_FREQ;
 
      TBL_POINTER_SHIFT[0] = TBL_POINTER_NEW[0] >> 11;
      DUTY_CYCLE[0] = TBL_POINTER_SHIFT[0];
 
      //Assign PWM duty 10 bit
      PDC0L = sine_table[DUTY_CYCLE[0]];
      PDC0H = sine_table[DUTY_CYCLE[0]] >> 8;
 
      TBL_POINTER_OLD[0] = TBL_POINTER_NEW[0];
      
 
      TBL_POINTER_NEW[1] = TBL_POINTER_OLD[1] + SET_FREQ;
 
      TBL_POINTER_SHIFT[1] = TBL_POINTER_NEW[1] >> 11;
      DUTY_CYCLE[1] = TBL_POINTER_SHIFT[1];
 
      if((DUTY_CYCLE[1] + 21) < 32)DUTY_CYCLE[1] += 21;
      else DUTY_CYCLE[1] -= 11;
 
      //Assign PWM duty 10 bit
      PDC1L = (sine_table[DUTY_CYCLE[1]]);
      PDC1H = sine_table[DUTY_CYCLE[1]] >> 8;
      
      TBL_POINTER_OLD[1] = TBL_POINTER_NEW[1];
 
 
      TBL_POINTER_NEW[2] = TBL_POINTER_OLD[2] + SET_FREQ;
 
      TBL_POINTER_SHIFT[2] = TBL_POINTER_NEW[2] >> 11;
      DUTY_CYCLE[2] = TBL_POINTER_SHIFT[2];
 
      if((DUTY_CYCLE[2] + 10) < 32)DUTY_CYCLE[2] += 10;
      else DUTY_CYCLE[2] -= 21;
 
      //Assign PWM duty 10 bit
      PDC2L = (sine_table[DUTY_CYCLE[2]]);
      PDC2H = sine_table[DUTY_CYCLE[2]] >> 8;
      
      TBL_POINTER_OLD[2] = TBL_POINTER_NEW[2];     
      
      PIR1bits.TMR2IF = 0;    
  }
}
 
 
int main(int argc, char** argv) {
 
    asm("CLRWDT");
    
    ANSEL0 = 0x00;
    ANSEL1 = 0x00;
     
    TRISA = 0xC0;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISD = 0x00;
    TRISE = 0x00;
 
    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;
 
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;
    
    PTCON0 = 0x20; 
    
    PWMCON0 = 0x40; 
    PWMCON1 = 0x01;
 
    DTCON = 0x84;          
 
    OVDCOND = 0xFF;     
 
    OVDCONS = 0xFF;     
 
    FLTCONFIG = 0x00;   
 
    //PTPER = ((Tpwm * Fosc/4) / PTMRPS) - 1
    //PTMRPS = 1:1 = 1
    //Tpwm = 62.5us, 16 KHz Fpwm
    //((62.5u * 16000000/4) / 1) - 1
    PTMRL = 0xF9;       
    PTMRH = 0x00;          
 
    PTPERL = 0xF9;         
    PTPERH = 0x00;         
 
    SEVTCMPL = 0x00;
    SEVTCMPH = 0x00;
        
    InitTimer2();
    
    PTCON1 = 0x80; 
    
    while(1) {
        
        asm("CLRWDT");
    }
     
    return (EXIT_SUCCESS);
}

 

Attachments

  • Three Phase Inverter.X.rar
    460.5 KB · Views: 124

I do not have MPLABX with me at the moment but my first thoughts are to check PDCxL and PDxH are being loaded with the correct 8 and 2 bit values.

I think you can simplify the code by making the three index values in a seperate loop as they simply chase each other in a 0->32 circle. At the moment you seem to be reading the array several times to make a single calculation which is inefficient and slower.

Brian.
 

I am using Tahmid's method. For me there is a need to vary the Sinewave frequency a little and hence I have used Tahmid's method.

sine table values are correct.

My crystal frequency is 16 MHz and PWM frequency is 16 KHz and so

pwm resolution is

= log10(Fosc/Fpwm)/log10(2)

= log10(16MHz/16KHz)/log(2)

= 9.965784 bits

2^9.965784 = 999.998

98% of 999.9998 = 979.999 = 980

You can see in my sine table that 980 is the highest value.


I have one doubt. In PIC18F4431 PCPWM there is center aligned and edge aligned PWM. What is it ? Does it come into consideration in free running mode ?
 
Last edited:

By referring page no. 187 of PIC datasheet I made below changes in ISR code.

Code:
PDC0L = (PDC0L & 0x03) | sine_table[DUTY_CYCLE[0]] << 2;
PDC0H = sine_table[DUTY_CYCLE[0]] >> 6;

Edit:

Also made this change

Code:
PTCON0 = 0x00;

Still not getting good signals but the sliding of signals has stopped. Even now when PWM duty reaches 0 it becomes 100% duty for a short period.

- - - Updated - - -

I am not able to understand what is mentioned in page no. 187 of PIC18F4431 datasheet 18.6.1 section.

It says that PDCxL and PDCxH are loaded from PTPERL and PTPERH. I don't understand this.

For me PTPERL is 0xF9

PTPER = ((Tpwm * Fosc/4) / PTMRPS) - 1
PTMRPS = 1:1 = 1
Tpwm = 62.5us, 16 KHz Fpwm
((62.5u * 16000000/4) / 1) - 1

= (1000/4) - 1)

= 250 - 1 = 249 = 0xF9

I am loading sine table which is a 10 bit value to PDCx registers.

Please explain what is mentioned in page 187 of datasheet.
 
Last edited:

I must admit I can't see the text you are commenting on in section 18.6.1 but 18.6.2 does say that the duty cycle registers are double-buffered and Figure 18-12 does how the impact of changing the duty cycle.
Some comments on your code:
- get rid of all of the #includes except the <hc.h>
- turn off the WDT (at least for now); if you really DO need to turn it on again then don't keep resetting it in the main 'while' loop: as you have nothing else in the main 'while' and there are no loops in the ISR, there is no place where you can realistically get 'stuck'.
A personal comment: I don't really like having a lot of code in the initialisation of the device that just sets registers to their power on reset values (e.g. TRISB= 0) as it just adds code that you need to write, you (or someone else) needs to debug and the processor needs to execute.
Susan
 

Ok Susan. Here is the new code. I am still not getting good signals. PWM2 and PWM3 are sliding. All PWMs when they reach 0 the suddenly become 100% duty for a short period.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* 
 * File:   main.c
 * Author: Okada
 *
 * Created on March 1, 2017, 4:51 PM
 */
 
#define _XTAL_FREQ 16000000
 
#include <xc.h>
 
#pragma config OSC      = HS                    
#pragma config FCMEN    = ON
#pragma config IESO     = OFF
#pragma config OSC      = HS
#pragma config DEBUG    = OFF                   
#pragma config LVP      = OFF                   
#pragma config PWRTEN   = ON                    
#pragma config WDTEN    = OFF                    
#pragma config WDPS     = 2048
#pragma config WINEN    = OFF
#pragma config MCLRE    = ON                    
#pragma config BOREN    = ON                     
#pragma config BORV     = 42
#pragma config PWMPIN   = OFF                   
#pragma config LPOL     = HIGH                  
#pragma config HPOL     = HIGH                  
#pragma config T1OSCMX  = OFF
#pragma config STVREN   = ON
#pragma config CP0      = OFF
#pragma config CP1      = OFF
#pragma config CPB      = OFF
#pragma config CPD      = OFF
#pragma config WRT0     = OFF
#pragma config WRT1     = OFF
#pragma config WRTC     = OFF
#pragma config WRTB     = OFF
#pragma config WRTD     = OFF
#pragma config EBTR0    = OFF
#pragma config EBTR1    = OFF
#pragma config EBTRB    = OFF
 
/*
 * pwm resolution = log((1*FOSC)/Fpwm) / log(2)
 */
 
unsigned int sine_table[32] = {
                                //0,9,37,83,144,218,302,394,490,586,678,762,836,897,943,971,
                                //980,971,943,897,836,762,678,586,490,394,302,218,144,83,37,9
                                0,10,38,84,146,222,309,402,500,598,691,778,854,916,962,990,
                                999,990,962,916,854,778,691,598,500,402,309,222,146,84,38,10
                              };
 
unsigned int TBL_POINTER_NEW[3]   = {0, 0, 0};
unsigned int TBL_POINTER_OLD[3]   = {0, 0, 0};
unsigned int TBL_POINTER_SHIFT[3] = {0, 0, 0};
unsigned char DUTY_CYCLE[3]       = {0, 0, 0};
unsigned int SET_FREQ = 410;
 
//Timer2
//Prescaler 1:1; Postscaler 1:1; TMR2 Preload = 249; Actual Interrupt Time : 62.5 us
void InitTimer2() {
  T2CON = 0x04;
  PIE1bits.TMR2IE = 1;
  PR2 = 249;
  INTCON = 0xC0;
}
 
void interrupt isr(){
  //if((PIE1bits.TMR2IE) && (PIR1bits.TMR2IF)) { 
  if(PIR3bits.PTIF) { 
      //Enter your code here
      
      //SET_FREQ = 65536 / (32 * 5) = 410
      //Required AC Frequency = 50 Hz
      //PWM frequency = 16KHz
      //Tpwm = 1/16KHz = 62.5us  (Timer2 Interrupt Period)
      //62.5us * 32 * 5 = 10ms (for 180 degrees)
      //10ms * 2 = 20ms
      //AC frequency = 1/20ms = 50.0Hz
 
      TBL_POINTER_NEW[0] = TBL_POINTER_OLD[0] + SET_FREQ;
 
      TBL_POINTER_SHIFT[0] = TBL_POINTER_NEW[0] >> 11;
      DUTY_CYCLE[0] = TBL_POINTER_SHIFT[0];
 
      //Assign PWM duty 10 bit
      //PDC0L = (PDC0L & 0x03) | sine_table[DUTY_CYCLE[0]] << 2;
      //PDC0H = sine_table[DUTY_CYCLE[0]] >> 6;
      PDC0L = sine_table[DUTY_CYCLE[0]];
      PDC0H = sine_table[DUTY_CYCLE[0]] >> 8;
                 
      TBL_POINTER_OLD[0] = TBL_POINTER_NEW[0];
      
      
      TBL_POINTER_NEW[1] = TBL_POINTER_OLD[1] + SET_FREQ;
 
      TBL_POINTER_SHIFT[1] = TBL_POINTER_NEW[1] >> 11;
      DUTY_CYCLE[1] = TBL_POINTER_SHIFT[1];
 
      if((DUTY_CYCLE[1] + 21) < 32)DUTY_CYCLE[1] += 21;
      else DUTY_CYCLE[1] -= 11;
 
      //Assign PWM duty 10 bit
      //PDC1L = (PDC1L & 0x03) | sine_table[DUTY_CYCLE[1]] << 2;
      //PDC1H = sine_table[DUTY_CYCLE[1]] >> 6;
      PDC1L = sine_table[DUTY_CYCLE[1]];
      PDC1H = sine_table[DUTY_CYCLE[1]] >> 8;
      
      TBL_POINTER_OLD[1] = TBL_POINTER_NEW[1];
 
      
      TBL_POINTER_NEW[2] = TBL_POINTER_OLD[2] + SET_FREQ;
 
      TBL_POINTER_SHIFT[2] = TBL_POINTER_NEW[2] >> 11;
      DUTY_CYCLE[2] = TBL_POINTER_SHIFT[2];
 
      if((DUTY_CYCLE[2] + 10) < 32)DUTY_CYCLE[2] += 10;
      else DUTY_CYCLE[2] -= 21;
 
      //Assign PWM duty 10 bit
      //PDC2L = (PDC2L & 0x03) | sine_table[DUTY_CYCLE[2]] << 2;
      //PDC2H = sine_table[DUTY_CYCLE[2]] >> 6;
      PDC2L = sine_table[DUTY_CYCLE[2]];
      PDC2H = sine_table[DUTY_CYCLE[2]] >> 8;
      
      TBL_POINTER_OLD[2] = TBL_POINTER_NEW[2];     
            
      PIR1bits.TMR2IF = 0;
      PIR3bits.PTIF = 0;
  }
}
 
 
int main(int argc, char** argv) {       
    
    TRISA = 0xC0;
        
    PTCON0 = 0x00; 
    
    PWMCON0 = 0x40; 
    PWMCON1 = 0x01;
 
    DTCON = 0xC8;          
 
    OVDCOND = 0xFF;     
 
    OVDCONS = 0xFF;     
 
    FLTCONFIG = 0x00;   
 
    //PTPER = ((Tpwm * Fosc/4) / PTMRPS) - 1
    //PTMRPS = 1:1 = 1
    //Tpwm = 62.5us, 16 KHz Fpwm
    //((62.5u * 16000000/4) / 1) - 1
    
    PTPERL = 0xF9;         
    PTPERH = 0x00;         
 
    SEVTCMPL = 0x00;
    SEVTCMPH = 0x00;
        
    InitTimer2();
    
    PTCON1 = 0x80; 
    
    while(1) {        
        
    }
     
    return (0);
}

 

But isn't PDCx is of 14 bit resolution?? 8 for PDCxL and 6 for PDCxH.
Data sheet also says : " PDCx is a double buffered register used to set the counting period for PWM time base"
 

I have some questions:
1> Why did you divided PDCxH by 2^8
2> What is the purpose of : int argc and char** argv in int main( int argc and char** argv)
3> and why did you use:
asm("CLRWDT")
...
while(1){
asm("CLRWDT")
}
4) If I use different PR2 value if I want different set of frequency?
5> I didn't understand this part properly:

if((DUTY_CYCLE[1] + 21) < 32)DUTY_CYCLE[1] += 21;
else DUTY_CYCLE[1] -= 11;

if((DUTY_CYCLE[2] + 10) < 32)DUTY_CYCLE[2] += 10;
else DUTY_CYCLE[2] -= 21;
 

@Okada: I find you code is becoming a bit confusing, especially around the mechanics of the ISR. In the code in Post #6, at the start of the ISR you test for PTIF (you still have this bad habit of only testing the IF bit) but I cannot find anywhere in your code where you set the PTIE bit. Therefore the ISR will not be called when PTIF is set.
However you DO set the TMR2IE bit and enable the timer, but you don't test for the TMR2IF in the ISR. You do clear it at the end of the PTIF conditional code section.
I can only guess that what you are trying to do is to have the conditional code in the ISR only execute when BOTH the timer and the PWM interrupts are set for some reason.
What I suspect is actually happening will be one of two things: Firstly if the timer interrupt is set first then the ISR will be repeatedly called but do nothing (except stopping any non-interrupt code from executing - fortunately there is no such code at the moment in your application) until the PWM IF bit is finally set when. However clearing the timer flag in that section of the code will mean that the timer will have been counting away and be at some unknown value which will cause the timer interrupt to trigger randomly again.
The other thing that will happen is that the PWM interrupt will occur but will not call the ISR until the timer interrupt occurs some time later. You will then handle the PWM interrupt but the timing will almost certainly not be when the PWM is expecting to be updated.
I suggest that you stop coding and start to rethink how the app is supposed to work: what is the role of the timer; what do you want to do with the PWM interrupts etc..
I'm only guessing but I suspect that one of these is happening and this is the cause of the strange behaviour you are seeing.
Depending on the level of optimisation you have set, it can be a bit more efficient to use pointers rather than indexes when referencing arrays. Pointers can be dereferenced directly whereas indexes need to be calculated each time and then the result used as a pointer. If the compiler spots that you are always using a constant index then it might generate code to do the accessing directly, but it is more likely to generate more code than it really needs to in this situation.
Also, while not an issue at the moment (as you have no code in the main while loop) it is a good habit to get in to to declare all variables that are altered in an ISR as volatile.
Susan
 

In which code I didvided PDCxH by 2^8 ?

int argc and char** argv is MPLAB X generated code. You don't have to worry about it.

I used


Code ASM - [expand]
1
asm("CLRWDT")



because to clear watch dog timer. I had enabled watch dog timer in config bits.


These

Code:
if((DUTY_CYCLE[1] + 21) < 32)DUTY_CYCLE[1] += 21;
else DUTY_CYCLE[1] -= 11;

if((DUTY_CYCLE[2] + 10) < 32)DUTY_CYCLE[2] += 10;
else DUTY_CYCLE[2] -= 21;

are for phase shift. it gives 120 degree and 240 degree phase shift from the first sine wave.

I have referred Thamid's method. I converter Tahmid's method to 3 Phase system.

https://tahmidmc.blogspot.in/2013/02/demystifying-use-of-table-pointer-in.html

I have 32 entries in the sine table and sine table is for 180 degrees so if duty for

phase 1 is sinetable[0] then sinetable[21] will give 120 degrees phase shift.


@Susan

(you still have this bad habit of only testing the IF bit) but I cannot find anywhere in your code where you set the PTIE bit

No I have changed my habit. I forgot to enable PTIE_bit. I just wanted to test if using PTIF_bit in ISR solves the problem of signals shifting while duties are changing.
 
Last edited:

When you enable the PTIE bit (and therefore allow the PWM to trigger the ISR) does this bring the timing back into line?
Susan
 

@Susan

I have not tested it after enabling PTIE_bit. I will do it today and will update this thread.
 

@Susan

I enabled PTIE_bit and disabled TMR1IE_bit but the problem exists that is phase 2 and phase 3 signals are sliding. The whole signal slides.
 

By disabling the Timer 2 (I assume your reference to Timer 1 is a typo) - which you don't reference anywhere else in your code that I can see - means that it is now effectively unused. I that your intention?
Looking at your code in the ISR, there seems to be a lot of unnecessary duplication. The values of TBL_POINTER_OLD, TBL_POINTER_NEW and TBL_POINTER_SHIFT across all 3 phases will always nee the same. Why not calculate these values once (and also there is no need to distinguish between xx_OLD and xx_NEW and one variable can do the job) and then determine DUTY_CYCLE[0]. From this you can make DUTY_CYCLE[1] = DUTY_CYCLE[0] + 10 and DUTY_CYCLE_[2] = DUTY_CYCLE[0] + 21 and then wrap the values around when they exceed 31.
If you are getting the result you want form phase 0 but not from phase 1 then the problem is likely to reside in the code that is doing the wrapping.
Also I note that when you have been through 159 times, then TBL_POINTER_OLD will be 65190 and when you add 410 the next time, it will wrap around to 64. While this will make DUTY_CYCLE[0] correctly wrap from 31 back to 0, after another 159 times through, TBL_POINTER_OLD will be 65254 (159 * 410 + 64). Adding another 410 to that will give you a value of 128.
Now, as you are adding 410 each time, but occasionally adding 64 (when you wrap the unsigned integer), when you do that the 7th time, you will skip a step (7 * 64 > 410).
Again, is this what you are intending?
If not then you need to sit down with a pencil and paper (as I did) and work through exactly what your code is doing to make sure that it is doign what you intend. I suspect that there is a much simpler way to achieve what you want.
Susan
 

I finally got some output but it seems the signals are not correct. Please see the video in the attached file. Do you think there is not exact 120 degree phase shift between the three phase signals ? Between the repeated 3 phase signals I see a gap.

- - - Updated - - -

Edit:

Here is the working project. Now it is fine. Problem was in Proteus simulation. PWM4 and PWM5 were interchanged connections. Code was ok. See video in the attached Fixed file.
 

Attachments

  • Three Phase Inverter - Pure Sinewave 16KHz PWM 50Hz AC.X.rar
    628.3 KB · Views: 84
  • Three Phase Inverter - Fixed.rar
    616.2 KB · Views: 131

My Client who is a student tested the project on hardware and sent these videos. he got exact frequencies of AC. I had written one code in which SET_FREQ was modified (keeping same Crystal and PWM frequencies) to get different AC frequencies but I don't know its requirement. I will post the project soon after he submits the project at college.

**broken link removed**
 

@Susan

Even I had to learn. I had not used PIC18F4431 chip earlier and also had not used PCPWM module of PIC. I have explained the working to the student.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top