PDA

View Full Version : Hey guys, will this work?



jmgelba
- 11th May 2009, 20:14
Creating a buck converter and need to monitor a current sence voltage and change a pwm duty cycle based on the current sence ADC result. The target output current is user adjustable by a pot and a max current is set by a pot that is internal to the product and set at the factory. These pots are in series so only 1 input is needed. This is protection for a short at the output or the wrong load.

So there are 2 inputs to the pic, the feedback from the current sence resistor and the voltage accross a potential divider for current set. I can set the hardware so that the current sence count and the current limit count are the same value when a given current target is met.

Also, looking at the pbp pro manual I see a max HPWM of 32.767kHz yet the datasheet lists over 200kHz. Will the HPWM command actually allow a frequency of 200kHz? This is on a 18F1320.

Here is what I think will work:



OSCCON = $70
define osc 8
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 10 ' Set sampling time in uS

CSET VAR WORD 'CURRENT SET
CSEN VAR WORD 'CURRENT SENCE
DUTY VAR wORD 'HPWM DUTY CYCLE

ADCON0 = %00011001
ADCON1 = %00001111
ADCON2 = %10111111
TRISA = %00000000
TRISB = %00110011

DUTY = 800 'SET INITIAL OUTPUT CURRENT HIGH TO ENABLE FAST STARTUP
CSET = 0
CSEN = 0

LOOP:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENCE
IF CSEN > CSET Then LET DUTY = DUTY - 1
IF CSEN < CSET THEN LET DUTY = DUTY + 1
HPwm 1,DUTY,32767 'OUTPUTS THE DUTYCYCLE AT 32.767KhZ
GOTO LOOP

mister_e
- 11th May 2009, 20:25
HPWM limit is as stated in your manual. To reach higher frequency, you need to write the PWM register manually. Use PICMultiCalc to find PR2 and Timer Prescaller value, then plug the DutyCycle values in CCP1CON and CCPR1L registers... double check your datasheet to confirm.

For Buck converter, usually the higher the better for reducing coil and capacitors size.

Make sure your ADCONx setting don't interfer with PBP ADCINs defines. You may want to place your define after those ADCONx lines, or get rid of ADCIN. Once again PICMultiCalc may give you some hints about min acquisition time and faster clock conversion source.... which is probably a must for buck converter. Don't forget to check the Resolution for the frequency you choosed. @8Mhz & 200KHz, you should have something like 7 bit of resolution.. 40 dutycycle steps... not bad, not good, depending how fancy you want it.

In some case it's not a so good idea to use a PIC for that, just for the reaction time and what your PIC will also need to do apart the voltage regulation.

jmgelba
- 11th May 2009, 20:36
Hmm, eventually I have to get this running over 100kHz, so I will need to learn how to manually write to the registers and preload timers etc. I have never done this.
All the links I've come across for the multicalc are dead. I had it once but lost it at some point.
There is not much else going on with the pic really. If a pin goes high, it turns on a FET and runs the converter. Pin the goes low, it switches off. Thats it really.

I've swapped the location of the DEFINE's.
Other than that, at 32.767kHz, will that code do what I think it should do?

mister_e
- 11th May 2009, 20:39
In theory it should work. Theory is always theory ;)

PicMultiCalc download
http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2957&d=1225550328

Probably you can get some inspiration of the following
http://www.picbasic.co.uk/forum/showpost.php?p=37750&postcount=10

jmgelba
- 11th May 2009, 21:19
Ok, so using the calc I get PR2 = 9, duty register = 20 and with a 1:1 prescaler.

Is this about right?:




OSCCON = $70
define osc 8

CSET VAR WORD 'CURRENT SET
CSEN VAR WORD 'CURRENT SENCE
DUTY VAR wORD 'HPWM DUTY CYCLE

ADCON0 = %00011001
ADCON1 = %00001111
ADCON2 = %10111111
TRISA = %00000000
TRISB = %00110011
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 10 ' Set sampling time in uS


'DUTY = 30 'SET INITIAL OUTPUT CURRENT HIGH TO ENABLE FAST STARTUP
CSET = 0
CSEN = 0

duty = 20 ' duty value for 50% duty cycle
PR2 = 9 '
T2CON = %00000100 ' timer2 on, prescale 1:1
CCPR1L = duty>>2 ' MSB of duty cycle value
CCP1CON=%00001100 | (dUTY<<5) ' set PWM mode and store the
' 2 LSB of duty




LOOP:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENCE
IF CSEN > CSET THEN LET DUTY = DUTY - 1
IF CSEN < CSET THEN LET DUTY = DUTY + 1
CCPR1L = duty>>2 ' MSB of duty cycle value
CCP1CON=%00001100 | (dUTY<<5) ' set PWM mode and store the
' 2 LSB of duty

'HPWM 1,DUTY,32767 'OUTPUTS THE DUTYCYCLE AT 32.767KhZ
GOTO LOOP

mister_e
- 11th May 2009, 21:33
Almost... but no cigar. Check CCP1CON for YOUR particular PIC. CCP1CON is a bit different on this one (and I think my example was false anyway ... dooh) as usual, MicroChip can't be consistent between all their PIC model. Good idea to release a datasheet for each and every different model though ;)


CCP1CON=%00001100 | (Duty<<4)

jmgelba
- 11th May 2009, 21:44
I did, it looks the same to me. I must have missed something.

bit 7 and 6 are 00 = Single output; P1A modulated; P1B, P1C, P1D assigned as port pins

bit 5 and 4 are the two LSbs of the PWM duty cycle. The eight MSbs are found in CCPR1L. I guess I do not know what to put in here or how to find out what should go in here. I thought duty>>2 took care of this.

and 3 - 0 are 1100 = PWM mode; P1A, P1C active-high; P1B, P1D active-high

mister_e
- 11th May 2009, 21:55
The change is above... <<4 instead of <<5... but as i said... <<5 was wrong anyway... not sure why, but wrong anyways... few years after... no one complaint :D

It is more code efficient... and obviously safer to use
CCPR1L = duty>>2
CCP1CON.4=Duty.0
CCP1CON.5=Duty.1

unless you'll screw up the CCP module on that 18F (think about the bit <7:6> of CCP1CON when duty value change). This was my major point here.

jmgelba
- 11th May 2009, 23:13
Ok, I think I understand all except how did you fill in bits 4 and 5? Why a 0 and 1 in the location you put them in?

The lsb's of the duty cycle go in there. Its a 10 bit duty cycle. The top 8 are shifted away leaving to 2 lsb's. In decimal the duty cycle is 20. Is the binary representaion of 20 used? Is that how you get the last 2 bits?
20 = 00010100 so the lsb's should be 00, no?

mister_e
- 11th May 2009, 23:56
Ok, I think I understand all except how did you fill in bits 4 and 5? Why a 0 and 1 in the location you put them in?

assuming a 10 bits results as follow


'Bit number 9876543210
MyVar = %1111110011
In red the MSB, in Blue the LSBs for PWM.

Shift them all two position to the right you have


MyVar = %0011111100

Now, where are the LSB now... gone... you need to extract them 2 from the original 10bit value, so Bit0 and BIT1, and transfer them to Bit4 and BIT5 of CCP1CON register
CCP1CON.4=MyVar.0 ' bit0 to bit4 of CCP1CON
CCP1CON.5=Myvar.1

jmgelba
- 12th May 2009, 00:34
YES!! I understand at last!! Thank you so much for your time Steve.

I have been looking at it all wrong. I can see moving the bits now. I thought each bit value, a 0 or a 1, was the 4 and 5 bit part of the number, so when you removed the lsb's, you shifted everything, and what was in 6 and 7 is now in 4 and 5 and is the new state.

jmgelba
- 12th May 2009, 01:59
Well now, of course, this does absolutly nothing!
Here's the complete code.




OSCCON = $70
define osc 8

CSET VAR WORD 'CURRENT SET
CSEN VAR WORD 'CURRENT SENCE
DUTY VAR wORD 'PWM DUTY CYCLE

ADCON0 = %00011001
ADCON1 = %00001111
ADCON2 = %10111111
TRISA = %00000000
TRISB = %00110011
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (5=fosc/16)
Define ADC_SAMPLEUS 10 ' Set sampling time in uS

CSET = 0
CSEN = 0

duty = 20 ' duty value for 50% duty cycle
PR2 = 9 '
T2CON = %00000100 ' timer2 on, prescale 1:1
CCPR1L = duty>>2 ' MSB of duty cycle value
CCP1CON.4=Duty.0 ' set PWM mode and store the
CCP1CON.5=Duty.1 ' 2 LSB of duty

LOOP:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENCE
IF CSEN > CSET Then LET DUTY = DUTY - 1
IF CSEN < CSET THEN LET DUTY = DUTY + 1
CCPR1L = duty>>2 ' MSB of duty cycle value
CCP1CON.4=Duty.0 ' set PWM mode and store the
CCP1CON.5=Duty.1 ' 2 LSB of duty
GOTO LOOP

jmgelba
- 12th May 2009, 04:28
Hehehe well it helps to actually turn on the PWM module!!
Glitchy though. I've delayed the update by 1mS to smooth it out but still a big problem. Going to try disabling the PWM then updating the duty cycle and turning it back on.

Darrel Taylor
- 12th May 2009, 04:41
To get Glitch-Free, you have to synchronize the updates with Timer2.

The HPWM10 module does that with 10-bit resolution, and works just like the HPWM command.
http://www.picbasic.co.uk/forum/showthread.php?p=37805#post37805

But at your higher frequency, you'll still need to do it manually.
It does show how to though.

hth,

jmgelba
- 12th May 2009, 05:47
Hi Darrel, I was just reading through that thread thinking it all looks familiar. I hadnt taken a look at your attachement yet.

I'll have to digest in the morning. Is there a tutorial in your attachement, and will it work for 18F devices?

I hate having one of those brains that learns by examples and questions rather than independant learning, feel so bad asking all the time. At least it usually goes in.

I should drink more. Alcohol kills brain cells, therefore one could deduce that the slower brains cells are in contact with the alcohol longer, which would lead to them being killed off. This would leave you with only faster brain cells and thus more intelligence as the slower ones are no longer holding up your thinking. So on that thought, I'm going to the fridge to open a can of knowledge.

Darrel Taylor
- 12th May 2009, 06:48
There's not really a tutorial.
But there is a test program in the .zip that shows how to use it.

The max frequency is still 32.767khz.
And it will work with 12F's, 16F's or 18F's. As long as they have CCP modules.

However, while you grab me one of those cans of knowledge ... :)

The whole thing boils down to synchronizing the update with TMR2.
And HPWM10 has extra code to handle different frequencies/prescaler/CCP modules, which you won't need with a constant frequency on a single CCP.

So all you need to do with your existing code, is wait for the TMR2IF before changing the dutycycle ...

TMR2IF VAR PIR1.1

TMR2IF = 0
while !TMR2IF : wend ; let current cycle complete
CCPR1L = duty>>2 ; MSB of duty cycle value
CCP1CON.4=Duty.0 ; set PWM mode and store the
CCP1CON.5=Duty.1 ; 2 LSB of duty
No digesting required.
Do I get that Can of knowledge now? :)
<br>

jmgelba
- 12th May 2009, 06:58
Sure do.

I'll report in the morning, its about 2am and my 18 month old is coughing himself awake as I type. I've got a feeling its going to be a long night. Poor guy, always so sick. Yay for ear tubes on Thursday.

jmgelba
- 12th May 2009, 13:16
Well the little guy is sick and I got about 4 hours sleep last night.

Havent tried this yet but I came up with this alternative and included Darrels changes.



START:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENCE
IF CSEN > CSET Then LET DUTY = DUTY - 1
IF CSEN < CSET THEN LET DUTY = DUTY + 1
GOSUB NewDuty '
PAUSE 1
GOTO Start

NewDuty:
TMR2IF = 0
while !TMR2IF : wend ; let current cycle complete
CCP1CON = 0
CCPR1L = Duty >>2
CCP1CON.5 = Duty.1
CCP1CON.4 = Duty.0
CCPCON.7 = 0
CCPCON.6 = 0
CCPCON.3 = 1
CCPCON.2 = 1
CCPCON.1 = 0
CCPCON.0 = 0
RETURN

Darrel Taylor
- 12th May 2009, 14:04
Poor little guy. :sad:

As for the proposed additions ...
You don't want to do that.

The idea is to minimize the glitches, not create more.
Leave the module in PWM mode and just change the dutycycle.
<br>

jmgelba
- 12th May 2009, 16:32
Hmm, well it dosent work. It's all over the place and then goes high and stays high. I have to power down to reset because adjusting the CSET pot does nothing to gain a recovery. Also, adc value for CSET does very little to alter the duty cycle.

Is my thinking right here? Will this try to find the right duty cycle so CSEN = CSET?

mister_e
- 12th May 2009, 18:22
Refresh your duty cycle only when it need to, unless you'll have problem.

try something like

START:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENCE
IF CSEN > CSET Then LET DUTY = DUTY - 1
IF CSEN < CSET THEN LET DUTY = DUTY + 1
if DUTY != OldDuty then
OldDuty = Duty
GOSUB NewDuty
ENDIF
GOTO Start

NewDuty:
TMR2IF = 0
while !TMR2IF : wend ; let current cycle complete
CCP1CON = 0
CCPR1L = Duty >>2
CCP1CON.5 = Duty.1
CCP1CON.4 = Duty.0
RETURN

You'll probably need to allow an error margin in your IF-THEN, remember you have a 7 bits or so PWM resolution but 10Bit ADC results. Reduce your ADC resolution to 8 bit may help.

You also want to make sure you don't overflow the Duty value...

Seeing your schematic would be nice.

Bruce
- 12th May 2009, 19:00
Does this work OK?


OSCCON = $70
DEFINE OSC 8

CSET VAR WORD 'CURRENT SET
CSEN VAR WORD 'CURRENT SENCE
DUTY VAR WORD 'PWM DUTY CYCLE
O_Duty VAR WORD 'previous Duty-cycle
MinDuty CON 2 'minimum duty cycle
MaxDuty CON 40 'maximum duty cycle

ADCON0 = %00011001
ADCON1 = %00001111
ADCON2 = %10111111
TRISA = %00000000
TRISB = %00110011
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (5=fosc/16)
Define ADC_SAMPLEUS 10 ' Set sampling time in uS

CSET = 0
CSEN = 0

DUTY = 20 ' duty value for 50% duty cycle
PR2 = 9 '
T2CON = %00000100 ' timer2 on, prescale 1:1
CCPR1L = DUTY>>2 ' MSB of duty cycle value
CCP1CON.4=DUTY.0 ' set PWM mode and store the
CCP1CON.5=DUTY.1 ' 2 LSB of duty
CCP1CON = %00001100

LOOP:
ADCIN 6, CSET 'READ VALUE OF CURRENT SET POT
ADCIN 4, CSEN 'READ VALUE OF CURRENT SENSE

' test for CSEN > CSET*2
IF CSEN > (CSET*2) THEN ' minimize short-cycling (increase as needed)
IF DUTY > MinDuty THEN ' don't allow below minimum duty
DUTY = DUTY - 1
ENDIF
ENDIF

IF CSEN < (CSET/2) THEN
IF DUTY < MaxDuty THEN ' don't allow greater than max duty
DUTY = DUTY + 1
ENDIF
ENDIF

IF O_Duty = DUTY THEN LOOP ' does duty-cycle need updating?
O_Duty = DUTY ' yes. copy last duty value for next comparison

CCP1CON.4=DUTY.0 ' set PWM mode and store the
CCP1CON.5=DUTY.1 ' 2 LSB of duty
CCPR1L = DUTY>>2 ' MSB of duty cycle value
GOTO LOOP
A low-pass filter on each A/D input would also help.

Darrel Taylor
- 12th May 2009, 20:12
At 200khz, you only get a Duty range of 0-40.
Not going to be a very precise regulator with that.

Your previous examples were at 32.767khz, which PicMultiCalc shows 0-244 duty range (better). But like mister_e said, you'll need to limit the range.

With a 20mhz crystal you can get 0-610 @32khz, or 0-100 @ 200khz.
<br>

jmgelba
- 13th May 2009, 04:32
Guys thanks for the ideas and snippets. I have not been around today to work on this. I need to up the frequency to 300KHz now to reduce inductor size and value. I was going to use a 20mhz resonator but just wanted to get something up quick and dirty so I used the internal osc at 8mhz.

My schematic is a scribble on a piece of paper at the moment, but its essentially a classic buck converter design that could be found anywhere on the web. I think some of the problem is ripple voltge on the 5v line. This changes the internal vref of the adc.

I'll mill or get the boys in the shop to etch me a pcb in the morning so I can load up on the capacitance and cut down on the noise.

Oh, last night, I killed 12 Osram Dragon infra red led's that are not mine. Oops. I think they are something like $15 a piece :mad:

Ioannis
- 13th May 2009, 10:34
Oh, last night, I killed 12 Osram Dragon infra red led's that are not mine. Oops. I think they are something like $15 a piece :mad:

1 or 2 is OK. But 12..????

Next time put a Dummy load first.

Ioannis

jmgelba
- 13th May 2009, 16:19
It was a mistake. I have a test box where I can push a few buttons and switch between different types, numbers and colors of LED's. I use it to test drivers that are new and about to be installed into a product. I also have some power resistors in there which are my dummy loads. I pressed the wrong switch and connected 12 IR led's instead of the dummy load. I put 23v through 2 strings of 6. The have about 1.8vdrop each typically.

It was not a good night.

jmgelba
- 15th May 2009, 13:48
OK, I found some time to try Bruce's code and I got the same results. At a very high and very low feedback signal the PWM signal disappears and the output goes 100% high. If the feedback signal varies rapidly the PWM goes 100% low.

I took off all the switching components to remove any chance of noise and just used a pot to vary a fake feedback voltage and got the same results.

I am going to try the code and ciruit used in the AN1130 app note. My schematic is different to this - I have the inductor on the positive side of the LED's and use a PFET.

My requirements are also different.

Input = 24v
LED forward V = 21V (6x blue LED's with 3.5vdrop each)
LED I = 700mA
Current Ripple = 10%
Switiching Frequency = 200KHz

I calculate the inductor value to be 131uH. I will have to lower the gain on the feedback opamp from 11 to maybe 5 or something. I'll figure that out later - just a simple resistor value change.

I'm going to spend a bit of time trying to convert the code from C to PICBasic. I've havent used C before so that will take me a while to actualy figure out what the heck void and so on means.