PDA

View Full Version : Swiching Mode Charger / PWM questions



almarsh
- 20th September 2013, 16:02
Hello all,
I am new here and new to pic's. At my new job (a few months now) I have been thrown into some design work involving PICs, so I am having to come up to speed fairly quickly. I have one design under my belt so I have a good start with my understanding.

What I am working on is a switched mode constant current / constant voltage Li-Ion battery charger based around the PIC18F2523. At this point, this is the only pic I have worked with.

We are using PBP and the U2 programmer from MELabs.

I have searched the forums and the net to help answer my questions but I haven't come up with anything solid and concise as of yet, so maybe you all can help me.

I am running my pic in the internal oscillator mode and have it set for 4MHz and I am using the PBP command HPWM to generate my PWM output that drives the MOSFETs in my circuit.

Right now my PWM is running at 32Khz but I would like to get it up into the 300-500kHz range but I am unsure how to do this. I have tried higher values in HPWM command and it doesn't seem to work.

I have read a few suggestions on the forum & other places about stuffing registers manually and calculating the period but I am unsure if that is my next step. I would also like to continue using the internal oscillator and would like to maintain decent resolution to the PWM steps.

Thanks

HenrikOlsson
- 20th September 2013, 19:10
Hi,
The HPWM command is, according to the manual, limited to 32768Hz as its maximum frequency. Anything higher than that you're going to have to do it "manually", which really isn't very hard.
It's good to run thru the calculations described in the datasheet in order to understand how it all (PWM period vs resolution etc) ties together but there is an excellent tool available called PICMultiCalc which quickly helps you calculate the different values.

I've just run it here and with 4MHz oscillator and 300kHz PWM frequency (333.333kHz) you're only going to get a resolution of 13 "steps".

However, that device has a PLL circuit which can be used with the internal oscillator. If you set the internal oscillator to 8MHz and enable the PLL you'll run the PIC at 32MHz. That will get you 107 "steps" at ~300kHz and 64 "steps" at 500kHz.

/Henrik.

almarsh
- 23rd September 2013, 16:09
Henrik,

Thanks for the information and ideas. You confirmed several things I was thinking.

I had an idea that I could up the oscillator speed and use PLL but wasn't sure. And in that regards, to enable my PLL, which of the following would I implement (or something else):

PLLEN = ON

or

OSCTUNE = %11000000


Secondly, I looked at my code again and I have the following line in my configuration section:

OSCCON = %11100010

Doesn't that indicate that my oscillator is already set to 8MHz? I was under the impression that I was configured for 4MHz, but again, I am the newbie at this.

Lastly, please let me know if the following lines would get me in the ballpark of what I would like to do... or if I have any idea of what is going on yet....

PR2 = 16 'pwm = 125000Hz (I changed my desired freq. PicCalc showed me that this freq would give me 256 steps to my pwm)
CCPR2L = 128 'duty at approx 50% (PR2*0.50)
TRISC.1 = 0 'make CCP2 output
T2CON = %00000100 'start timer2
CCP2CON = %00001100 'lowest duty bits and PWM on 2

.... and then I would manipulate the CCPR2L register to change the duty cycle.... no??....

Thanks again.

HenrikOlsson
- 24th September 2013, 10:36
Hi,
I don't think it'll recognise PLLEN directly so in order to enable the PLL (when using the internal oscillator) you'd do OSCTUNE.6 = 1 (set bit 6 of OSCTUNE).

The compiler recognises all the names of all the registers but not the names of each individual bit in the registers. You can, however create an alias and use it:

PLLEN VAR OSCTUNE.6 ' Of course you could give it any name you like.
PLLEN = 1

Your OSCCON = %11100010 would result in 4MHz on the internal oscillator (it's controlled by bits 4 thru 6, which I've highlighted in red, in that register). Set those three bits to 111 to get 8MHz from the oscillator (resulting in 32MHz once the PLL is enabled).

At 32MHz system clock and PR2=63 (not 16) you'll get 125kHz and 8 full bits (256 "steps"). But you need to "split" those 8bits so that the two lowest significant bits of your dutycycle value ends up in CCPxCON bits 4 and 5 (if you're using the second PWM module) and the upper 6 bits ends up the lower 8 bits of CCPRxL.

So, the actual value to get 50% would be 127 or 128 but, using the CCP2 module, you do something like

Duty = 127
CCP2CON.4 = Duty.0
CCP2CON.5 = Duty.1
CCPR2L = (Duty >> 2)

/Henrik.

almarsh
- 24th September 2013, 20:34
Henrik,
Thank you once again for the assistance and suggestions.

After implementing what you showed me and lots of staring at the data sheets I was able to get my code to compile and run this afternoon. One problem though, is that I am still only seeing a 31.2kHz 50% duty cycle square wave on the output of my pic. I am not sure what I have done. The only deviation I made from your suggestions was that I had to use CCP1 instead of CCP2 due to the way my board is already wired. (I could possibly reconfigure)

Please take a look at the following and see if you can spot my error.

Thanks again.



' Charger Program for PIC18F2523 Microprocessor
' written in PICBasic 3.0.7

' Battery: Test Program for hight speed PWM
' PC Board Assembly: MAI-xyzpdq
' PC Board: MAI-123456
' Schematic: MAI-xxxxxx
' Program: MAI-yyyyyy


@ ERRORLEVEL -306 'ignore "page boundary" errors during compiling
ver VAR BYTE[4]
ARRAYWRITE ver,["1.00"]

'PIC18F2523 Configuration Registers (Assembler)

#CONFIG
CONFIG OSC = INTIO67 ; Set oscillator configuration Internal Oscillator
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor Enable bit
CONFIG IESO = OFF ; Internal/External Oscillator Switchover bit
CONFIG PWRT = OFF ; Power-up Timer Enable bit
CONFIG BOREN = SBORDIS ; Brown out detector enabled SBOREN disabled
CONFIG BORV = 2 ; Brown-Out voltage set to 2.7
CONFIG WDT = OFF ; Watchdog Timer Enable bit
CONFIG WDTPS = 32768 ; Watchdog Timer Postscale Select bits
CONFIG CCP2MX = PORTC ; CCP2 input/output is multiplexed with RB3
CONFIG PBADEN = ON ; PORTB<4:0> pins are configured as analog I/O on Reset
CONFIG LPT1OSC = OFF ; (DEF) Timer1 configured for high power operation
CONFIG MCLRE = ON ; MCLR pin enabled; RE3 input pin disabled
CONFIG STVREN = ON ; Stack Full/Underflow Reset Enable bit (0=disabled)
CONFIG LVP = ON ; Single-Supply ICSP™ Enable bit (On = enabled)
CONFIG XINST = OFF ; Instruction set extension disabled
CONFIG DEBUG = OFF ; Background debugger disabled, RB6 and RB7 I/O pins
CONFIG CP0 = OFF ; Block 0 is not code protected
CONFIG CP1 = OFF ; Block 1 is not code protected
CONFIG CP2 = OFF ; Block 2 is not code protected
CONFIG CP3 = OFF ; Block 3 is not code protected
CONFIG CPB = OFF ;(DEF) Boot block is not code protected
CONFIG CPD = OFF ;(DEF) Data EE is not read protected
CONFIG WRT0 = OFF ;(DEF) Table 0 is not write protected
CONFIG WRT1 = OFF ;(DEF) Table 1 is not write protected
CONFIG WRT2 = OFF ;(DEF) Table 2 is not write protected
CONFIG WRT3 = OFF ;(DEF) Table 3 is not write protected
CONFIG WRTC = OFF ;(DEF) Configuration is not write protected
CONFIG WRTB = OFF ;(DEF) Boot table is not write protected
CONFIG WRTD = OFF ;(DEF) Data EE is not write protected
CONFIG EBTR0 = OFF ;(DEF) Table 0 is not read protected
CONFIG EBTR1 = OFF ;(DEF) Table 1 is not read protected
CONFIG EBTR2 = OFF ;(DEF) Table 2 is not read protected
CONFIG EBTR3 = OFF ;(DEF) Table 3 is not read protected
CONFIG EBTRB = OFF ;(DEF) Boot table is not read protected
#ENDCONFIG

'-----------------------------------------------------------------------------
' SETTING UP OSCILLATOR AND PWM SETTINGS
'-----------------------------------------------------------------------------

OSCCON = %11110010 'use internal oscillator, set to 8 MHz
OSCTUNE.6 = 1 'PLL Enabled : OSC will now run at 32MHz

PR2 = 63 'pwm = 125000Hz (highest pwm for 256 steps)

DUTY VAR WORD 'SET UP A VARIABLE FOR DUTY CYCLE
DUTY = 127 'WE SHOULD STILL HAVE A RESOLUTION OF 256 STEPS: THIS SETS PWM TO 50%

CCP1CON.4 = DUTY.0 '10 BITS OF PWM VALUES ARE SPLIT BETWEEN TWO REGISTERS
CCP1CON.5 = DUTY.1 'CCP1CON.<4:5> HOLDS THE LOWER 2 BITS
CCPR1L = (DUTY >> 2) 'CCPR1L HOLDS THE HIGH 8 BITS (SIX IN OUR SPECIFIC CASE)

TRISC.2 = 0 'MAKES CCP1 (PORT C PIN 3) AN OUTPUT
T2CON = %00000100 'SETS TMR2 PRESCALE VALUE AND ENABLES TIMER 2

CCP1CON = %00001100 'CONFIGURES CCP1 MODULE AS PWM: SEE PG 139 SECTION 15 OF DATA SHEET

HenrikOlsson
- 24th September 2013, 21:28
Hi,
CCP1 is fine, I just used CCP2 because that's what you used in your previous post.
The fact that you're getting 31.25kHz indicates that the PLL isn't active. You should get 125kHz which is 4 times (ie the PLL ratio) of what you're actually getting. I'm not SURE that's what's happening and I'm not sure WHY - if that's case.

One thing, which isn't related to the problem: You should always tell the compiler which oscillator speed you intend to run at so that it can calculate the correct values for things like PAUSE and so on. In this case

DEFINE OSC 32
This does in no way SET the frequency, it just tells the compiler how fast you INTEND to run.

Next thing, your program doesn't end anywhere, it'll continue to execute thru blank program memory until it reaches the end at which point it'll start over. Maby that's got something to do with it. Put some infinity loop at the end like

DoItForever:
TOGGLE PortB.0
Pause 10
Goto DoItForever

Using the above infinity loop will also allow you to verify if the PIC is actually running at the intended 32MHz by looking at the signal comming out of PortB.0, or whichever pin you like.

Apart from that I can't really see what might be wrong.

/Henrik.

almarsh
- 25th September 2013, 01:31
I figgured it out!!! Or at least I think I did.... none the less it is working now.

I was taking a stab at different things to see what may be causing the PLL not to run.

If you notice, my OSCCON register is set to 11110010.

I changed the OSCCON to = 11110000 and the output on pin 13 is now 125k (actually 124.8k according to the scope)

And thank you for pointing out my lack of defining the oscillator and my lack of any program.

Like I mentioned, I was taking stabs at things I thought might be inhibiting my progress, so I was stripping back everything I could. I guess I went a little too far.

Thank you once again for your assistance. Higher PWM frequencies were a major hurdle in my next design stage and I had to figgure it out. It will allow my project to use much smaller components and be more efficient.

-Albert

HenrikOlsson
- 25th September 2013, 06:32
Great, I'm glad that it works!
I can't say I understand WHY though.... Setting the lower two bits of OSCCON to 00 selects the primary oscillator as the source while setting it to 10 selects the INTOSC, I thought the PIC should be run by the internal oscillator.... Oh, wait, NOW I think I see what's going on...

Look at the figure 2.8 in the datasheet. When we select INTOSC by setting the lower two bits in OSCCON to 10 we're driving the chip directly from the internal oscillator with whatever frequency we set it to. The signal comming out of the "OSCCON MUX" in the diagram is selected to drive the PIC via "Clock Control MUX".

But when we enable the PLL we have the switch the clock source from INTOSC to the Main Oscillator block (even though that's what we use with EXTERNAL crystal) so that we get the signal from the PLL (which is now driven by the internal oscillator). The "real" primary oscillator is disabled though because we've selected the INTIO67 mode via the CONFIG bits.

Anyway, I'm glad you figured it out, good luck with the rest of the project!

/Henrik.