Counter UpCnt & DwnCnt mode as an Encoder

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

cross mob
lock attach
Attachments are accessible only for community members.
Dave_Goshen
Level 1
Level 1
First reply posted First question asked Welcome!

Hi guys! I am new in the cypress community, I hope that you can help me with this issue. I am trying to read an encoder without using interrupts. The solution that came to my mind is to use a counter in  UpCnt & DwnCnt mode. I have tried almost everything but the function Counter_ReadCounter(); returns me always the period value. I cannot understand how to fix it.  Pin_encoder_B and Pin_encoder_A are my two signal wires that go high and down. I am using Pin_encoder_A as a clock, when it turns up I look at the Pin_encoder_B, if Pin_encoder_B and Pin_encoder_A are equal or disequal I understand if my encoder is tourning clockwise or counterclockwise and I should be able to decrement or increment my counter.  What is wrong in my code? Thank you all.

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Dave,

I saw a number of issues with your design. 

Len_CONSULTRON_1-1635174137258.png

 

1: Won't count up or down

Your clock to Counter_Logic is the same as Pin_encoder_A.   Both upCnt and downCnt need to have TWO clock transitions to detect the 'rising' edge needed to increment or decrement the counter.  Since the clock input is the same as one of the encoder pins you only get at most ONE clock.  This is not enough.  You need another clock source to use the counter component.

2: The Count will be WRONG even if you fix 1:

You use the inverted signal of upCnt to generate downCnt from the AND gate.  In this case, either Cnt input will be active much longer (for many clock cycles) than intended.  

Recommendation:

Cypress/Infineon provides a Quadrature Decoder component.  It has the appropriate logic and glitch filtering in the case you are using a mechanical switching encoder.  

I've made changes to your project to substitute a 32-bit QuadDec component in place of the Counter component.  

I've attached this project.  I've made some codes changes as well.  I have not tested it since I don't have an encoder.  However, your code is fairly straight forward and should be easy to debug.

I've also enabled the glitch filter.

Use this component.  Cypress did much of the work for you.

3: Avoid using blocking functions in an ISR

You use the UART_PutString() in the ISR.  This is a potential blocking function.  This might cause unintended delays.    In your case, you are trying to print up to 14 characters to the UART.   Since the UART only has a byte-character FIFO, the first 4 chars are immediately loaded but the remaining 10 bytes block return of the function until the last byte is loaded into the FIFO.   At 115.2Kbps, this means t will block for 868us.

In my project mods, I left the UART_PutString() in the ISR.   It shouldn't be a "show-stopper" in your project as it currently stands.

 

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

0 Likes
5 Replies
lock attach
Attachments are accessible only for community members.
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Dave,

I saw a number of issues with your design. 

Len_CONSULTRON_1-1635174137258.png

 

1: Won't count up or down

Your clock to Counter_Logic is the same as Pin_encoder_A.   Both upCnt and downCnt need to have TWO clock transitions to detect the 'rising' edge needed to increment or decrement the counter.  Since the clock input is the same as one of the encoder pins you only get at most ONE clock.  This is not enough.  You need another clock source to use the counter component.

2: The Count will be WRONG even if you fix 1:

You use the inverted signal of upCnt to generate downCnt from the AND gate.  In this case, either Cnt input will be active much longer (for many clock cycles) than intended.  

Recommendation:

Cypress/Infineon provides a Quadrature Decoder component.  It has the appropriate logic and glitch filtering in the case you are using a mechanical switching encoder.  

I've made changes to your project to substitute a 32-bit QuadDec component in place of the Counter component.  

I've attached this project.  I've made some codes changes as well.  I have not tested it since I don't have an encoder.  However, your code is fairly straight forward and should be easy to debug.

I've also enabled the glitch filter.

Use this component.  Cypress did much of the work for you.

3: Avoid using blocking functions in an ISR

You use the UART_PutString() in the ISR.  This is a potential blocking function.  This might cause unintended delays.    In your case, you are trying to print up to 14 characters to the UART.   Since the UART only has a byte-character FIFO, the first 4 chars are immediately loaded but the remaining 10 bytes block return of the function until the last byte is loaded into the FIFO.   At 115.2Kbps, this means t will block for 868us.

In my project mods, I left the UART_PutString() in the ISR.   It shouldn't be a "show-stopper" in your project as it currently stands.

 

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
Dave_Goshen
Level 1
Level 1
First reply posted First question asked Welcome!

Hi Len, thank you very much for your reply! I really appreciate that you spent your time for helping me.  
I tested the QuadDec component and it works,  but at high speed it loses a lot of pulses. My encoder should generate 600 pulses every roung. I tried to increase the clock source up to 1 MHz, but still it loses pulses. Do you know if there is a way to increase its accuracy?

Thank you

Dave

0 Likes

Dave,

I'm glad it's working ... a kinda ... sorta ...

The component is capable of operating with a clock input up to 28 MHz.  In your case, with A and B pulsing at 600 Hz seconds, you theoretically only need an input clock of 6000 Hz according to the spec sheet.  Your applying 1 MHz is in theory 167x overkill.  And yet it appears to miss pulses.

Len_CONSULTRON_0-1635252221867.png

According to your previous post: "... but at high speed it loses a lot of pulses."

This assumes that at slow speeds you are not losing pulses.

Let's try some experiments.

Experiment #1

Increase the clock input to 28 MHz.  Does it lose any pulses at high-speed AB inputs?  If not, you're AB frequency might actually be higher than 600 pps.

Experiment #2

Connect the "interrupt" output of the QuadDec component to a pin.   

The interrupt output goes active on the following events:

▪ Counter overflow and underflow
▪ Counter reset due to index input (if index is used)
▪ Invalid state transition on the A and B inputs

In a properly operating AB inputs you should only get the "Counter overflow and underflow" event.  With the counter depth being 32-bits this should occur relatively rarely.

If you are getting 'other' interrupt events, you might want to check your AB inputs.  Also, there is a API to read the Status register to determine what type of event occurred.

Len_CONSULTRON_1-1635254166182.png

Experiment #3

Have you captured your AB inputs on a scope?  Are the signals clean?  I don't know what you are using for an encoder, but you might need to condition the AB inputs which might be at a different threshold than the digital GPIO inputs being used.

 

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
lock attach
Attachments are accessible only for community members.

Dave,

I created a modification of my uploaded project with a Simulated Quadrature encoder.

With the simulated encoder I place AB phase edges to a count of 100,000.  I get a return count from the QuadDec component of 100.001 every time even with the QuadDec input clock of 10Khz.

I see no loss of counts.

I would guess that the Experiment #3 might find the issue.  You might need to condition the inputs properly.

I've attached my modified project for your review.

Len
"Engineering is an Art. The Art of Compromise."

Dave,

Have you identified the root cause of your missing pulses?

Len
"Engineering is an Art. The Art of Compromise."
0 Likes