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.

[SOLVED] PIC18F series Power Control PWM configuration

Status
Not open for further replies.

gonespa

Member level 1
Joined
Sep 10, 2012
Messages
32
Helped
2
Reputation
4
Reaction score
1
Trophy points
1,288
Activity points
1,654
Hi,

I am Trying to build a BLDC motor controller with the PIC18F4431 MCU. My plan is to use the six step sensorless trapezoidal commutation. Complementary and unipolar PWM, to be precise. The reason I chose this is to use synchronous rectification instead of simplt using the MOSFET intrinsic diodes.

This means that, at any given time, both MOSFETs for a phase will be PWM switching (the lower one as the complement of the high one + dead time), in another phase the high one will be off and the low one with be on (no PWM) and finally the third phase will have both MOSFETs off.

The problem is that I don´t see a way to configure the Power Control PWM module to allow this... if I configure the three phases as complementary, there is no way to turn off BOTH MOSFETS in a single phase at the same time (the lower is always the complement of the higher, so when I shut off the higher one the lower is automatically set on by the MCU).
If I configure the channel as independent, I loose the dead time functionality, which is something very convenient.

I tried to change the PMOD* bits on PWMCON0 register each time I change from one step to the next (I set the undriven phase to independent mode and the rest to Complementary mode), but this must not be allowed once the module is active since I see no effect in the pin outputs. (or I am doing something wrong).

Is there a way to configure this MCU for this driving requirements?

Kind Regards.
 

there is no way to turn off BOTH MOSFETS in a single phase at the same time

Yes, there is. Post your complete project and I will fix the code.
 
Yes, there is. Post your complete project and I will fix the code.

You mean the code?

Well, it is a bit crude right now, it just configure the registers , set the commutating table and change between the six steps each second. PWM duty cycle fixed at a low value.

This is it:
Code:
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1H
//#pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
#pragma config OSC = IRCIO      // Oscillator Selection bits (Internal oscillator block, port function on RA6 and port function on RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switchover bit (Internal External Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled)
// BORV = No Setting

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDPS = 32768     // Watchdog Timer Postscale Select bits (1:32768)
#pragma config WINEN = OFF      // Watchdog Timer Window Enable bit (WDT window disabled)

// CONFIG3L
#pragma config PWMPIN = OFF     // PWM output pins Reset state control (PWM outputs disabled upon Reset (default))
#pragma config LPOL = HIGH      // Low-Side Transistors Polarity (PWM0, 2, 4 and 6 are active-high)
#pragma config HPOL = HIGH      // High-Side Transistors Polarity (PWM1, 3, 5 and 7 are active-high)
#pragma config T1OSCMX = OFF    // Timer1 Oscillator MUX (Standard (legacy) Timer1 oscillator operation)

// CONFIG3H
#pragma config FLTAMX = RC1     // FLTA MUX bit (FLTA input is multiplexed with RC1)
#pragma config SSPMX = RC7      // SSP I/O MUX bit (SCK/SCL clocks and SDA/SDI data are multiplexed with RC5 and RC4, respectively. SDO output is multiplexed with RC7.)
#pragma config PWM4MX = RB5     // PWM4 MUX bit (PWM4 output is multiplexed with RB5)
#pragma config EXCLKMX = RC3    // TMR0/T5CKI External clock MUX bit (TMR0/T5CKI external clock input is multiplexed with RC3)
#pragma config MCLRE = OFF      // MCLR Pin Enable bit (Disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Low-Voltage ICSP Enable bit (Low-voltage ICSP disabled)

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000200-000FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (001000-001FFF) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (002000-002FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (003000-003FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000200-000FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (001000-001FFF) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (002000-002FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (003000-003FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000200-000FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (001000-001FFF) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (002000-002FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (003000-003FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks)

#define _XTAL_FREQ 8000000     

#include <stdio.h>
#include <stdlib.h>

unsigned char overrides[6];
unsigned char override_values[6];

void main(int argc, char** argv) {    

    int contador = 0;
    
    OSCCONbits.IRCF0 = 1;
    OSCCONbits.IRCF1 = 1;
    OSCCONbits.IRCF2 = 1; //8Mhz
    OSCCONbits.SCS1 = 1; //Internal oscillator block


    TRISDbits.RD2 = 0;
    PORTDbits.RD2 = 0;

    
    PWMCON0bits.PWMEN2 = 1;
    PWMCON0bits.PWMEN1 = 0;
    PWMCON0bits.PWMEN0 = 0;
  
    PWMCON0bits.PMOD3 = 0;
    PWMCON0bits.PMOD2 = 0;
    PWMCON0bits.PMOD1 = 0;
    
    
    PWMCON1bits.OSYNC = 1;
    
    
    
    PTPERH = 0; 
    PTPERL = 99;
    
    PDC0L = 0b00100100;
    PDC0H = 0b00000000;
    PDC1L = 0b00100100;
    PDC1H = 0b00000000;
    PDC2L = 0b00100100;
    PDC2H = 0b00000000;
    
    PTCON0bits.PTMOD1 = 0;
    PTCON0bits.PTMOD0 = 0;
    
    DTCONbits.DT0 = 0;
    DTCONbits.DT1 = 1;
    DTCONbits.DT2 = 1;
    
    
    //Step 1
    overrides[0] = 0b00000011; 
    override_values[0] = 0b00000100; 
    //Step 2
    overrides[1] = 0b00000011; 
    override_values[1] = 0b00010000;     
    //Step 3
    overrides[2] = 0b00001100; 
    override_values[2] = 0b00010000;   
    //Step 4
    overrides[3] = 0b00001100; 
    override_values[3] = 0b00000001;      
    //Step 5
    overrides[4] = 0b00110000; 
    override_values[4] = 0b00000001;   
    //Step 6
    overrides[5] = 0b00110000; 
    override_values[5] = 0b00000100;    
       
    OVDCOND = overrides[contador];
    OVDCONS = override_values[contador];
    contador++;
    

    PTCON1bits.PTEN = 1;
    

    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
    __delay_ms(10); 
      
    while(1)
    {
        
        OVDCOND = overrides[contador];
        OVDCONS = override_values[contador];
        if (contador == 5)
        {
            contador = 0;
        }
        else
        {
            contador++;
        }
        
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        __delay_ms(10); 
        
    }
  
}
 
Last edited by a moderator:

Please zip and post the complete MPLAB X XC8 project files.
 
What PWMs you want ?

- - - Updated - - -

Post your circuit. I am writing code.

- - - Updated - - -

Post your circuit. I am writing code.
 
Lets focus in the first step:

Phase "A" -->PWM
-PWM to the high side MOSFET (PWM1).
-Complementary PWM to the low side MOSFET (PWM0) + dead time.

Phase "B" -->no PWM
-Low side MOSFET on (pin PWM2).
-High side off (pin PWM3).

Phase "C" -->no PWM
-Low side MOSFET off (pin PWM4).
-High side off (pin PWM5).

This is just step one, this rotates as steps advance, you know, as any typical six step BLDC driver.

I don´t have the three phase full circuit diagram but I have this one for an (incomplete) half bridge for one phase (the high-side MOSFET in missing). The circuit is posted here:
HTML:
https://www.edaboard.com/threads/361796/#post1549322

The MCU is missing too, but its output pins are connected to HIN (PWM1) and LIN(PWM0)
 

Just mention all the steps for all the phases in sequence. I have never worked with BLDC motor but I will try to solve your problem.

- - - Updated - - -

I got the steps and sequences. Post the actual circuit. I am writing the code.
 
Just tell me do you want three PWMs with 120 degree phase shift between the signals ?

- - - Updated - - -

See attached document page no. 16. It shows 3 Phase BLDC Motor commutation sequence. Are these the sequence you want ? Can you use PIC18F46K22 instead ?

- - - Updated - - -

I found a very good document related to driving BLDC motor using sensorless method using PIC18FXX31. I am working on it. I want to know your PWM frequency and method of sensorless control.
 

Attachments

  • Brushless DC Motor Fundamentals.pdf
    618 KB · Views: 191
Hi,

120 degree phase shift is OK. The PIC can be any PIC18F, It´s just that the one I currently have is the PIC18F4431.

The issue I have is related to the way I want to drive the phases (Specifically, at the moment the PWM for the active phase if OFF. For instance, if high side MOSFET for "A" Phase is PWM at a 50% duty cycle, there is a 50% of the time it is off). In all the Microchip notes I found they show you a method relying in the intrinsic parasitic diode to conduct the free-wheeling current. In that mode, you do not need to use the complementary switching, so no problem, you can configure all PCPWM channels as independent. This is shown in the PDF you attached too, page 15, Figure 12. You will see that, for any given step, there is a phase where PWM is seen and the complementary switch is driven low. What I want is to PWM that switch too, with the complementary waveform.

I want, however, to use the low side MOSFET of that phase ("A" in our example) to free-wheel that current and hence need the complementary switching and the dead time insertion.

This is a good video explaining what I mean:
HTML:
https://www.youtube.com/watch?v=uqzOQGiwGnE

Since I use the six step commutation method, I need to have one of the phases completelly undriven (both MOSFETS off) so I can measure Back Electromotive Force to Know when to move to the next commutation step, but this is not possible if you have the channels configured as complementary.

I suppose I can use some workaround to achive what I want with mi MCU (or the one you propose), but the reason why I chose an MCU with this module is to avoid having to handle this myself.
 

Ok. I will try to use PIC18F4431 or PIC18F46K22 and see if a code can be written for your needs but before that I need your exact hardware circuit including the circuit used to detect back emf preferably drawn in Proteus.
 
In the end, I decided to use the "SD" pin of my gate driver chip (IR2110) to completelly disable each phase whenever It must be (just before changing commutation step, using uno digital output from the MCU). I was unable to find a way to do what I want with the PCPWM module.

Regards.
 

I finally managed to devise how to do this in the MCU.

Changing from complementary to independent mode (and the other way around) is in fact possible at any time BUT the phase must have PWM on it (it wont work if it is overriden to a fixed value via OVDCON registers, which is what I was trying originally).

So, In my case, each time I move from one step to the next, it´s a matter of:
- Decreasing duty value for the undriven phase to 0%. (and the rest to whatever duty cycle must have)
- Change that phase to independent mode (and the rest to complementary).
- Change OVDCON registers so that the undriven and the phase to which PWM is applied are configured to do PWM. The other one is overriden to set a fixed value of '1' to the Low-side MOSFET. (and a '0' to the high-one).

I do this with the PWMCON1 OSYNC syncronization bit set to a value so that the changes in the overrides are synchronized to the PWM time base.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top