cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

Anonymous
Not applicable

hi, i am using CY8C29466-24SXI kit, and i am trying to convert the RPM speed of motor to a frequency from the monitor "n", i have problem with the code, the output is constant and should change when i change the speed of motor

   

the equation should be : Freq(monitor) = [n ( speed[rpm]) * Zpol ( which is 😎 ] / 20

   

thanks 

0 Likes
Reply
32 Replies
Esteemed Contributor

When you do an ISR you have to modify boot.tpl in root project directory to add

   

the vector jump.

   

 

   

You have currently -

   

 

   

   

org 34h ;PSoC Block DBB11 Interrupt Vector

   

`@INTERRUPT_13`

reti

   

   

 

   

This should be -

   

 

   

   

   

org 34h ;PSoC Block DBB11 Interrupt Vector

   

ljmp _ms_Timer_ISR_C

reti

   

   

 

   

Also you did not use the #pragma qualifier when declaring the C intterupt, look at Imagcraft manual.

   

 

   

Regards, Dana.

0 Likes
Reply
Esteemed Contributor

Note the interrupt vector comes from the last block in a timer or counter chain, in your case DBB11.

   

 

   

Regards, Dana.

0 Likes
Reply
Esteemed Contributor

Sorry, forgot to add this -

   

 

   

#pragma interrupt_handler foo

void foo(void) {

   

..

   

..

   

}

   

 

   

Note "foo" is not used with an underscore in the declaration, just in boot.tpl.

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Hi Dana,

   

i have the freqcode.asm, and tickhander.asm and called them in the h file. i am not sure if i have to use interupt for the timer because it should capture from the comparator. can you please be more clear what exactly i am doing wrong?

   

Thanks

0 Likes
Reply
Esteemed Contributor

Do you have a schematic you can post ?

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Hi Dana, here is schematic for my project. basically, i want to take the frequency and put it in the RPM equation to measure RPM of the motor with the voltmeter ( manually ). the thing is the output from monitor is a digital signal (high/low) and is equivlant to a third of the commutation frequency.

   

the equation is: RPM = 2.5 * Freq (monitor)

   

Thanks

0 Likes
Reply
Esteemed Contributor

Basically to measure PW you use a timer, start it on positive edge of

   

input pulse, and either do a capture on 1 edge or an ISR on negative

   

edge. You could also use a counter to do this.

   

 

   

One simple method is use positive edge of pulse to start timer, and negative edge

   

to indicate end of pulse period,. That can be input pin set to ISR on negative edge.

   

 

   

Here is an ap note with several methods. Including an anlog method.

   

That works if freq is a constant.

   

 

   

      http://www.psocdeveloper.com/docs/appnotes/an-mode/detail/an-pointer/an2103/an-file/119.html

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Hi Dana,

   

i tried to fix a project to have a function generator as input signal. and have compare out and terminal count out as outputs,, and connected LED on port 2-0 to check if it is working. for some reason when i connect the generator it doesnt want to compile, but once i take the generator out it compiles but cant test it beacuse of no signal in.

   

FYI, the link you sent earlier, i cant open any of these projects to look at it.

   

 

   

Thanks a lot for your time

0 Likes
Reply
Anonymous
Not applicable

it works, but the terminal count out i have nothing comes out, and compare out is same as signal i am putting in.

0 Likes
Reply
Esteemed Contributor

I am at a remote site, do not have my cube with me for debugging, but here

   

is what I see -

   

 

   

1) boot.tpl. root directory you have to modify vector table to do the ISR vector to TachTimer16_MSB_ISR()

   

Edit boot.tpl vector table to reflect this change

   

 

   

   

org 24h ;PSoC Block DBB01 Interrupt Vector

   

`@INTERRUPT_9`

reti

 

to

 

org 24h ;PSoC Block DBB01 Interrupt Vector

ljmp _TachTimer16_MSB_ISR

reti

  

   

   

 

   

2) In TachTimer16INT.asm I think the call name TachTimer16_MSB_ISR

   

must be changed to _TachTimer16_MSB_ISR, not 100% sure about this,

   

but I think that is the case.

   

 

   

3) The programming pins on the 29466 are Vdd, Vss, XRES, SCLK, and SDAT, so if you

   

are using any of these in design they have to be disconnected to program.

   

 

   

4) Function generator putting out 0 - 5 V, not some negative voltage to 5V ? You

   

have offset its output waveform, right ?

   

 

   

Regards, Dana.

0 Likes
Reply
Esteemed Contributor

Some other observations -

   

 

   

1) Any reason for running the part not full speed at 24 Mhz ? Why waste MIPs (unless trying to save

   

power) available.

   

 

   

2) If you have a port with mixed I/O, you need to use shadow registers -

   

      http://www.cypress.com/?id=4&rID=28251

   

     
http://www.planetpsoc.com/psoc1-articles-digital/13-basics-of-psoc-gpio.html?start=5
 

   

 

   

3) ISR notes -

   

http://www.cypress.com/?id=4&rID=36720

   

]     http://www.planetpsoc.com/component/content/article/43-writing-a-c-isr.html

   

      http://www.planetpsoc.com/psoc1-articles-digital/13-basics-of-psoc-gpio.html?start=7

   

 

   

4) I was wrong on call inside TachTimer16INT.asm,  you do not need the underscore as

   

you are calling an asm(), not a C f().

   

 

   

Regards, Dana.

0 Likes
Reply
Esteemed Contributor

One last, I am so used to writing C interrupts that I forget when not to use

   

the _ preceding a call.

   

 

   

When I discussed boot.tpl, I indicated to put the underscore preceding that call,

   

but you are calling an asm function, so leave it off, should be -

   

 

   

ljmp TachTimer16_MSB_ISR

   

 

   

Bonehead I am.

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Hi Dana,

   

i think i am too close now, i have it working but my output ( Compare out ) on PORT0-0 is always zero, it doesnt update with the frequency.

   

i wont be able to debuge it by LCD, however can i tested by Multimeter?

   

thanks

0 Likes
Reply
Anonymous
Not applicable
0 Likes
Reply
Anonymous
Not applicable

here is the file

0 Likes
Reply
Esteemed Contributor

Maybe start at the basics for a moment.

   

1) To measure PW we use counter or timer.

   

2) Since all PSOC 1 counter/timers (C/T) are down counters, we load
them with a full scale value, in your case you have chosen 65000.
Normally for a 16 bit C/T you would use 65535.

   

Timer solution -

   

3) We start the Timer on the positive edge of the input signal whose
pulse width we want to measure. So we have the starting value of the
period register, which is 65000 in your case. We start it with an ISR
from the positive edge of the input signal (via pin configuration), and
 read the timers count register in this ISR opr set a flag to do so.
 Remember Timer runs continuously unless you stop it.

   

4) Timer continues to run, counts dropping in its counter register, then
input signal drops, triggering a capture event (another ISR). Now we read
timer count register giving us counts at end of its pulse. So we take start
counts and subtract capture counts. Note, there is a problem, if timer over-
flows, ie counts to 0 then next count starts back at full count (65000 in your
case) we have to take care of this subtraction problem.

   

Example, counter starts at 65000, counts down to 30000, PW = 35000. If
Clock to timer is 1 Mhz, 1 uS, then PW = 1 uS X 35000 = 35 mS.

   

 

   

The Compare register has no functionality in this solution.

   

 

   

Counter solution -

   

5) We load max period into period register, 65000 in your case.
6) Input signal goes to enable pin on counter.
7) Input goes high, counter starts counting down.
😎 We have the input pin configured for an interrupt on falling edge.
9) Input falls, ISR triggered, we read the counter register, not the
period register, and get the counts at the end of the pulse.
10) We subtract the ISR counts from the full scale counts we loaded (65000
in your case)  and we have the PW counts. We get the PW time using same
calculation we did for timer case based on clock.
11) We stop and reload counter with 65000 in this ISR
12) We have to take care of the same “rollover” problem as the timer.

   

The Compare register has no functionality in this solution.
When to use the compare register. Say you want to know when the pulse has exceeded
3000 counts, in the case of a 1 Mhz clock, 3 mS width. Then you would set the compare
Register to 65000 – 3000 = 62000. When the C/T reaches 62000 the compare output
goes high. That can trigger an ISR to handle your pulse has exceeded 3 mS.

   

Hope this helps.

   

Regards, Dana.

   


 

0 Likes
Reply
Esteemed Contributor

The reason your compare output never went high is the counts never dropped below

   

200, the value you wrote to the compare register.

   

 

   

As an aside, the core of all C/T blocks is a counter, counting clock inputs pulses.

   

 

   

The COMPARE and PERIOD register are separate registers from the core counter in the C/T.

   

 The compare has logic, that looks at whats in the core counter, and compares its value against

   

whats in the compare register, generating a compare output and an ISR if you enable it.

   

 

   

The compare logic you select, < or <=.......

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

   

//----------------------------------------------------------------------------

   

// C main line

//----------------------------------------------------------------------------

   

#include

    <m8c.h>    

   

#include "PSoCAPI.h" // PSoC API definitions for all User Modules

   

#pragma

        interrupt_handler Tach16_MSB_ISR   

#pragma

WORD count=

WORD result=

WORD compare1=

WORD compare2=

    interrupt_handler Tach16_LSB_ISR    0    ;    0    ;    0    ;    0    ;   

int

    no_of_TimerPeriod=    0    ;   

int

    no_of_TimerPeriod2=    0    ;   

int

    flag=    0    ;   

void

{

count++;

    Tach16_MSB_ISR (    void    )   

}

   

void

{

 

{compare1=TachTimer16_wReadCompareValue();

no_of_TimerPeriod=count;

flag=

}

 

    Tach16_LSB_ISR (    void    )    int    pulse_width=    0    ;    if    (flag==    0    )    1    ;     else   

{ flag=

compare2=TachTimer16_wReadCompareValue();

no_of_TimerPeriod2=count;

pulse_width=(compare1 +(no_of_TimerPeriod2 - no_of_TimerPeriod)*

 

}

    0    ;    65000    +     65000    -compare2)/    100    ;    }   

void

{

    main(    void    )   

int

 

TachTimer16_EnableInt();

TachTimer16_EnableTerminalInt();

TachTimer16_EnableCaptureInt();

TachTimer16_Start();

 

 

{

}

}

    i;    M8C_EnableGInt ;     while    (    1    )
0 Likes
Reply
Anonymous
Not applicable

Hi dana,

   

thanks for your respond. i used a tach timer, i am testing it with function generator as input signal, and measuring the output by Multimeter as output.

0 Likes
Reply
Esteemed Contributor

Correction to my prior post. I forgot, frankly, the Timers do not have a separate capture register,

   

so was trying to advise you the compare register was pointless in the design to calc PW.

   

 

   

That being said I fooled around trying different approaches, looking at jitter, and seem to

   

think a slightly different approach produces a better result.

   

 

   

So I set up a timer, to capture on falling edge, and the input pin to the timer to ISR on rising edge.

   

In ISR for pin I simply read timer register. In capture ISR I do not read the compare register,

   

I execute again a simple read on timer register. So I have two values, and keep the timer running

   

continuously. Reason I did not read the capture register for second value is I felt that the machine

   

cycles, latency, is same for both ISR calls. So my observed jitter was better with this approach.

   

 

   

I worked with pulses up to 10 Khz with a 1 uS timer clock. And PW down to  30 uS in width,

   

where error seemed too high. I have not tried faster Timer clock, say 12 Mhz, to see what that will do.

   

 

   

I then tried using a counter solution, just one ISR on GPIO negative edge that feeds counter enable.

   

Pulse coming in goes high, starts counter counting. ISR stops counter, reads it, reloads it, restarts it.

   

Net result seemed I could handle much narrower pulses, 10 uS reading accurately.

   

 

   

Food for thought, Dana.

0 Likes
Reply
Esteemed Contributor

I omitted a couple of points.

   

 

   

1) Counter requires only 1 ISR.

   

 

   

2) Counter enable serves two purposes, going high we start

   

counter with a known value, going low ISR to indicate done counting.

   

 

   

3) For real accurate count one would look at read counter register

   

ASM listing and count instruction cycles to get latency.

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Hi dana, can you take a look at that project, i used PWM to get RPM from tachtimer.

   

i am using function genrator connecting to pin 0-5 and have the out put that connect to Multimeter to measure RPM on pin 0-2

   

 

   

Thanks

0 Likes
Reply
Esteemed Contributor

Soime questions -

   

 

   

1) You are changing thePWM16 pulse width, not its frequency, with -

   

PWM16_WritePulseWidth(curr_rpm), is that what you intended ?

   

Most multimeters only measure frequnecy.

   

 

2) Your multimeter is measuring what, freq or PW ?

 

3) You have "freq = (float) 2400000/pulse_width;", this should be

"freq = (float) 24000000/pulse_width;"

 

Regards, Dana.

 

 

 

0 Likes
Reply
Anonymous
Not applicable

Hi Dana,

   

the curr_rpm is from the equation of the freq, so when i change the freq, it should change the rpm. and take that rpm value and measure thro the multimeter. as freq.

   

Mina

0 Likes
Reply
Anonymous
Not applicable

Dana,

   

thats what i am trying to do, take the freq from output and put it in the RPM equation and measure the freq that equivlant to RPM.

   

equation is RPM( freq) = 2.5 ( monitor freq)

   

so if i input freq 200HZ, i want to read on freqmeter 200*2.5= 500HZ

   

 

   

Can you advice me if my way is right or wrong ?

   

Thanks

0 Likes
Reply
Esteemed Contributor

1) You are changing thePWM16 pulse width, not its frequency, with -

   

PWM16_WritePulseWidth(curr_rpm), is that what you intended ?

   

 

   

   

 

   

3) You have "freq = (float) 2400000/pulse_width;", this should be

"freq = (float) 24000000/pulse_width;"

 

Did you fix those problems ? A PWM has two registers associated with it,

period, hence frequency, and pulse width, eg. duty cycle. I think you

were writing the wrong register.

 

Regards, Dana.

 

 

0 Likes
Reply
Anonymous
Not applicable

 Hi friends,

   

  i have configured the UART module along with timer 16. My uart operating at 9600 bps.  i have congigured the global resource as follows

   


Sysclk at 24 Mhz

VC1= 24Mhz /8
VC2 = VC1/ 3
VC3 = VC2/13 

   

Now i need to operate my timer interrupt every 25 msec. 

   

i just did like dis

   


Now my timer operating at VC2 i.e 1Mhz which is equal to 1micro sec.

Now i have given 65000 as period

40000 as compare value.

interrupt on compare true

compare value less than or equal to..

capture is low.

as i calculated  the period value of 65000 gets decremented and when it reaches 40000 it generates an interrupt.

65000          (PERIOD)
40000 (-)      (COMPARE VALUE)
-----------
25000 = 25000* 1micro sec  = 25msec .
-----------
 so as my calculation every 25 msec an interrupt should generate but im not getting the expecting output.. Tried checking the interrupt every  sec but my expected value reaches only after 3 sec.

can u please help us in this.  Is this the right way .... 

0 Likes
Reply
Esteemed Contributor II

Welcome in this forum and in the fascinating world of PSoCs!

   

You should set the period value to generate your wanted frequency, in your case to 25000-1 = 24999.

   

The compare value will change the duty-cycle of the compare output only, so you can set that to 25000/2 -1 = 12499 to have a 50% duty cycle.

   

 

   

Bob

0 Likes
Reply
Esteemed Contributor

 The interrupt is going to occur at the period rate, unless in interrupt you reset

   

timer. So 25 mS = 40 Hz, therefore  N = 1 Mhz /  40 = 25000. So set period to 24999,

   

 then either set  compare value to anything from 1 to 24998 (the extreme

   

gives very narrow pulses on compare out) or set interrupt type to terminal count,

   

compare value to 12499 (gives 50% duty cycle on compare out).

   

 

   

Note the compare interrupt occurs at the period rate, unless in ISR you terminate

   

timer by a reset, stop....or change the timer period.

   

 

   

Also don’t forget to modify boot.tpl for the interrupt vector.

   

 

   

                  

   

http://www.cypress.com/?rID=91487     AN90833 - PSoC® 1 Interrupts

   

http://www.cypress.com/?rID=34189     AN47310 - PSoC® 1 Power Savings Using Sleep Mode

   

 

   

 

   

Lastly the way you had the timer set up it would have generated an ISR 25 mS

   

from the start of the timer, but then next interrupt would have occured 40,000 +

   

25,000 counts which would have been a little over 15 Hz rate. The counter counts

   

down from period value, hits the compare value (so its output goes true, continues

   

counting down to 0, and on rollover compare goes false, counter rolls over to period

   

value, and process repeats......

   

 

   

Regards, Dana.

0 Likes
Reply
Esteemed Contributor

A couple of other items -

   

 

   

1) You have CPU clock set to / 8 or 3 Mhz, if you want more performance

   

set it to /1. Note that would impact power.

   

 

   

2) If you have any analog coming out to a pin set in global properties

   

the OpAmp and Abuff power to high, otherwise impacts bandwidth and

   

CM range for analog signals.

   

 

   

3) In ISR mimimize code, like other f() calls, etcc. Reason is that creates a

   

lot of stack push and wastes MIPs. Generally speaking, wherever possible,

   

set a flag in ISR and exit, then process ISR from main(). Just good practice.

   

 

   

4) Ref material -

   

 

   

    

   

         

   

http://www.cypress.com/?rID=2638     AN2197 - Stepper Motor Driver for Smart Gauges

   

 

   

http://www.element14.com/community/docs/DOC-47984/l/cypress-an2229--application-note-on-psoc-1-motor...       AN2229  Motor Control-Multi-Functional Stepping Motor Driver

   

 

   

http://www.element14.com/community/docs/DOC-47938/l/cypress-an41949--application-note-for-psoc-1-ste...     AN41949 - Application Note for PSoC 1 Stepper Motor Controller

   

 

   

 

   

5) If your ISR rate is flexible you could always use the sleep timer, saves

   

digital blocks for use in something else. It has rates for ISR of -

   

 

                                                                                                                                                                                                

Constant

Value

Interrupt rate

SleepTimer_1_HZ

0x18

1 Hz

SleepTimer_8_HZ

0x10

8 Hz

SleepTimer_64_HZ

0x08

64 Hz

SleepTimer_512_HZ

0x00

512 Hz

0 Likes
Reply
Anonymous
Not applicable

Hi,

   

 

   

I am writing a code to measure the frequency and I am using CY8c28445-24PVXI chip. I have added FreqCode.h header file but when I compile it says cannot inlcude this header file. can you please help me.

0 Likes
Reply
Esteemed Contributor II

Welcome in the forum.

   

A bit difficult to guess what the reason might be. Can be the wrong place where FreqCode.h and .c are stored. Are the files listed (added) to workspace explorer? Can you provide us with a project archive made from designer -> File ...

   

 

   

Bob

0 Likes
Reply