# Cypress Developer CommunityTM

## A PWM Algorithm Realized With Only One Add Instruction

Summary: 25 Replies, Latest post by fyzhu on 28 Aug 2013 08:33 PM PDT
User
14 posts

A PDM Algorithm Based On Addition

This algorithm is described in my Chinese blog “A PWM Algorithm For Software And Hardware Realized With Only One Add Instruction”. And an example implemented by hardware (UDB datapath) and software respectively on PSoC 4 pioneer kit is also included - ZhuPDM8(PSoC Creator 2.2 SP1).rar .

The blog is written in Chinese , but the programming language is common.

http://blog.chinaaet.com/detail/33332.html

http://files.chinaaet.com/files/blog/2013/07/21/ZhuPDM8(PSoC%20Creator%202.2%20SP1).rar

User
1362 posts

A clever approach. However, with N =2 and 1 =1, the output duty cycle would not be 50% as there is more CPU cycle in one half of the operation. The slower the CPU the higher the error.

User
14 posts

What's wrong?

MATLAB shows the duty cycle is 50% for N=2 and H=1:

>>

npulse = 8;

N = 2;

H = 1;

CNT = 0;

disp( '     k  Pout for init. CNT=0' )

for k = 1:npulse

CNT = CNT + H;

if CNT >= N

CNT=mod(CNT,N) ;

Pout = 1 ;

else

Pout = 0 ;

end

disp( [k Pout] )

end

k  Pout for init. CNT=0

1     0

2     1

3     0

4     1

5     0

6     1

7     0

8     1

>> ...

k  Pout for init. CNT=1

1     1

2     0

3     1

4     0

5     1

6     0

7     1

8     0

User
1362 posts

The difference between the two condition is one with the % instruction,  and the other does not.

My answer is runing it from a 'CPU'. The CPU needs to process the % instruction.

You can compile the code and check the difference of instructions.

User
14 posts

Hi H L,

I don't think there is any difference between the mod() and the %-operator.

The debug result (see attached screen copy) of following programm runing in a real CPU with the %-operator

shows the same duty cycle of 50%.

void main()

{

uint16 N = 2;

uint16 H = 1;

uint16 CNT = 1;

uint8 Pout[8];

uint16 k=0;

do {

CNT += H;

if (CNT >= N)

{ CNT %= N ; Pout[k] = 1 ; }

else Pout[k] = 0 ;

k++;

}while(k<8);

for(;;) {    }

}

May the defferent compiler cause the defferent result of %-operator ?

http://files.chinaaet.com/images/blog/2013/07/24/442064405399.jpg

User
1362 posts

the problem is having to do the mod function( % or MOD). try write down the operation needs to be done, consider you are the computer. you can see that the no. of operation is different from 1 to o and from o to 1 is different.

User
1362 posts

Assume there is a function delayInSeconds().

And added the call to the function in RED as in the following.

***********

do {

CNT += H;

if (CNT >= N)

{ CNT %= N ;  delayInSeconds(99); Pout[k] = 1 ; }

else ( delayInSeconds(1) ;  Pout[k] = 0 ; }

k++;

}while(k<8);

***********

you have a delay of 100 seconds in one condition and 1 second in other condition. The duty cycle is around 1%, but the array Pout[] didn't show that because it doesn't capature the time information.

User
1362 posts

Sorry, a typo.

you have a delay of 99 seconds in one condition and 1 second in other condition. The duty cycle is around 1%, but the array Pout[] didn't show that because it doesn't capature the time information.

User
14 posts

Is OK for following sentanses?

CNT += H;

if (CNT >= N)

{ Pout = 1 ;  CNT %= N ;}

else Pout = 0 ;

or

CNT += H;

if (CNT >= N) Pout = 1 ;

else Pout = 0 ;

CNT %= N ;

But maybe some one says : the if-branch and the else-branch use different numbers of CPU instructions.

And even in hardware imlemention with datapath there still has the difference of a few nano-seconds

caused by the difference between the pulse rise time and the pulse fall time. The duty cycle is not 50% in absolutely accurate meaning.

In my blog above, i just give a principle of the algorithm in style of C. In the real projects, I usualy use assembly language for software realization, and always pay attantion to minimazing the number of instructions and the balance of instruction cycles between branches.

As i declared in my chinese blog, for the convinience of reading i do not use the assembly language to describe the algorithm.

Thank you for your precision of CPU instruction number level.

Any more difference between us ?

User
1362 posts

The first one

********

CNT += H;

if (CNT >= N)

{ Pout = 1 ;  CNT %= N ;}

else Pout = 0 ;

*************

Still has the same issue.

The second one

*********

CNT += H;

if (CNT >= N) Pout = 1 ;

else Pout = 0 ;

CNT %= N ;

****

doesn't has that issue.

My intention is not for the timing of different type of instruction as It would be different with CPU with branck prediction or newer and faster CPU with tricks to work faster. And I am not trying to argue about the ns different in rising or falling edge of the pulse.

My intention is that your orignal method of prove missing important information about the out come. For a fast CPU the different is very small. The bigger the number is N, the smaller is the error as well.

But as I mention before, it is a clever way to doing it.

User
1362 posts

And as you mentioned. Using assembly language would give more accuray timming of the pulse.

A word of caution: The code is good as a concept. But in real life that with ISR or the PWM routine is part of a main loop, the timming would be complicate/inpossible  to calculate.