PSoC 16-Bit PWM generation C Language

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable
        Hi all , i am working with PSoC 5LP. I have continious changable Analog Signals. I convert it to Digital with help of ADC. From this Result i want to generate PWM (Output1 Forwards, Output2 Ruckwards). All in 16-Bits. So i have range upto 65536. I have Analog Input 0,1 to 3,3v. So if i gave Input 1,6v than i have 50% Duty Cycle of generated PWM. PWM Basic Configuration: 16-Bit UDB PWM Mode: Two Outputs Period: 65535 CMP Value1: 32767 CMP Value2: 32676 CMP Type 1: Less CMP Type 2: Greater Dead Band: Disable Interrupt: None Clock with 12MHz freq. Here is the code. In ADC_Result i have 12-bit ADC result. From this result i want to generate 2 PWM Outputs. I know that i have to use WritePeriod(), WriteCompare(), WriteDeadtime() APIs. Code: int32 ADC_Result; uint16 i=0; int pwmValue, pulseWidth; int main() { // Start the components Sys_Init(); // CyGlobalIntEnable; // Uncomment this line to enable global interrupts. // Start Clock & PWM Clock_Start(); PWM_Start(); while(1) { pwmValue = ADC_Result // Which equation i have to use. PWM_WritePeriod(pwmValue); PWM_WriteCompare1(); } } I read the PWM datasheet & also check the Example PWM Programms but still i am much confsed for this following questions. 1. Need i Dead Band? 2. Which equation for converting ADC result into PWM? 3. Need i Interrupt/Global Interrupt ? Regards Shveta   
0 Likes
127 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the fascinating (and sometimes complicated) world of PSoCs!

   

The terms "Forward and Ruckward" are not only telling me that you try to do some direction / motor control, but too that you are from Germany.

   

As for your questions.

   

I cannot see for now that you need an interrupt from the PWM. Nonetheless it would be advisable to have a dedicatet timing of your main-loop since it makes no sense to re-write the compare-value(s) several times before the PWM has completed a cycle. Also there are some issues (look at PWM's datasheet) when re-writing the values on-the-fly.

   

 

   

The differentiation of the foreward and backward direction is easy to be done:

   

Take your ADC-value and subtract the mid-point  (1.6V) from it. When the value is positive, set a variable Direction to TRUE, else set it to FALSE and negate the adc-value. You may drive a pin for the direction or even drive a de-mux, whatever suits you.

   

 

   

Concerning deadband: It is a good idea to avoid noise near your mid-point which is now your zero-point. I would set the PWM when below a to be defined value.

   

 

   

And a last point: It is always the best way to get help when you post your complete project here, so that we all can have a look at. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.



Bob
PS: I'm located near Bremen, and you?

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
        Thank you Bob, pls check the attached file of my Propject. As i Wrote that I had converted 16-Bit ADC Value & i Display it on LCD. Now the first Important question is I want to use this Result as Input for PWM. How can i do this?   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The attached file is just a picture, but not your project.

   

You have to scale the adjusted ADC-value to 0..65000 for youre PWM's compare-value, just some interpolation as

   

f(x) = a *x +b where you might see that b is equal to zero (0)

   

 

   

Bob

0 Likes
Anonymous
Not applicable
        Hello bob, I got my answer. I have ADC result in one variable named "ADC_Result". So for PWM Input I use this variable value further. Now I go to next Step. I have continious Analog Input. After getting this Input i Convert it to digital with ADC. Now fromn this REsult i want to go further with PWM. I have Input range 0 to 3,3v. For E.g. If i have Input value 1,6v than i get PWM Signal with 50% Duty cycle. But what i have to write in my Program? I need one equation to generate PWM But which one? Regards Shveta   
0 Likes
Anonymous
Not applicable
        I don't understand ur euation Bob.   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Well, let ADCMax be the result of converting 3.3V

   

At 1.65V you have to set your compare-value to 32768 which is half of your period so 50% duty-cycle.

   

 

   

So Compare_Value = PWM_Period / ADCMax * ADC_Value.

   

This calculation will deliver bad results when performed in pure integer arithmetic du to overflows and roundings, so better calulate in float or int64.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi bob, thanks for Explanation . I do this calculation in float.

   

I understood the ADC_Max & ADC_Result. Can u pls tell me abt  "PWM_Value"(Initial Value) ? which u wrote in Equation.

   

 

   

Regards

   

Shveta

0 Likes
Anonymous
Not applicable

I have doubt abt "PWM_Period"

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The PWM_Period is the value you set in the properties window for your PWM or, when later set by the program (which you normally do not need to).

   

 

   

Bob

0 Likes
Anonymous
Not applicable
        Hello Bob, I try to implement it in Programm. For Output i already attached Osciloscope on Output pin. So i can easily watch PWM Signal. AS Input i gave 1,6v. After doing this Programm i got no Output signals. Pls chech program in attached file   
0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Your input range, 0.1 to 3.3v, is that desired or would you rather

   

have 0.0 to 3.6 ? If so disable the DelSig input buffer and you

   

will get a range down to 0.0

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable
        No, i have 0 to 3,3v Input range   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I already showed you how to post a project, can you please follow that instruction.

   

"And a last point: It is always the best way to get help when you post your complete project here, so that we all can have a look at. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file."

   

 

   

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
        Hello bob, pls find my Project in attachment   
0 Likes
lock attach
Attachments are accessible only for community members.
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

First thing I realized is that you are using outdated components. I would suggest you to update Creator to latest version.

   

I took the freedom to change some of your code, have a look into the attached project.

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

You might want to make your reference 6*Vref. Reason is if you care

   

about absolute accuracy. If ref is Vdd, that typically is derived from a

   

3 term regulator, which is accurate to 5% typically. Stated another way

   

thats 1 part in 20 or effectively 4.5 bits absolute accuracy. So your 16 bit

   

A/D becomes 4.5 bits. Unless you use an actual external reference to

   

supply chip Vdda.

   

 

   

Note setting ref to 6*Vref does not mean PSOC can take 7.5 volts as an in

   

put, thats just telling you the effective slope gain of the A/D, you are still

   

constrained to ~ the supply rails, see properties window graphic.

   

 

   

Regards, Dana.

0 Likes
SuMa_296631
Level 5
Level 5
50 replies posted 25 replies posted 10 replies posted

I generally get a bit concerned when the design criteria is 16 bits - that means being able to distinguish 1/655536th of the full scale range. In reality noise will often limit you to 10 ot 12 bits or effective accuracy at best (8 bits is typically what I find is practical).

   

Also the more bits you try to use, the slower the measurement process becomes and the more costly the electronics is.

   

When I discuss this with people, my question is "what different decision can be made or outcome will occur if the least significant bit changes" an dthe answer is generally "none". So you look at the next bit and ask the same question until you get to the number of bits where a difference CAN be detected.

   

In this case, you can look at the frequency steps that 16 bits will give you compared to the frequency discrimination the human ear is capable of. Looking at (for example) 'www.cochlea.eu/en/sound/psychoacoustics/pitch' it says the discrimination limit is 0.0035 which is about 1 in 286 - rather close to 256 which is 8 bits. Then you can add a few bits 'for luck' (actually to give you a few guard bits) which is why I've have never needed more than 10 bits for anything I've been involved with.

   

Susan

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Susan,

   

I fully agree with you! I'm afraid that (exept you) only Dana frequently hints to "calculating an error budget".

   

Yes, it is tempting when you can have 32 bits just to use 8 bits and still be in the range of 1% uncertainity, having an output with higher frequency (if I like to) which is easier to filter (if I need to) and consuming fewer resources (if I want to).

   

Even the incoming 16 bits from ADC in this example could be reduced, filtered at need to reduce noise using CPU or Filter component.

   

I believe that Shveta is in the state of exploring the world of PSoCs, bringing first this, then that component to life to get a "feeling" how to handle this complex but easy-to-use chips (if you know how).

   

 

   

Bob

   

Greetings to Australia! My daughter just emigrated to that beautiful country!

0 Likes
Anonymous
Not applicable
        Thank u Bob, The program runs perfect. I have some doubts in program. 1. PWM_Period 60000u for 200 Hz frequency. why u took 60000u. If i want to change it then how can i calculate it? 2. Why u enable Global interrupt ? After this i have to do PWM with 1kHz schnitt(Deutsch wort). How can i do this? pls find the accual PWM Output which i have to do in attached file Regards Shveta   
0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
        Thank u Bob, The program runs perfect. I have some doubts in program. 1. PWM_Period 60000u for 200 Hz frequency. why u took 60000u. If i want to change it then how can i calculate it? 2. Why u enable Global interrupt ? After this i have to do PWM with 1kHz schnitt(Deutsch wort). How can i do this? pls find the accual PWM Output which i have to do in attached file Regards Shveta   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Divide your clock frequency by the period value and you get the frequency. Choosing the right combination will give you any wanted frequency.

   

I generally enable global interrupts. This saves me from forgetting to enable them when needed which often comes quickly.

   

 

   

Bob

   

PS: Again, Which city do you live in?

0 Likes
Anonymous
Not applicable
        Thanks Bob, So if i wanted to give 80 kHz frequency, than i have 12,5ms (1/80000). For doing this what i have to write in program? Did u check my last attached doc? For first Step i want to Start PWM-1, than after some time start PWM-2. Can u pls suggest me for this? Regards Shveta PS: I am living near Hannover.   
0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

The relationships for a PWM are -

   

 

   

PWMoutfreq = PWMclk / PWMperiodvalue

   

PWMoutdutycycle = ( PWMcomparevalue / PWMperiodvalue ) X 100%

   

 

   

Both PWMperiodvalue and PWMcomparevalue have API that allow you to write

   

the respective PWM registers.

   

 

   

To start PWM2 after PWM 1 you could -

   

1) Issue a start of PWM1_Start( )  then issue PWM2_Start( ). This method is imprecise.

   

2) Use a LUT or a counter or a timer to count off a predetermined number of clks

   

from PWM1 and use that to set a "D" to enable PWM2. This methoid then would be more

   

precise.

   

 

   

Regards, Dana.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
        Hello dana, thank u. I tried it in my Program. Pls check it. Am i going in right way? pls find Output file in next reply Regards Shveta   
0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
        Here is the Output file   
0 Likes
Anonymous
Not applicable
        Hi Bob & Dana, Thanks for your suppoert & ideas. Before my all last questions i have to do this. I have Analog Input from 0 to 3,3v. From ADC i get answer into uint16 ("ADC_Result" in attached Project). Now i want to divide this result to get PWM Period time. if Input 0,2v then PWM_Period = 149...this value increses with uptp 3,3 v. Last value for PWM_Period = 479. how can i do this?   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You are on a wrong track: The PWM period should be kept fixed and only the compare-value should change.

   

The little bit of math needed is already explained in the previous posts (Dreisatz / rule of three).

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Are you trying to make a V to F or V to DC (Duty Cycle) converter ?

   

 

   

In the former case you would write the period register and then write

   

the compare register with a value of period / 2 to keep a square wave 50%

   

duty cycle waveform.

   

 

   

In the latter case you write only the compare register. Note you would have to scale

   

the A/D result so that at max value its scaled value to be written to PWM compare

   

register is < period, otherwsie if it is >= then the output would be a logic "1" DC value.

   

 

   

Scalefactor = (PWMperiodvalue - 1) / ADCmaxvalue

   

PWMcomparevalue = Scalefactor * ADCvalue

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

I am not sure I understand your pic below.

   

 

   

Does this imply PWM2 only once generates a pulse during the "0" time of PWM1,

   

or do you want PWM2 to follow every PWM1 "1" pulse with a PWM2 pulse in PWM1's

   

"0" time ?

   

 

   

What if PWM1 duty cycle approaches 100%, then there is no time left to make a PWM2

   

pulse inside the PWM1 low time.

   

 

   

What is TD1 ? A fixed number of PWM1's input clock time ? If so how many clocks ?

   

 

   

Regards, Dana.

   

 

   

0 Likes
Anonymous
Not applicable
        Hi Bob & Dana, I will clear ur all douts later. First pls clear my doubt for reading Pin value. AS i told i have continious Analog value on Pin P0_7. For this i wrote this Programm. But it display only 00 on LCD. uint8 Input_Val; // Input Pin Value Pin0_7 Input_Val = CyPins_ReadPin(Pin_Input_0); LCD_ClearDisplay(); LCD_Position(1u,0u); LCD_PrintInt8 (Input_Val); while(1) { } pls give your suggestions. Regards Shveta   
0 Likes
Anonymous
Not applicable
        When my Input Voltage is < 0,002 & > 3262. then in LCD Displays only 3299 or 3266. So before doing ADC i want to check the value of Input pin value.   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You cannot read the analog voltage of a pin with Pin_Read(), this will always return the corresponding digital value.

   

 

   

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hello Dana & Bob

   

@ Dana  I want to do V to F converter.

   

For Output i have two individual PWM. PWM1 work as Master & PWM2 work as Slave.

   

First generate PWM1, after sometime PWM2 generats. PWM1 & PWM2 have always 49% Duty cycle of Total Period.

   

Before PWM1 falling Edge PWM2 fall before sometime.

   

Td1 = sometime

   

Td2 = Before sometime

   

This is the Starting Generation of both PWM signals.

   

pls find my Project in this Forum

   

In 2nd Post find PWM_Output file

   

In 3rd Post find PWM Input file.

   

Regards

   

Shveta

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

PWM Output file in attachment

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Pls find PWM Output Generation table in Attachement.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

@ Dana  I want to do V to F converter.

   

For Output i have two individual PWM. PWM1 work as Master & PWM2 work as Slave.

   

First generate PWM1, after sometime PWM2 generats. PWM1 & PWM2 have always 49% Duty cycle of Total Period.

   

Before PWM1 falling Edge PWM2 fall before sometime.

   

 

   

From the above I understand -

   

 

   

1) Using A/D you want to convert voltage into a frequency, and that the frequency out has a duty cycle

   

as close to 49% as possible. This means when you write PWM period value, for example 1000, you also

   

follow it with a compare value write, in this case 500, and that compare logic has been set up for "<". Note

   

if you do not want a temporarily distorted signal, eg say your old PWM period was 1000, and compare value

   

was 500, and new PWM period is 2000, if you write the period for some cycles the duty cycle would be ~ 25%

   

until the new compare value (1000) was written. Way to handle this is to stop PWM, do both writes, then start it again.

   

 

   

Actually in my example you have to comparevalue = .49 x periodvalue. So above should have been 490 in first

   

case, and 980 in second case. In order to get 49% duty cycle.

   

 

   

2) PWM2 frequency same as PWM1, but after a delay ?

   

 

   

3) PWM2 duty cycle always < PWM1 ?

   

 

   

4) For Vin = 0V PWMfreq = ? Hertz

   

 

   

5) For Vin = 3.3V (your limit) PWMfreq = ? Hertz

   

 

   

Note question 4 & 5 asked because right now you have a V to Period to 1 / Frequency converter, stated

   

another way as V goes up do you want F to go up or down ?

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana
1. I already converts Volts into Digital using ADC & answer store in ADC_Result1 in my attached Project. [In comment line i convert it into Freq. Variable Comp_Val. But i m not sure that for my requierment i m right or wrong..??]

   

2. ya, PWM2 freq. same as PWM1.i Need bit delay for starting of PWM2.

   

3.No. PWM2 Duty cycle[49%] = PWM1 Duty Cycle [49%] = Same Duty cycle for both PWMs.

   

4.For Vin = 0,5v PWMfreq = 250kHz
5.For Vin = 3,25v PWMfreq = 80kHz

   

So i have when V goes up, F go down.

   

Regards
Shveta
 

0 Likes
Anonymous
Not applicable

@Bob

   

ya, i searched it but i cannot read analog Input voltage.

   

I want to make Error handling after Input.

   

For voltage Input < 0,002 & max > 3,262 then LCD Display 3299 & 3266. At this time i want to Display on LCD "Invalid Input".

   

For that i wrote in my last attached Project. Pls check it. Am i doing right ?

   

Regards

   

Shveta

0 Likes