Rotary Quadrature Encoder
Moderator: Benj
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Rotary Quadrature Encoder
I use PIC18F4550, a rotary quadrature encoder with a push button contact and a LCD 20x4 lines.
The program is based on original “Quad_Encode_Test” from here:
http://www.matrixtsl.com/wiki/index.php ... tronics%29
Here is the program that I use: And is working good, reading the encoder very fast, not missing a count when I rotate fast with my fingers. I tested the code on real circuit. Worth to mention that my rotary encoder gives 4 pulses at one indent, so that’s why I divide by 4.
The program displays on the first line of the LCD the text “PWM=xxx%” where xxx is a variable VAR which is only between 0 and 100. There is no actually PWM signal for the moment, it is just a text displayed on LCD. When I push the button, then the VAR value for PWM% is reset to 0.
My problem is that I need the PIC18F4550 to perform a lot of other tasks, the program will be written later, and the reading of rotary encoder to be only a secondary task.
In other words, I do not want the reading on the main loop of the program, but a subroutine, eventually using the interrupts, perhaps interrupts on change on port B (IOC).
But then, I notice that the reading is not so fast, I miss pulses.
The rotary encoder should be normally a secondary priority task, but when is rotated then should be read fast, eventually changing its subroutine priority for the PIC. I notice writing to LCD takes time and the PIC misses the reading of the rotary encoder pulses.
What suggestions, code example could you provide to help reading fast the rotary encoder, but in the same time to not let the PIC doing only that?
The program is based on original “Quad_Encode_Test” from here:
http://www.matrixtsl.com/wiki/index.php ... tronics%29
Here is the program that I use: And is working good, reading the encoder very fast, not missing a count when I rotate fast with my fingers. I tested the code on real circuit. Worth to mention that my rotary encoder gives 4 pulses at one indent, so that’s why I divide by 4.
The program displays on the first line of the LCD the text “PWM=xxx%” where xxx is a variable VAR which is only between 0 and 100. There is no actually PWM signal for the moment, it is just a text displayed on LCD. When I push the button, then the VAR value for PWM% is reset to 0.
My problem is that I need the PIC18F4550 to perform a lot of other tasks, the program will be written later, and the reading of rotary encoder to be only a secondary task.
In other words, I do not want the reading on the main loop of the program, but a subroutine, eventually using the interrupts, perhaps interrupts on change on port B (IOC).
But then, I notice that the reading is not so fast, I miss pulses.
The rotary encoder should be normally a secondary priority task, but when is rotated then should be read fast, eventually changing its subroutine priority for the PIC. I notice writing to LCD takes time and the PIC misses the reading of the rotary encoder pulses.
What suggestions, code example could you provide to help reading fast the rotary encoder, but in the same time to not let the PIC doing only that?
- QMESAR
- Valued Contributor
- Posts: 1287
- Joined: Sun Oct 05, 2014 3:20 pm
- Location: Russia
- Has thanked: 384 times
- Been thanked: 614 times
- Contact:
Re: Rotary Quadrature Encoder
I am not sure if the setting that is shown in your project code is the actual setting however when true you are running at Fosc =24Mhz then Tcy = 24/4 = 6 Mips you are running very slow this is 50% of the speed of the MCUviki2000 wrote: eventually using the interrupts, perhaps interrupts on change on port B (IOC).But then, I notice that the reading is not so fast, I miss pulses.
the 18F4550 can run at 48Mhz /4 = 12Mips that would speed the thing up quite a bit
Regards
QMESAR
- Attachments
-
- 13.11.png
- (19.54 KiB) Downloaded 7830 times
https://www.flowcodexchange.com/
Regards QMESAR
Regards QMESAR
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
No.
It should work also with the internal oscillator 4MHz from a smaller PIC.
Let's make some calculations.
The average speed when turning the rotary encoder is about half of turn in 1 second and maximum 1 turn per second. This is what I tested for real.
If you read the datasheet of such encoders, then you may see that maximum speed is rated 60-100RPM, which is around 1 turn per second, as I tested, but in reality the max. speed is in fact half of it, around half rotation in 1 sec, around 1 full rotation in 2 sec.
http://www.mouser.com/ds/2/54/PEL12T-48721.pdf
http://www.mouser.com/ds/2/54/PEC11L-74340.pdf
My encoder is 24 dents with 4 pulses between 2 dents, so in total 96 pulse per revolution. Let's make it 100 for easy calculation.
Then we have 100 pulses for 1 revolution in max. 1 sec as the fastest turn.
That leads to 10ms between two pulses.
Well, 10ms is a lot of time to read and do something else with a simple 4MHz internal oscillator (1MIPS = 1 Million Instructions per Second).
Then with 24MhZ is 6 times faster, enough speed.
It is just a question how the code is written.
It should work also with the internal oscillator 4MHz from a smaller PIC.
Let's make some calculations.
The average speed when turning the rotary encoder is about half of turn in 1 second and maximum 1 turn per second. This is what I tested for real.
If you read the datasheet of such encoders, then you may see that maximum speed is rated 60-100RPM, which is around 1 turn per second, as I tested, but in reality the max. speed is in fact half of it, around half rotation in 1 sec, around 1 full rotation in 2 sec.
http://www.mouser.com/ds/2/54/PEL12T-48721.pdf
http://www.mouser.com/ds/2/54/PEC11L-74340.pdf
My encoder is 24 dents with 4 pulses between 2 dents, so in total 96 pulse per revolution. Let's make it 100 for easy calculation.
Then we have 100 pulses for 1 revolution in max. 1 sec as the fastest turn.
That leads to 10ms between two pulses.
Well, 10ms is a lot of time to read and do something else with a simple 4MHz internal oscillator (1MIPS = 1 Million Instructions per Second).
Then with 24MhZ is 6 times faster, enough speed.
It is just a question how the code is written.
- QMESAR
- Valued Contributor
- Posts: 1287
- Joined: Sun Oct 05, 2014 3:20 pm
- Location: Russia
- Has thanked: 384 times
- Been thanked: 614 times
- Contact:
Re: Rotary Quadrature Encoder
Well yes I agree when you have rotation speed of 2 sec per rotation that leaves enough time at 6MipsThe average speed when turning the rotary encoder is about half of turn in 1 second and maximum 1 turn per second. This is what I tested for real.
If you read the datasheet of such encoders, then you may see that maximum speed is rated 60-100RPM, which is around 1 turn per second, as I tested, but in reality the max. speed is in fact half of it, around half rotation in 1 sec, around 1 full rotation in 2 sec.
my comment was based on average as running at 50% of the capability could be a problem as you did not mention these specs in your previous post
https://www.flowcodexchange.com/
Regards QMESAR
Regards QMESAR
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
I just measured the rectangular signal at the rotary encoder pins with oscilloscope on the real application.
I tried to turn it as fast as I could with my fingers for a normal operation.
I measured around 2ms for "1" logic and almost similar for "0" logic as the narrowest pulses, meaning the fastest speed.
That's about 4ms one period for the signal at one pin, almost 50% less than my theoretical estimation from yesterday.
I think is still plenty of time for the PIC to do also something else.
I tried to turn it as fast as I could with my fingers for a normal operation.
I measured around 2ms for "1" logic and almost similar for "0" logic as the narrowest pulses, meaning the fastest speed.
That's about 4ms one period for the signal at one pin, almost 50% less than my theoretical estimation from yesterday.
I think is still plenty of time for the PIC to do also something else.
Last edited by viki2000 on Fri Nov 14, 2014 11:49 am, edited 3 times in total.
- Benj
- Matrix Staff
- Posts: 15312
- Joined: Mon Oct 16, 2006 10:48 am
- Location: Matrix TS Ltd
- Has thanked: 4803 times
- Been thanked: 4314 times
- Contact:
Re: Rotary Quadrature Encoder
Hello,
Ideally you would use a fairly fast timer interrupt or an interrupt on change to trigger the call to the CheckForChanges macro. This should guarantee that you don't miss any changes and you can get on with your other tasks as part of the main loop.
Ideally you would use a fairly fast timer interrupt or an interrupt on change to trigger the call to the CheckForChanges macro. This should guarantee that you don't miss any changes and you can get on with your other tasks as part of the main loop.
Regards Ben Rowland - MatrixTSL
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Could you provide an example for such interrupts application with quadrature encoder?
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
I have tried to test the interrupt on change on port B, in simulation and also with the real PIC+Encoder.
The update of the LCD is fast and the PIC reads fast the Encoder, no pulses are missed.
I have this time an increment of 2 pulses at each indent. That should be not a problem, because I can divide by 2.
There is only one problem: it gives only negative numbers, no matter if the encoder turns right or left.
Where is the mistake?
The update of the LCD is fast and the PIC reads fast the Encoder, no pulses are missed.
I have this time an increment of 2 pulses at each indent. That should be not a problem, because I can divide by 2.
There is only one problem: it gives only negative numbers, no matter if the encoder turns right or left.
Where is the mistake?
- Benj
- Matrix Staff
- Posts: 15312
- Joined: Mon Oct 16, 2006 10:48 am
- Location: Matrix TS Ltd
- Has thanked: 4803 times
- Been thanked: 4314 times
- Contact:
Re: Rotary Quadrature Encoder
Hello,
Aha, the negative numbers are occurring because the IOC interrupt only works for pins RB4-RB7 and you have one of the encoder pins set to RB3 so it was missing this change. If you really need to use RB3 then take my example and change the IOC interrupt for a fairly high speed timer interrupt and it should work.
I've changed the program slightly so that the interrupt macro is left as free as possible so it can be fired again when needed and changed the pin connections to RB4 and RB5 and hopefully it should be working correctly for you now.
Aha, the negative numbers are occurring because the IOC interrupt only works for pins RB4-RB7 and you have one of the encoder pins set to RB3 so it was missing this change. If you really need to use RB3 then take my example and change the IOC interrupt for a fairly high speed timer interrupt and it should work.
I've changed the program slightly so that the interrupt macro is left as free as possible so it can be fired again when needed and changed the pin connections to RB4 and RB5 and hopefully it should be working correctly for you now.
Regards Ben Rowland - MatrixTSL
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Many thanks for this observation. I just missed it.
Indeed, on page 111 from datasheet of the PIC18F4550 is written:
“9.9 PORTB Interrupt-on-Change
An input change on PORTB<7:4> sets flag bit, RBIF (INTCON<0>).”
http://ww1.microchip.com/downloads/en/d ... 39632c.pdf
I tested the proposed program and works. The only thing is that 200ms delay, which I replaced with an IF decision, and works better for me.
Indeed, on page 111 from datasheet of the PIC18F4550 is written:
“9.9 PORTB Interrupt-on-Change
An input change on PORTB<7:4> sets flag bit, RBIF (INTCON<0>).”
http://ww1.microchip.com/downloads/en/d ... 39632c.pdf
I tested the proposed program and works. The only thing is that 200ms delay, which I replaced with an IF decision, and works better for me.
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Now, after the correction above, I have again the 4 pulse for 1 indent, therefore I divide with 4 to get 1 increment seen on the display.
I have only one more question related with the rotary encoder.
Practically, I need to make some calculations with the number obtained from the encoder.
For example, in my case I need to limit the number in the range 0-100, so it can display PWM in percent 0% to 100%.
Then I tried the next code, which works good but not very good. Just for my curiosity, I decided to see how is it working with Timer interrupts, so I tried Timer0.
As I know the encoder signal is 2ms on and 2ms off at fastest turn with my fingers, measured with oscilloscope, I considered an internal interrupt of TMR0 under 1ms fast enough, in my case around 682us (1/1464.844).
I have only one more question related with the rotary encoder.
Practically, I need to make some calculations with the number obtained from the encoder.
For example, in my case I need to limit the number in the range 0-100, so it can display PWM in percent 0% to 100%.
Then I tried the next code, which works good but not very good. Just for my curiosity, I decided to see how is it working with Timer interrupts, so I tried Timer0.
As I know the encoder signal is 2ms on and 2ms off at fastest turn with my fingers, measured with oscilloscope, I considered an internal interrupt of TMR0 under 1ms fast enough, in my case around 682us (1/1464.844).
Last edited by viki2000 on Mon Nov 17, 2014 10:21 am, edited 2 times in total.
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Basically, in the first code with interrupt on change on port B I have next settings for the interrupt, where we can see also RB4-RB7 only as pins for IOC on PORTB:
The difference is not noticeable when I rotate the encoder fast with my fingers, but if I rotate slowly, as for example 1 indent, 1 mechanical step only, seen as 1 increment on display, then the TMR0 code reacts perfect and the IOC code does not catch the change sometimes. One more time: only sometimes and only at low rotation of the encoder, the IOC is not so good as TMR0 code.
My question is: why? What can be done for improvement, so the IOC code will react fast, the same way as TMR0 code reacts?
I would still love to use IOC, because TMR0 interrupt will be used later for other functions/subroutines.
Then for the second code, with interrupt in Timer0 I have next setting for the interrupt, the rest of the code remain the same:
By testing the both codes on real device I noticed a difference.The difference is not noticeable when I rotate the encoder fast with my fingers, but if I rotate slowly, as for example 1 indent, 1 mechanical step only, seen as 1 increment on display, then the TMR0 code reacts perfect and the IOC code does not catch the change sometimes. One more time: only sometimes and only at low rotation of the encoder, the IOC is not so good as TMR0 code.
My question is: why? What can be done for improvement, so the IOC code will react fast, the same way as TMR0 code reacts?
I would still love to use IOC, because TMR0 interrupt will be used later for other functions/subroutines.
Last edited by viki2000 on Mon Nov 17, 2014 12:19 pm, edited 1 time in total.
- Benj
- Matrix Staff
- Posts: 15312
- Joined: Mon Oct 16, 2006 10:48 am
- Location: Matrix TS Ltd
- Has thanked: 4803 times
- Been thanked: 4314 times
- Contact:
Re: Rotary Quadrature Encoder
Hello,
The problem could potentially be contact bounce which is giving you problems. Have you fitted the resistors and caps to the encoder input signals like shown on the schematic for the quad encoder E-block.
I've linked the datasheet below if you want to look at our recommended circuit.
http://www.matrixtsl.com/resources/getr ... php?id=610
The problem could potentially be contact bounce which is giving you problems. Have you fitted the resistors and caps to the encoder input signals like shown on the schematic for the quad encoder E-block.
I've linked the datasheet below if you want to look at our recommended circuit.
http://www.matrixtsl.com/resources/getr ... php?id=610
Regards Ben Rowland - MatrixTSL
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
I had installed something like:
But I will try also your recommended filter.-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Here is an update with my last trials.
I tried the proposed filter from E-block and additional next filter:
http://tunafishsandwich.wordpress.com/2 ... ebouncing/
which has a nice explanation with calculations here:
http://www.eng.utah.edu/~cs5780/debouncing.pdf
Then I have tried 2 more encoders, 1 similar with dents and 4 pulses per dent and one without any mechanical dents.
The results are basically the same and they are definitely related with what you suggested: the debouncing in conjunction with external interrupt on change.
Probably additional circuits, a bit more complex, with gates, trigger-Schmidt or other dedicated IC for debouncing would solved the problem and would make the IOC with similar response as TMR0 code.
I also believe that more complex code, with digital filtering and eventually writing different code for reading the encoder instead of using the ready-made encoder component, would solve the problem.
Another solution would be the usage of more expensive encoders as magnetic encoders or better optical encoders.
As it is now, the IOC code is working but not so good as TMR0 code.
I also noticed that using encoders with mechanical dent gives a very nice feedback to the user when rotate one mechanical dent to obtain one increment on display. The encoder without mechanical dents seems that react better for IOC, or at least let the impression when interact with the fingers and we look at display for the results, but not having a feedback for 1 pulse/increment does not always feels nice, but bouncing seems less.
Regarding the TMR0 interrupt code for encoder, I have tried several frequencies for interrupt.
At least in my case, the 1500HZ interrupt seems very good. Of course works very well with higher frequency as 2900Hz, but is not needed. Then I have tried the 700Hz and is OK, but seems not so good as 1500Hz. The 300Hz is not good.
These interrupt frequencies are related with prescaler rate of TMR0. As conclusion, the difference between IOC interrupt and TMR0 interrupt used to read the component encoder is definitely related with bouncing as suggested.
I tried the proposed filter from E-block and additional next filter:
http://tunafishsandwich.wordpress.com/2 ... ebouncing/
which has a nice explanation with calculations here:
http://www.eng.utah.edu/~cs5780/debouncing.pdf
Then I have tried 2 more encoders, 1 similar with dents and 4 pulses per dent and one without any mechanical dents.
The results are basically the same and they are definitely related with what you suggested: the debouncing in conjunction with external interrupt on change.
Probably additional circuits, a bit more complex, with gates, trigger-Schmidt or other dedicated IC for debouncing would solved the problem and would make the IOC with similar response as TMR0 code.
I also believe that more complex code, with digital filtering and eventually writing different code for reading the encoder instead of using the ready-made encoder component, would solve the problem.
Another solution would be the usage of more expensive encoders as magnetic encoders or better optical encoders.
As it is now, the IOC code is working but not so good as TMR0 code.
I also noticed that using encoders with mechanical dent gives a very nice feedback to the user when rotate one mechanical dent to obtain one increment on display. The encoder without mechanical dents seems that react better for IOC, or at least let the impression when interact with the fingers and we look at display for the results, but not having a feedback for 1 pulse/increment does not always feels nice, but bouncing seems less.
Regarding the TMR0 interrupt code for encoder, I have tried several frequencies for interrupt.
At least in my case, the 1500HZ interrupt seems very good. Of course works very well with higher frequency as 2900Hz, but is not needed. Then I have tried the 700Hz and is OK, but seems not so good as 1500Hz. The 300Hz is not good.
These interrupt frequencies are related with prescaler rate of TMR0. As conclusion, the difference between IOC interrupt and TMR0 interrupt used to read the component encoder is definitely related with bouncing as suggested.
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
There are 2 more observations/requests related with the present subject:
1) It would be very nice if the component encoder would permit to set its counter value. Now, we can only ReadCounter and ResetCounter. But are situations when we want the counter value to be suddenly different or to have limits as in my case with 0-100%. Then a kind of “SetCounter” would be very helpful.
I know this was discussed also in the past here:
http://www.matrixtsl.com/mmforums/viewt ... +variables
and additional variable was suggested as solution, but it would be nice to have everything embedded in the component encoder, by adding this “SetCounter” function.
2) For situations with external interrupts, interrupts on change (IOC) and mechanical encoders with bounces, no matter if we have external RC filters or not, it would be very helpful to have the possibility to add a digital filter, a bit of code, between real input pins and the inputs of the component encoder. Such digital filters are for example here:
http://www.gooligum.com.au/tutorials/ba ... se_C_2.pdf
http://www.gooligum.com.au/tutorials/mi ... id_C_1.pdf
The idea would be to have the possibility to connect the input of the component encoder to an internal bit, a variable in memory defined by the user. Then the user may apply his own code with a digital filter that considers good for his application, between real pins and that bit variable defined as input for component encoder.
I think that will help a lot, especially for situation with IOC.
I never tried to build a component by following the guide from the forum, but maybe the development of the existing encoder component, or perhaps making another new from scratch, and then adding the above 2 functions-properties will generate an improved version of the component encoder.
What do you think?
1) It would be very nice if the component encoder would permit to set its counter value. Now, we can only ReadCounter and ResetCounter. But are situations when we want the counter value to be suddenly different or to have limits as in my case with 0-100%. Then a kind of “SetCounter” would be very helpful.
I know this was discussed also in the past here:
http://www.matrixtsl.com/mmforums/viewt ... +variables
and additional variable was suggested as solution, but it would be nice to have everything embedded in the component encoder, by adding this “SetCounter” function.
2) For situations with external interrupts, interrupts on change (IOC) and mechanical encoders with bounces, no matter if we have external RC filters or not, it would be very helpful to have the possibility to add a digital filter, a bit of code, between real input pins and the inputs of the component encoder. Such digital filters are for example here:
http://www.gooligum.com.au/tutorials/ba ... se_C_2.pdf
http://www.gooligum.com.au/tutorials/mi ... id_C_1.pdf
The idea would be to have the possibility to connect the input of the component encoder to an internal bit, a variable in memory defined by the user. Then the user may apply his own code with a digital filter that considers good for his application, between real pins and that bit variable defined as input for component encoder.
I think that will help a lot, especially for situation with IOC.
I never tried to build a component by following the guide from the forum, but maybe the development of the existing encoder component, or perhaps making another new from scratch, and then adding the above 2 functions-properties will generate an improved version of the component encoder.
What do you think?
- Benj
- Matrix Staff
- Posts: 15312
- Joined: Mon Oct 16, 2006 10:48 am
- Location: Matrix TS Ltd
- Has thanked: 4803 times
- Been thanked: 4314 times
- Contact:
Re: Rotary Quadrature Encoder
Hello,
I've added the WriteCounter macro so you can set and bound the count value.
The changes can be loaded by copying the attached file into your "C:\Program Files (x86)\Flowcode 6\components" directory before starting Flowcode.
As for digital filtering this would be simple enough if we were calling the macro on say a timer tick but as demonstrated this is already working ok. I think the issue is that the IOC interrupt is not firing on all edges due to the bounce which is causing the problem. Therefore even if we added filtering the macro wouldn't be called to actually do the filtering unless the debounce problem is solved outside of the micro, therefore allowing the IOC interrupt to fire as and when an actual change is detected.
Do you have your encoders on a lead or long traces? If so then it might be worth moving the filters so they are as close to the micro pins as possible. Do you have access to a scope so you can see the signals at the microcontroller pins so you can confirm what is happening.
I've added the WriteCounter macro so you can set and bound the count value.
The changes can be loaded by copying the attached file into your "C:\Program Files (x86)\Flowcode 6\components" directory before starting Flowcode.
As for digital filtering this would be simple enough if we were calling the macro on say a timer tick but as demonstrated this is already working ok. I think the issue is that the IOC interrupt is not firing on all edges due to the bounce which is causing the problem. Therefore even if we added filtering the macro wouldn't be called to actually do the filtering unless the debounce problem is solved outside of the micro, therefore allowing the IOC interrupt to fire as and when an actual change is detected.
Do you have your encoders on a lead or long traces? If so then it might be worth moving the filters so they are as close to the micro pins as possible. Do you have access to a scope so you can see the signals at the microcontroller pins so you can confirm what is happening.
Regards Ben Rowland - MatrixTSL
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
Flowcode Product Page - Flowcode Help Wiki - Flowcode Examples - Flowcode Blog - Flowcode Course - My YouTube Channel
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
Thank you for the improved encoder component. It works very well for me, allowing me to simplify the code, using less variables.
I tried 2 codes, both working, both implemented with TMR0 interrupt. The difference is in the “Display” subroutine/macro, where I had to add some conditions for the boundaries of 0% and 100% in order to avoid “flickering” on LCD display when I reach one end or another of the range 0-100 and then the LCD line is written once for short time with numbers "<0" or ">100" instead of staying still 0% or 100%, and that creates the effect of flickering in the real application.
I tried 2 codes, both working, both implemented with TMR0 interrupt. The difference is in the “Display” subroutine/macro, where I had to add some conditions for the boundaries of 0% and 100% in order to avoid “flickering” on LCD display when I reach one end or another of the range 0-100 and then the LCD line is written once for short time with numbers "<0" or ">100" instead of staying still 0% or 100%, and that creates the effect of flickering in the real application.
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
The encoder have very short connections and the capacitors for filtering the bouncing are very close to the pins of the PIC.
Here are the screenshots from oscilloscope:
Here are the screenshots from oscilloscope:
-
- Posts: 190
- Joined: Mon Jul 07, 2014 9:38 am
- Has thanked: 30 times
- Been thanked: 77 times
- Contact:
Re: Rotary Quadrature Encoder
“I think the issue is that the IOC interrupt is not firing on all edges due to the bounce which is causing the problem. Therefore even if we added filtering the macro wouldn't be called to actually do the filtering unless the debounce problem is solved outside of the micro, therefore allowing the IOC interrupt to fire as and when an actual change is detected.”
I am not yet convinced.
Especially for the situation interrupt on change on port B (IOC) combined with very low speed of the encoder, as 0.5s-1s for one dent change, when the bouncing of the encoder input are negligible compared with “normal” rotation of the encoder with my fingers. We can see the less noise signal (bounces) as almost negligible at low speed also from the above screenshots.
I still believe a customized digital filter together with component encoder having as inputs a bit variable would solve the problem. As it is now, I cannot control what is happening between real pins, IOC and input/reading of the component encoder.