cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

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
JoMe_264151
Expert II

It is not helpful for you to declare two values as errors, better would be to check where errorneous values come from. What comes to my mind is: You declared ADC_Result as an uint16, but you use it with routines that expect/deliver 32-bit results.

   

I would at first suggest you to declare ADC_Result as uint32 and remove the typecasts you used.

   

When I open your project I am informed that there are newer component versions availlable, it can be advisable to update your Creator to latest SP2.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

thanks bob,

   

I remove typecasting from Programm. All for uint16, GetResult16().

   

But still i get the Error value.

   

I think i stay with my last updated Programm.

   

Once i updated the PSoC Version i got error. So i don't want to Change it.

   

Regards

   

Shveta

0 Likes
JoMe_264151
Expert II

The datasheet tells you to useGetResult32() when the precision is set to 16 bits and I advised you to change the

   

variable ADC_Result to

   

uint32 ADC_Result;

   

 

   

Bob

0 Likes
Anonymous
Not applicable

@ Bob

   

thanks. I do it ADC_Rssult to uint32. then i get value 3300 for 0,0 Volt.

0 Likes
JoMe_264151
Expert II

This is something I really doubt! the result is showing 3.3V which is the maximum voltage.

   

What is the external connection you made and how do you measure the incoming voltage?

   

 

   

Bob

0 Likes
ETRO_SSN583
Esteemed Contributor

To compute the divider values then from your response

   

  

   

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

   

 

This defines an equation that looks like -

   

 

   

 
Freq = gVin + Offset     where g = slope of line and Offset = Freq for Vin = 0.0

   

  
So        g = ( 80000 – 250000 ) / ( 3.25 - .5 )  = -61818 Hz / Volt

   

 So        Offset = Freq – gVin = 250000 – ( -61818 x .5 ) = 250000 + 30909 = 280909 Hz

   

 Then Freq = -61818 x Vin + 280909

   

 

   

 
Periodvalue     = 12 Mhz / Freq = 12000000 / ( -61818 x Vin + 28909 )

   

Comparevalue = .49 (49% duty cycle) x Periodvalue

   

 

   

 

   

So do this computation as floats then when you have period and compare values

   

 cast back to uint16 to write to period and compare registers of PWM. In case of

   

 floats add .5 to final value to do roundoff to closest integer value when cast back

   

 to uint16.

   

 

   

 

   

Also remember your Vin value is in milivolts, so convert it to Volts for the equation

   

 by dividing it by 1000. First cast Vin to a float, then do the divide.

   

 

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Esteemed Contributor

Another issue is resolution of Frequency/Period of the PWM.

   

 

   

Right now you use 12 Mhz which translates to 83 nS, which in turn

   

translates to an equvalent frequency step per count of PWM. If you

   

need finer resolution use a faster clock, but then check endpoints in

   

the equation to make sure they do not exceed 16 bits in divider value.

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Esteemed Contributor

I am going to take a stab at this to see if I can implement

   

the timing on PWM2 for you. Note the register will be used

   

to synch start both PWMs, and the SR will delay (for now)

   

by 8 clocks the start of PWM2. I think by using a slightly

   

smaller PWMcomparevalue in PWM2 vs PWM 1 that will also

   

take care of the trailing edge problem.

   

 

   

0 Likes
ETRO_SSN583
Esteemed Contributor

The basic approach seems to be working but I am having issues getting

   

PWM2 falling edge to occur before PWM1 falling edge. SR sets up delay

   

on rising edge of PWM2.

   

 

   

Not I did this on a -050 DVK, you will have to reassign pins/ports.

   

 

   

0 Likes
ETRO_SSN583
Esteemed Contributor

Well if I had taken the time to read the datasheet this is all it takes -

   

 

   

0 Likes
ETRO_SSN583
Esteemed Contributor

With this lashup I get the following -

   

 

   

1) At Hi freq DC of both waveforms ~40%

   

2) At Low freq DC of both waveforms ~ 47%

   

3) Delays, deadband,  are ~ 300 nS between PWM 1 and PWM2. The deadband

   

can be increased at the expense of DC dropping.

   

 

   

Project attached.

   

 

   

Regards, Dana.

   

 

   

0 Likes
Anonymous
Not applicable

@Dana,

   

I tried ur last Project. It works same for the Kind of PWM which i want to generate.

   

1 big Problem is , as i have continiously Changing Analog input values. Because of ISR in ADC i have to Reset each n every time when i get new Input.

   

Can we do something for this?

   

N ya i Need finer signals so want to Change PWM Clock Freq. pls tell me which can be better for my application.

   

Regards

   

Shveta

0 Likes
Anonymous
Not applicable

@ Bob,

   

U r right. I get some garbage values.

   

I want to set if Analog Input is < 0,5 then it Stay 0,5.  For Maximum if Analog Input is > 3,25 then Stay it 3,25.

   

For that i check ADC_Result variable in my Programm but LCD Display some other values.

   

pls suggest me for this.

   

   

 

   

if

{

(ADC_Result1 == 3300 ) // Input Freq < 0,5 then stay 0,5
   

LCD_PrintString(

}

{

LCD_PrintString(

 }

@ PS : I updated PSoC Creator

    "< 0,5"    );     ADC_Result1 = 1000;        else        if    ( ADC_Result1 == 3265)     // Input Freq > 3,25 then Stay 3,25        "> 3,25"    );     //ADC_Result1 = 3254;
0 Likes
ETRO_SSN583
Esteemed Contributor

1 big Problem is , as i have continiously Changing Analog input values. Because of ISR in ADC i have to Reset each n every time when i get new Input.

   

 

   

What do you have to reset, what is "n" ?

   

 

   

N ya i Need finer signals so want to Change PWM Clock Freq. pls tell me which can be better for my application.

   

 

   

If you want finer delay/deadband control raise the clock frequency. Right now the incremental delay is

   

based on 12 Mhz = 83 nS increments of control. Using a 24 Mhz clock would give you ~ 42 nS. Note

   

that becomes the new clock freq in the equations to compute PWM period and compare values. You also

   

would have to reset in PWM global properties the number of clocks of deadband to get the desired

   

deadband timing.

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Esteemed Contributor

One point of clarification, your picture of waveforms showed that

   

PWM2 DC < PWM1 DC, yet you stated you wanted them both to

   

have the same DC. That is a conflicting statement of requirements.

   

 

   

If you want deadband then inherently PWM DC 1 > PWM2 DC,

   

Or freq would have to be lower for PWM2 to get same DC as PWM1.

   

 

   

Regards, Dana.

0 Likes
JoMe_264151
Expert II

Quite easy: you wrote

   

if Analog Input is < 0,5 then it Stay 0,5

   

In C-Language you can write

   

if(ADC_Result < 500) ADC_Result = 500;  // 500mv

   

and you wrote

   

if Analog Input is > 3,25 then Stay it 3,25.

   

This you can translate yourself into C

   

 

   

Bob

0 Likes
Anonymous
Not applicable

@ dana

   

Sorry. I made mistake to draw picsture.

   

The DC for both PWM will Same.

0 Likes
ETRO_SSN583
Esteemed Contributor

Then the solution would change to a simple PWM, no deadband, and use a shift register to

   

delay PWM1 waveform, the output of the shift register becomes PWM2. Note that means that

   

PWM2 leading edge occurs after PWM1's, and PWM2's trailing edge also occurs after PWM1's

   

trailing edge.

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Esteemed Contributor

So this would be basic approach.

   

 

   

   

 

   

The clock to SR and its length determine delay from PWM1 out to PWM2 out. Don't

   

forget in initialization to start ShiftReg.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana

   

1 big Problem is , as i have continiously Changing Analog input values. Because of ISR in ADC i have to Reset each n every time when i get new Input.

   

I mean Each & Every changed analog Input i have to Reset my Hardware Board.

0 Likes
ETRO_SSN583
Esteemed Contributor

Revised project attached.

0 Likes
ETRO_SSN583
Esteemed Contributor

@Dana

   

1 big Problem is , as i have continiously Changing Analog input values. Because of ISR in ADC i have to Reset each n every time when i get new Input.

   

I mean Each & Every changed analog Input i have to Reset my Hardware Board.

   

 

   

 

   

I do not understand why an ISR is causing any reset activity of anything ?

   

 

   

 

   

Note I put this test in code to eliminate constant PWM update in the presence of noise -

   

 

   

            if ( ( ADC_Result > ADC_Result_Old + 10 ) || ( ADC_Result < ADC_Result_Old - 10 ) ) {       // Only update PWMs if A/D has changed > +/- 10 mV
 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana

   

Thank u very much. My Project works. Sorry for requirment Change. I was corrrect before. Both PWM DC is different & i need deadband. pls check my attached Project.

   

One Problem is when the Input value is 0 then it's 80kHz but when i start to give value than it jumps directly from 80kHz to 250kHz. Accually i want to give like if Input value < 0,5v then stay 250kHz & if Input value > 3,25v then stay 80kHz.

   

For that i try in my program but it's not working.

   

My new requirment is i Need 1 more 16-Bit.ADC for getting CMP value as Input.

   

For that i took one more Del_Sig_ADC in my Project. But when i run it i got Error named

   

   

Regards

   

Shveta

 

 

 

 

    

 

   

 

   

Maximum number of DSM Fixed Blocks exceeded.

   

   

Maximum number of DSM Fixed Blocks exceeded

0 Likes
ETRO_SSN583
Esteemed Contributor

If Input signals < 0,005 then Stay Freq. 80kHz & if Input signals > 3,25 then Stay Freq. 250kHz.

   

 

   

This should read per your prior instructions

   

 

   

If Input signals < 0,005 then Stay Freq. 250kHz & if Input signals > 3,25 then Stay Freq. 80kHz.

   

 

   

But then you earlier stated range was to be

   

 

   

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

   

 

   

So your test is inconsistent ? Should test limits be 0.5 V = 250 Khz and 3.25V = 80 Khz ?

0 Likes
ETRO_SSN583
Esteemed Contributor

Here is what I believe final project. Note don't forget

   

to reassign pins/ports. Also the accuracy of the internal

   

clock will be reflected in output frequency, so if you need

   

80Khz and 250Khz to be very accurate, consider an external

   

xtal clock.

   

 

   

One additional, the pwm values are -1 for entry, whcih I did not do, so they should be

   

changed to

   

 

   

                // For Vin = 0.5v PWMfreq = 250kHz then PWMperiod = ( 12000000 / 250000 ) = 47 as an integer ( -1 value to be written)
                // For Vin = 3.25v PWMfreq = 80kHz then PWMperiod = ( 12000000 / 80000 ) = 149 as an integer ( -1 value to be written)
                //               
 

   

and then try changes in compare values to get closer to 49%. Also try a faster clock for PWM, and

   

recompute equation,. etc., for best performance.

   

 

   

                if ( ADC_Result1 < 500 ) {                                          // Force PWM to stay at 250 Khz for < 500 mV input
                   
                     PWMperiod = 47.;                                               
                     PWMcompare = 24.;
                }
               
                if ( ADC_Result1 > 3250 ) {                                          // Force PWM to stay at 80 Khz for > 3250 mV input
                   
                     PWMperiod = 149.;                                               
                     PWMcompare = 75.;
                }
 

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana  Thank u very much. It works perfect.

   

Regards
Shveta
 

   

 

   

@Dana I have to give CMP Value as Input. For that i took AMux. & connect both my Input Pins to it & AMux to ADC. I am using EOC Interrupt . So thew question how can i jump from 1 channel to another .For that i tried bit in my project. Pls check the attached Project.

   

   

Hier is the CMP_Input configuratiuon.

   

Max 3,25v == 1ms

Min 0,5v == 250us

For both this Freq_Input & CMP_input have to generate PWM.

Regards

Shveta

0 Likes
ETRO_SSN583
Esteemed Contributor

PSOC 5LP parts (most)only have 1 DelSig in them. Best bet is add a mux

   

in front of ADC and code it to convert two channels. You can use a SW

   

or HW mux depending on your requirements. Note this part also has 2 SARs

   

in it, only they are limited to 12 bits, which also can be used with muxes.

   

 

   

Regards, Dana.

   

 

   

   

 

   

My prior comment about increasing clock, I tried it at 48 Mhz, Creator gave

   

me warnings about timing (so I do not reccomend you use 48 Mhz), but

   

it worked with more precision getting close to 49% and less variation from

   

one end of the range to the other. But you could do it with 24 Mhz and improve

   

design.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Thanks Dana.

   

I used it. @PS I try to use 24Mhz unfortunetly the program jumps from 80 to 250 n vice versa. (Don't know Why..??)

   

but now the question is of EOC Interrupt  programming with 2 ADC channel.

   

I Need both channels Output & then to generate PWM.

   

i can't attaach my Project.

   

i try to explain with small code

   

AMux_Select(0);

   

Regards

   

Shveta

   

 

   

{

   

ADC_StartConvert();

   

   

 

   

ADC_StopConvert ();

   

}

   

Am i right here?

   

Because i Need both Freq & CMP converted value before PWM Generation.

0 Likes
ETRO_SSN583
Esteemed Contributor

Basically you have a flag that indicates what channel is being worked on.

   

So when you get an EOC in ISR, you know what mux channel you have selected,

   

you read ADC, then change the flag and mux to next channel.

   

 

   

 

   

Remember to make all variables used volatile. Also check datasheet on settling

   

time for A/D. If its an issue then throw away the first sample, stated another way

   

code to take two measurements each channel, and throw away the first one.

   

You could to a quick test by creating another project and create a quick testbed to

   

evaluate this issue.

   

 

   

From datasheet -

   

 

   

All four ADC modes fully flush the decimator when the ADC initially starts conversions. This ensures that the first reading from the ADC is valid as long as the input voltage is stable before starting conversions with either the ADC_StartConvert() API or when triggered by the “soc” input. Although all modes reset the decimator when starting the ADC, only the continuous mode does not reset the decimator between readings. Because of this, the first reading in continuous mode takes four times longer than the subsequent readings. When using an analog mux to scan between multiple inputs, make sure that the ADC is not running while the input switches are......

   

 

   

This does not mean you cannot use continuous mode, just says beware settling time when

   

changing mux channel.

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Esteemed Contributor

You do not have to stop A/D, just leave it running continuously.

   

 

   

As far as 24 Mhz clock, seems to be working fine here, does your pot (Vin)

   

have issues with its wiper at end of travel ? Here is the code I used -

   

 

   

            if ( ( ADC_Result1 > ADC_Result_Old + 10 ) || ( ADC_Result1 < ADC_Result_Old - 10 ) ) {       // Only update PWMs if A/D has changed > +/- 10 mV
               
                // From equations
                //
                // Freq = -61818 x Vin + 280909
                //
                // Periodvalue = 48 Mhz / Freq = 24000000 / ( -61818 x Vin + 28909 )
                // Comparevalue = .49 949% duty cycle) x Periodvalue
                //               
                //               
                // For Vin = 0.5v PWMfreq = 250kHz then PWMperiod = ( 24000000 / 250000 ) = 47 as an integer ( -1 value to be written)
                // For Vin = 3.25v PWMfreq = 80kHz then PWMperiod = ( 24000000 / 80000 ) = 149 as an integer ( -1 value to be written)
                //               
               
                Freqdesired = ( -61818.0 * (float) ADC_Result1 / 1000. ) + 280909;
               
                PWMperiod = ( ( 24000000. / Freqdesired ) + .5 );
                PWMcompare = ( 0.49 * PWMperiod ) + .5;
               
                if ( ADC_Result1 < 500 ) {                                          // Force PWM to stay at 250 Khz for < 500 mV input
                   
                     PWMperiod = 95.;                                               
                     PWMcompare = 48.;
                }
               
                if ( ADC_Result1 > 3250 ) {                                          // Force PWM to stay at 80 Khz for > 3250 mV input
                   
                     PWMperiod = 299.;                                               
                     PWMcompare = 150.;
                }

                EnabPWMs_Write( 0 );                                                //  Disable PWMs, reset shift reg for delaying PWM2 start

                PWM_1_WritePeriod( (uint16) PWMperiod );                            // Update PWM1
                PWM_1_WriteCompare( (uint16) PWMcompare );        

               
                EnabPWMs_Write( 1 );                                                //  Enable PWMs, enable shift reg for delaying PWM2 start
               
                ADC_Result_Old = ADC_Result1;
                AtoDdoneflg = 0;                                                    // Reset A/D EOC flag
            }
 

   

Regards, Dana

0 Likes
Anonymous
Not applicable

@Dana

   

Thank u very much.

   

Now i try to make equation for PWM CMP value. pls check it. Am i going correct?

   

For Vin = 0,5v PWM_CMP = 250ns (Nenosecond)

   

For Vin = 3,25v PWM_CMP = 1us (Microsecond)

   

Freq = gVin + Offset where g = slope of line and Offset = Freq for Vin = 0.0

   

So g = ( 1000 - 250 ) / ( 3.25 - .5 ) = 272.72 Nenosecond / Volt

   

So Offset = Freq - gVin = 250 - ( 272.72 x .5 ) = 250 + 136.36 = 386.36 Nenosecond

   

Then Freq = 272.72 x Vin + 386.36

   

CMP_Value = ?

   

Regards

   

Shveta

0 Likes
ETRO_SSN583
Esteemed Contributor

When you use this nomenclature PWM_CMP what is this, just the name

   

of another PWM that you want to control as a V to F converter ? Describe

   

what this PWM is being used for.

   

 

   

The eqation you computed is mathmatically correct.

   

 

   

This line you typed -

   

Freq = gVin + Offset where g = slope of line and Offset = Freq for Vin = 0.0

   

Should be changed to -

   

Freq = gVin + Offset where g = slope of line and Offset = Freq for Vin = 0.5

   

 

   

 

   

Regards, Dana/

0 Likes
Anonymous
Not applicable

@Dana

   

CMP is PWM Coompare value. Which i calculated

   

PWMcompare = ( 0.47 * PWMperiod ) + .5;  (AS per my last Project)

   

Now i want to give for this PWMcompare

   

For Vin = 0,5v PWM_CMP = 250ns (Nenosecond)

   

For Vin = 3,25v PWM_CMP = 1us (Microsecond)

   

Regards

   

shveta

0 Likes
ETRO_SSN583
Esteemed Contributor

The compare value does noit have to be computed thru the straight line

   

equation, as I stated earlier its computed -

   

 

   

                // Periodvalue = 48 Mhz / Freq = 24000000 / ( -61818 x Vin + 28909 )
                // Comparevalue = .49 (49% duty cycle) x Periodvalue

   

 

   

It then follows the equation for Periodvalue because it is derived from the

   

straight line equation for Periodvalue. And your requirement the DC be as

   

close to 49% as possible.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Thanks Dana,

   

So now i want to give analog Input for both PWMperiod & PWMcompare (Now no Need of 49% of PWMPeriod) . I Need seprate calculation for PWMcompare.

   

So for PWMPeriod

   

Min 0,5v = 80kHz

   

Max 3,25v = 250kHz

   

For PWMcompare

   

Min 0,5v = 250ns (Nenosecond)

   

Max 3,25v = 1us (Microsecond)

   

Can we do both this calculation?

   

Regards

   

Shveta

0 Likes
ETRO_SSN583
Esteemed Contributor

Yes, you will have the 80 Khz/250 Khz when using the earlier equations,

   

and 1 Mhz/4 Mhz for the compare solution.

   

 

   

Problem is at the 16X faster PWM freq you are going to have very small

   

duty cycle because the dead band clocks eat up a much greator amount

   

of the total clocks to make up the period.

   

 

   

Or is this solution to stay at 80 Khz/ 250 Khz, but DC varies from 1 uS to

   

250 nS ?

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana

   

then what can i do? I have to do this. It's Project requirment. What u suggest ? pls tell me the equation for PWM Compare value.

   

N ya i try with 2 AMux channel for ADC. But i got only 1 Output.

   

Pls find it in attached Project.

   

Regards

   

Shveta

0 Likes
ETRO_SSN583
Esteemed Contributor

My problem is what is the project -

   

 

   

1) A PWM with fixed DC 0f 49% that acts as a V to F converter 80 Khz to 250 Khz

   

 

   

2) A PWM with fixed frequency, and acts as a V to pulse width converter, going

   

from 250ns to 1 uS in pulse width.

   

 

   

3) 2 PWMs, 1) and 2) above ?

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

@Dana

   

Sorry. I understand the requirment wrong.

   

Now In my last Project PWMperiod & PWMcompare(49% of PWMperiod) works perfect. No worries abt PWMperiod & PWMcompare.

   

I want to give Deadband as Input. (For 2-256 Cycles). So here is the Deadband values

   

Min 0,5v = 2

   

Max 3,25v = 24

   

how can i set this in Program? pls find Project design in attachment.

   

Regards

   

Shveta

0 Likes
Anonymous
Not applicable

@Dana

   

Sorry. I understand the requirment wrong.

   

Now In my last Project PWMperiod & PWMcompare(49% of PWMperiod) works perfect. No worries abt PWMperiod & PWMcompare.

   

I want to give Deadband as Input. (For 2-256 Cycles). So here is the Deadband values

   

Min 0,5v = 2

   

Max 3,25v = 24

   

how can i set this in Program? pls find Project design in attachment.

   

Input E.g  Input Freq. = 3,25v

   

then           PWMperiod = 47

   

                   PWMcompare = 23 (49% of PWMperiod)

   

                   Deadtime = 2

   

when Input Freq. decrese then Deadtime increse upto 24.

   

Regards

   

Shveta

0 Likes