BLDC with 3 or 6 PWM?

Started by Gaetan Barthelemy August 7, 2006
Hello,

I have been working on controlling a BLDC motor with a LPC2103. I wanted to use 6 PWM signals (3 generated by Timer 1 and 3 by Timer2) to control the MOSFETs. The issue is that there is a small time difference (about 330ns) between the PWM generated by Timer1 and the ones generated by Timer2.
I have read an application note using only 3 PWM signals for the high side, the low side being controlled by ON/OFF signals. The only drawback I have seen using that approach is that the zero crossing will be more difficult to detect due to the voltage drop of the diode in the lower MOSFETs.

Has anyone tried that method? And if yes is there any special thing I should pay attention to?

Thanks a lot for your help

Gaetan

---------------------------------
Groups are talking. We┬┤re listening. Check out the handy changes to Yahoo! Groups.

An Engineer's Guide to the LPC2100 Series

--- In l..., Gaetan Barthelemy
wrote:
>
> I have been working on controlling a BLDC motor with a LPC2103. I
> wanted to use 6 PWM signals (3 generated by Timer 1 and 3 by
> Timer2) to control the MOSFETs. The issue is that there is a small
> time difference (about 330ns) between the PWM generated by Timer1
> and the ones generated by Timer2.

Isn't it just because the timers are out of sync with each other?
This will happen if you initialize/reset and start one timer, and
then initialize/reset and start the other timer.

Since you cannot start them at exactly the same time, you can
initialize one timer to zero and the other one to a small number, and
then start the first and then the other timer. The "small number"
should be the number of clocks it takes to start the first timer.

If APBDIV is 1, a write to a timer register takes 7 clocks. So the
timers will be in sync if you do something like this:

T1TC = 0;
T2TC = 7; /* Timer 2 needs a head start of 7 clocks */
/* ... and other initializations, except T1TCR and T2TCR */

and then start them using assembler, so that nothing comes between
the two STR instructions. You may even want to disable interrupts
around them.

LDR R0, =T1TCR
LDR R1, =T2TCR
MOV R2, #0x01
STR R2, [R0, #0] /* Start timer 1... */
STR R2, [R1, #0] /* ...and 7 clocks later start timer 2 */

Karl Olsen
Thanks Karl,

I thought about the fact that both timer were out of sync, and I also played with the timer counter, but the lowest timer difference I could get was 66ns. So I have done somer others tests, and here is what I got:
I worked with a PCLK = CPU CLK/4 = 15MHz
T1TC = 0 and T2TC = 0 => time difference of 334ns = 5 cycles
T1TC = 1 and T2TC = 0 => time difference of 66ns = 1 cycle
so increasing T1TC by 1, is the same as adding 400ns or 6 cycles.

You said that "If APBDIV is 1, a write to a timer register takes 7 clocks." Could you tell me how you calculate that or where I can find the execution time for the instructions? I guess that it will help figure out a lot of stuff.

again thanks a lot for you help

Gaetan

Karl Olsen wrote:
--- In l..., Gaetan Barthelemy
wrote:
>
> I have been working on controlling a BLDC motor with a LPC2103. I
> wanted to use 6 PWM signals (3 generated by Timer 1 and 3 by
> Timer2) to control the MOSFETs. The issue is that there is a small
> time difference (about 330ns) between the PWM generated by Timer1
> and the ones generated by Timer2.

Isn't it just because the timers are out of sync with each other?
This will happen if you initialize/reset and start one timer, and
then initialize/reset and start the other timer.

Since you cannot start them at exactly the same time, you can
initialize one timer to zero and the other one to a small number, and
then start the first and then the other timer. The "small number"
should be the number of clocks it takes to start the first timer.

If APBDIV is 1, a write to a timer register takes 7 clocks. So the
timers will be in sync if you do something like this:

T1TC = 0;
T2TC = 7; /* Timer 2 needs a head start of 7 clocks */
/* ... and other initializations, except T1TCR and T2TCR */

and then start them using assembler, so that nothing comes between
the two STR instructions. You may even want to disable interrupts
around them.

LDR R0, =T1TCR
LDR R1, =T2TCR
MOV R2, #0x01
STR R2, [R0, #0] /* Start timer 1... */
STR R2, [R1, #0] /* ...and 7 clocks later start timer 2 */

Karl Olsen




---------------------------------
How low will we go? Check out Yahoo! Messengers low PC-to-Phone call rates.





--- In l..., Gaetan Barthelemy
wrote:

> I thought about the fact that both timer were out of sync, and I
> also played with the timer counter, but the lowest timer difference
> I could get was 66ns. So I have done somer others tests, and here
> is what I got:
> I worked with a PCLK = CPU CLK/4 = 15MHz
> T1TC = 0 and T2TC = 0 => time difference of 334ns = 5 cycles
> T1TC = 1 and T2TC = 0 => time difference of 66ns = 1 cycle
> so increasing T1TC by 1, is the same as adding 400ns or 6 cycles.
>
> You said that "If APBDIV is 1, a write to a timer register takes
> 7 clocks." Could you tell me how you calculate that or where I can
> find the execution time for the instructions? I guess that it will
> help figure out a lot of stuff.

The basic ARM7TDMI-S timings are documented in
http://www.arm.com/pdfs/DDI0234A_7TDMIS_R4.pdf
chapter 7. I and C cycles are always one core clock each, and N and
S cycles are one core clock each, plus some wait states in some cases.

The waitstates added by the flash and MAM are described in the MAM
chapter of the LPC2xxx manuals.

I measured the waitstates added by going through the APB bridge:
http://groups.yahoo.com/group/lpc2000/message/7808 . These should
really be documented by Philips.

Karl Olsen
Thanks Karl for the info,

so I calculated all that, and I found a way to have timer 1 and 2
synchronize, the issue is that it doesn't make sense. I enclosed the
assembler code of the PWM parts from the starting of the timer2 to
the start of the timer1

T2TCR = 0x01; //START timer 2
MOV R1,#0x01 +1 Cycle
LDR R0,[PC,#0x0074] +3 Cycles
STRB R1,[R0,#0x00] +2 Cycles
***************************************** # of cycle = 0
T1PR = 5;
LDR R0,[PC,#0x0074] +3 Cycles
STR R5,[R0,#0x00] +2 Cycles

T1PC = 0; //RESET PRESCALE COUNTER
LDR R0,[PC,#0x0074] +3 Cycles
STR R4,[R0,#0x00] +2 Cycles

T1TC = 6; //RESET TIMER.
MOV R4,#0x06 +1 Cycle
LDR R0,[PC,#0x0074] +3 Cycles
STR R4,[R0,#0x00] +2 Cycles
T1MR0 = 254;
LDR R0,[PC,#0x0074] +3 Cycles
STR R3,[R0,#0x00] +2 Cycles

T1MCR = 0x00000003;
MOV R3,#0x03 +1 Cycle
LDR R0,[PC,#0x0070] +3 Cycles
STRH R3,[R0,#0x00] +2 Cycles

T1PWMCON = 0x0000000F;
LDR R0,[PC,#0x0070] +3 Cycles
STR R2,[R0,#0x00] +2 Cycles

//Start timer 1
T1TCR = 0x01;
LDR R0,[PC,#0x0070] +3 Cycles
STRB R1,[R0,#0x00] +2 Cycles

***************************************** # of cycles = 37

So I checked that count with the signals on the scope, and all
matches, but what I don't get is why I need to set T1TC to 6 to in
fact get 36 PCLK cycle is there any reasons to that?
I don't have wait states, MAM is fully enabled and MAM timing is 4

I appreciate a lot your help; especially that it starts driving me
crazy

Gaetan

--- In l..., "Karl Olsen" wrote:
>
> --- In l..., Gaetan Barthelemy
> wrote:
>
> > I thought about the fact that both timer were out of sync, and I
> > also played with the timer counter, but the lowest timer
difference
> > I could get was 66ns. So I have done somer others tests, and here
> > is what I got:
> > I worked with a PCLK = CPU CLK/4 = 15MHz
> > T1TC = 0 and T2TC = 0 => time difference of 334ns = 5 cycles
> > T1TC = 1 and T2TC = 0 => time difference of 66ns = 1 cycle
> > so increasing T1TC by 1, is the same as adding 400ns or 6
cycles.
> >
> > You said that "If APBDIV is 1, a write to a timer register
takes
> > 7 clocks." Could you tell me how you calculate that or where I
can
> > find the execution time for the instructions? I guess that it
will
> > help figure out a lot of stuff.
>
> The basic ARM7TDMI-S timings are documented in
> http://www.arm.com/pdfs/DDI0234A_7TDMIS_R4.pdf
> chapter 7. I and C cycles are always one core clock each, and N
and
> S cycles are one core clock each, plus some wait states in some
cases.
>
> The waitstates added by the flash and MAM are described in the MAM
> chapter of the LPC2xxx manuals.
>
> I measured the waitstates added by going through the APB bridge:
> http://groups.yahoo.com/group/lpc2000/message/7808 . These should
> really be documented by Philips.
>
> Karl Olsen
>



---- Original Message ----
From: "gaetanbarthelemy"
To:
Sent: Tuesday, August 08, 2006 6:05 PM
Subject: [lpc2000] Re: BLDC with 3 or 6 PWM?

> so I calculated all that, and I found a way to have timer 1 and 2
> synchronize, the issue is that it doesn't make sense. I enclosed the
> assembler code of the PWM parts from the starting of the timer2 to
> the start of the timer1
>
> T2TCR = 0x01; //START timer 2
> MOV R1,#0x01 +1 Cycle
> LDR R0,[PC,#0x0074] +3 Cycles
> STRB R1,[R0,#0x00] +2 Cycles
> ***************************************** # of cycle = 0
> T1PR = 5;
> LDR R0,[PC,#0x0074] +3 Cycles
> STR R5,[R0,#0x00] +2 Cycles
>
> T1PC = 0; //RESET PRESCALE COUNTER
> LDR R0,[PC,#0x0074] +3 Cycles
> STR R4,[R0,#0x00] +2 Cycles
>
> T1TC = 6; //RESET TIMER.
> MOV R4,#0x06 +1 Cycle
> LDR R0,[PC,#0x0074] +3 Cycles
> STR R4,[R0,#0x00] +2 Cycles
> T1MR0 = 254;
> LDR R0,[PC,#0x0074] +3 Cycles
> STR R3,[R0,#0x00] +2 Cycles
>
> T1MCR = 0x00000003;
> MOV R3,#0x03 +1 Cycle
> LDR R0,[PC,#0x0070] +3 Cycles
> STRH R3,[R0,#0x00] +2 Cycles
>
> T1PWMCON = 0x0000000F;
> LDR R0,[PC,#0x0070] +3 Cycles
> STR R2,[R0,#0x00] +2 Cycles
>
> //Start timer 1
> T1TCR = 0x01;
> LDR R0,[PC,#0x0070] +3 Cycles
> STRB R1,[R0,#0x00] +2 Cycles
>
> ***************************************** # of cycles = 37
>
> So I checked that count with the signals on the scope, and all
> matches, but what I don't get is why I need to set T1TC to 6. to in
> fact get 36 PCLK cycle. is there any reasons to that?
> I don't have wait states, MAM is fully enabled and MAM timing is 4.

Don't know if this explains all of your T1TC=6, but...

You do have waitstates when reading or writing from/to the timer registers,
they are inserted by the APB bridge. If APBDIV=1, each of your STR and STRB
take 7, not 2, cclks. If APBDIV>1, the number of cclks added is larger
since some of the 5 wait states are of the slow pclk kind. I haven't
measured how much larger. Note that the Keil simulator doesn't know about
the APB or MAM waitstates so it incorrectly thinks a load always takes 3 and
a store 2 cclks.

The point of the fast GPIO in LPC214x and LPC2101,2,3 is that access to the
new FIO registers don't go through an APB bridge, and they don't get these 5
waitstates. The timers, and other peripherals, do get them.

Some of your LDR R0,[PC,#xxx] also take more than 3 cclks because of MAM
waitstates. For at least every fourth LDR, the MAM needs to fetch a new
16-byte block from flash which adds 3 cclks (with MAMTIM=4). The MAM only
fetches instructions invisibly ahead, not flash data.

If you use APBDIV=2 or 4, pclk, and the timer tick rate, get
correspondingly slower than cclk, so the last timer needs fewer counts of
head start.

You'll make the cycle counting easier by having the T2TCR=0x01 and the
T1TCR=0x01 as close together as possible, after having initialized all the
other T1 and T2 registers. If you have any interrupts enabled at that time,
you have to disable interrupts around the T2TCR and T1TCR writes so an
interrupt doesn't get in between and invalidate the clock counts completely.

You also make the cycle counting somewhat easier by using APBDIV=1 so that
pclk = cclk. Unless the CPU spends most of the time idle, the power saved
by using a slower pclk is minimal.

If power is an issue, you should of course turn off all unused peripherals
in PCONP. Be aware of the error in the LPC2103 manual, see
http://groups.yahoo.com/group/lpc2000/message/12737 .

Karl Olsen