tag:blogger.com,1999:blog-1257112335293436059.post206757964784085655..comments2023-11-05T23:51:07.814+11:00Comments on Buxtronix: Rotary encoders, done properlyAnonymoushttp://www.blogger.com/profile/02191923625652700450noreply@blogger.comBlogger141125tag:blogger.com,1999:blog-1257112335293436059.post-37552214557039728652021-06-14T22:01:41.736+10:002021-06-14T22:01:41.736+10:00FYI Ben, as of June 2021: This is still the nutz. ...FYI Ben, as of June 2021: This is still the nutz. Thanks for sharing.Jeff Brownhttps://www.blogger.com/profile/12332485614294605176noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-65445047098874640662021-02-15T23:03:16.811+11:002021-02-15T23:03:16.811+11:00Simple, fast and easy to port to my PIC-controller...Simple, fast and easy to port to my PIC-controller, using MPLAB IDE with CX8 C-compiler.<br /><br />Before, I lost several days trying to solve some strange behavior of my Encoders. It took me some while to realize that it was caused by bouncing. Realizing that using a state-machine was the way to go, this post crossed my path, and made me win back several days instead of re-inventing the wheel!<br /><br />Thanks a lot!!!Anonymoushttps://www.blogger.com/profile/06964746615549497994noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-28831270041425391302020-09-27T06:42:37.180+10:002020-09-27T06:42:37.180+10:00https://hashmiipc.com/adobe-premiere-pro-cc-2015-f...https://hashmiipc.com/adobe-premiere-pro-cc-2015-free-downloadHashmiiPChttps://www.blogger.com/profile/05599985162915972638noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-45340632119471282782020-09-07T03:42:50.922+10:002020-09-07T03:42:50.922+10:00http://alltopc.com/ for softwareshttp://alltopc.com/ for softwaresMichaelhttps://www.blogger.com/profile/09011450683939245083noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-31861125668066207312020-09-07T03:42:17.178+10:002020-09-07T03:42:17.178+10:00https://getdailybook.com/ for top selling books https://getdailybook.com/ for top selling books Rosehttps://www.blogger.com/profile/02946610819312347756noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-25708005538635013672020-05-22T19:19:32.932+10:002020-05-22T19:19:32.932+10:00The example doesn't compile on windows 10 with...The example doesn't compile on windows 10 with arduino 1.8.11.<br />So far I only spent countless hours getting a decent rotary encoder routine to work. This project highlights the issues I've had, so I would hope it would get working.<br /><br />C:\Users\me\AppData\Local\Temp\cc8tAXOq.ltrans0.ltrans.o: In function `rotate':<br />D:\buxtronix-encoder\interrupt/interrupt.ino:29: undefined reference to `Rotary::process()'<br />C:\Users\me\AppData\Local\Temp\cc8tAXOq.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_interrupt.ino.cpp.o.1755':<br />:(.text.startup+0x60): undefined reference to `Rotary::Rotary(char, char)'<br />collect2.exe: error: ld returned 1 exit status<br />exit status 1<br />Error compiling for board Arduino Uno.<br />teushttps://www.blogger.com/profile/17186666345644590567noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-74181196972924067852020-04-16T06:23:44.336+10:002020-04-16T06:23:44.336+10:00Someone did: https://forum.arduino.cc/index.php?to...Someone did: https://forum.arduino.cc/index.php?topic=242356.msg2308019#msg2308019<br />Alexhttps://www.blogger.com/profile/01438178086905342535noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-56781612699471140912020-01-13T15:13:09.350+11:002020-01-13T15:13:09.350+11:00I have been unsuccessful using your code. Can you...I have been unsuccessful using your code. Can you help by putting it in an .ino for me.Sampson20220https://www.blogger.com/profile/15568470259274421647noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-25532447625655649902019-11-11T20:49:18.221+11:002019-11-11T20:49:18.221+11:00i'm calling RotaryProcessThing.process() in a ...i'm calling RotaryProcessThing.process() in a later function to increment or reduce variablesflowhttps://www.blogger.com/profile/01125760969179071647noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-29028630568075231122019-11-11T20:47:29.298+11:002019-11-11T20:47:29.298+11:00hi.
i'm trying to use one RE for many jobs. is...hi.<br />i'm trying to use one RE for many jobs. is this the right way to do it?<br /><br /> Rotary Step1Rotary = Rotary(rotarypin1, rotarypin2);<br /> Rotary Step2Rotary = Rotary(rotarypin1, rotarypin2);<br /> Rotary Step3Rotary = Rotary(rotarypin1, rotarypin2);<br /> Rotary Step4Rotary = Rotary(rotarypin1, rotarypin2);<br /><br /> RotaryProcessThing = &Step1Rotary;<br /><br />Then change what RotaryProcessThing refers to each time I change what I'm using the encoder for?<br /><br />I'm assuming the last state is then preserved for each?<br />flowhttps://www.blogger.com/profile/01125760969179071647noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-42437957760115503152019-10-15T22:48:04.015+11:002019-10-15T22:48:04.015+11:00Hey, I just wanted to thank you for writing and sh...Hey, I just wanted to thank you for writing and sharing this library.Haamedhttps://www.blogger.com/profile/07381653297698308886noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-50986227637297613612019-09-22T06:06:48.986+10:002019-09-22T06:06:48.986+10:00I need a rotary encoder just as good as this one b...I need a rotary encoder just as good as this one but in Python (M5Stack|Core). Anyone that has one?Anonymoushttps://www.blogger.com/profile/17810920778938101035noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-69792403881582077212019-07-27T14:52:22.340+10:002019-07-27T14:52:22.340+10:00Hi there...I have included in the following link t...Hi there...I have included in the following link the rotary.h and .cpp libraries with a brief explanation of a couple of modifications that I've made. I hope it helps!<br /><br />https://carlossilesblog.wordpress.com/2019/07/27/rotary-encoder/<br />Carloshttps://www.blogger.com/profile/10924020113566420680noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-73859212130804157412019-07-24T05:21:43.366+10:002019-07-24T05:21:43.366+10:00Hello and thank you for the elegantly simple code ...Hello and thank you for the elegantly simple code to bypass all the nasty debounce routines that I have been seeing all over the web. I am interested in modifying the .h file and .cpp files so that I can use an encoder that was a third input, the SW button when pushing down on the shaft. Would this even be possible? <br /><br />I want to control and navigate a menu on an LCD screen using a single rotary encoder and its push button functionality.<br /><br />Thank you in advance for taking the time to read and respond.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-63635216721763532482019-05-19T22:53:14.030+10:002019-05-19T22:53:14.030+10:00With your code, my encoder is running smoothly. Th...With your code, my encoder is running smoothly. Thank you very much! <br /><br />My encoder has half-turn detents, in 11 and 00, then I have to use the half step table.<br /><br />I added some code to activate acceleration. Although it is running right until now, I am relatively new to these things, and I don't know yet if the code is well writen or if the code is bullet proff.<br /><br />The acceleration depends of maximum multiplier and the gap time. Bigger multiplier permits bigger increments, while bigger gap time, permits activate the acceleration with less turning speed. <br /><br />In practice it works like this: on slowly turning the encoder, each step will change the value 1 by 1, as the speed of rotation increases, it will change the value by 2 in 2, more speed by 3 in 3, and so, until the maximum set in the multiplier was hit. How quickly the acceleration will be active depends on the gap time.<br /><br /><br /><br />unsigned char Rotary::process()<br /> {<br /> unsigned char pinstate = (digitalRead(pin2) << 1) | digitalRead(pin1);<br /> state = ttable[state & 0xf][pinstate];<br /> <br /> //instead returning directly, the result is passed to variable "direction"<br /> int direction = encoderState_ & 0x30; <br /><br /> int factor = 1; //factor used to multiple to output, default is 1<br /> if ((direction != 0) && accIsOn_) //if direction has changed and acc is on (accIsOn_ is a bool flag to acceleration)<br /> {<br /> //elapsed time between actual turning and last turning <br /> unsigned long turnInterval = (millis() - lastReadTimeMs_);<br /> if (turnInterval < accGapTimeMs_) //if elapsed time is smaller than gap time<br /> {<br /> // Here the turn interval will be subtracted from the acceleration gap time<br /> // This returns a value that will be larger as the rotation is faster<br /> int z = (accGapTimeMs_ - turnInterval);<br /><br /> // And here the value will be remaped from: minimum = 1, maximum: acc gap time<br /> // to: minimum = 1, maximum = (acc multiplier +1). This +1 is because without it<br /> // the acceleration, even at the maximum, will reach only the maximum - 1.<br /> factor = map(z, 1, accGapTimeMs_, 1, (accMaxMultiplier_ + 1));<br /> }<br /> lastReadTimeMs_ = millis(); // store when the last turn happened<br /> }<br /><br /> // The return of function will be<br /> // 0 = no movement<br /> // positive number = clock wise turning<br /> // negative number = counter clock wise turning<br /> if (direction == DIR_CW) //if direction is CW<br /> {<br /> int x = (1 * factor); //multiply the factor by 1<br /> return x; //return the value<br /> }<br /> else if (direction == DIR_CCW) //if direction is CCW<br /> {<br /> int x = (-1 * factor); //multiply the factor by -1<br /> return x; //return the value<br /> }<br /> else<br /> // if has no movement<br /> return 0; //return 0<br /> }Tomazellihttps://www.blogger.com/profile/13691270496917020473noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-7859685500643426632019-05-14T18:19:32.338+10:002019-05-14T18:19:32.338+10:00YOU ARE MY HEROYOU ARE MY HEROAnonymoushttps://www.blogger.com/profile/02146917171476056621noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-70004741039813819872019-05-04T10:45:18.269+10:002019-05-04T10:45:18.269+10:00Now I understand…
I was puzzled as of why, in the...Now I understand…<br /><br />I was puzzled as of why, in the 3rd line (R_CW_BEGIN), an output of 00, rather than 11, took us to state R_CW_NEXT. If you follow the states, you will find that, for a CW, the sequence is 00>01>00>10>11>00….so it still works! Although, through a less efficient route…<br /><br />I have re written the state table so that it follows the required sequence: 00>10>11>01>00<br /><br />const unsigned char ttable[7][4] = { <br /> // R_START <br />{R_START, R_CCW_BEGIN, R_CW_BEGIN, R_START}, <br /> // R_CW_FINAL <br />{R_START | DIR_CW, R_CW_FINAL, R_START, R_CW_NEXT}, <br /> // R_CW_BEGIN <br />{R_START, R_START, R_CW_BEGIN, R_CW_NEXT}, <br /> // R_CW_NEXT <br />{R_START, R_CW_FINAL, R_CW_BEGIN, R_CW_NEXT}, <br /> // R_CCW_BEGIN <br />{R_START, R_CCW_BEGIN, R_START, R_CCW_NEXT }, <br /> // R_CCW_FINAL <br />{R_START | DIR_CCW, R_START, R_CCW_FINAL, R_CCW_NEXT}, <br /> // R_CCW_NEXT <br />{R_START, R_CCW_BEGIN, R_CCW_FINAL, R_CCW_NEXT}, <br />}; <br /><br />I have tested it and it works like a charm! I hope it helps others...<br />Carloshttps://www.blogger.com/profile/10924020113566420680noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-26430282761465293072019-05-01T04:09:00.626+10:002019-05-01T04:09:00.626+10:00@Lewis: I have seen the youtube and understood the...@Lewis: I have seen the youtube and understood the state diagram, however, I'm still confused about having an output (from the encoder) of 00 and state jumping to 11 (NEXT). Any hint will be greatly appreciated...Carloshttps://www.blogger.com/profile/10924020113566420680noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-41288896968393333632018-09-18T19:04:16.605+10:002018-09-18T19:04:16.605+10:00Excellent work! thanksExcellent work! thanksAnonymoushttps://www.blogger.com/profile/12574510997762624431noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-34135282269488956812018-08-25T07:41:40.153+10:002018-08-25T07:41:40.153+10:00Another thanks from me :)Another thanks from me :)Arptastichttps://www.blogger.com/profile/11992211910198727541noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-78999729142304381652018-05-07T10:55:29.686+10:002018-05-07T10:55:29.686+10:00Thank you very much for your work, and for sharing...Thank you very much for your work, and for sharing!!!Nick Greenhttps://www.blogger.com/profile/03449621066628421604noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-32730787479468456152017-12-16T03:39:42.384+11:002017-12-16T03:39:42.384+11:00Hold the press ! I figured it out with the help o...Hold the press ! I figured it out with the help of a youtube video where a fellow implements a similar approach and in fact references this site. The key to understanding this (at least for me) was the "state diagram" that he draws out on the whiteboard. You can see the paths much easier and prevent confusion.<br />https://www.youtube.com/watch?v=BJHftzjNjkwLewiwhttps://www.blogger.com/profile/03277166565691984498noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-79334829199952855852017-12-15T02:02:23.267+11:002017-12-15T02:02:23.267+11:00ok - I've spent too many hours trying to under...ok - I've spent too many hours trying to understand this state table and finally I am giving up and asking for help. I looked back through all the comments and there was one fellow that asked pretty much the same thing as I am trying to figure out without getting a response so I will copy his question here - <br />-----<br />In the full step code, in the 3rd row in the table:<br /><br />R_CW_BEGIN<br />(R_CW_NEXT, R_CW_BEGIN, R_START, R_START),<br /><br />I don't understand why if we receive the 0-0 encoder output, we have to go to R_CW_NEXT. As far as i can understand the code, the previous state was 1-0, so we only can go to 1-1 (NEXT) or 0-0. 0-0 should mean START... but the table has R_CW_NEXT.<br /><br />could you explain why these values are so?<br />--------------------------------Lewiwhttps://www.blogger.com/profile/03277166565691984498noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-30779010093096540452017-10-19T00:51:19.394+11:002017-10-19T00:51:19.394+11:00Hi Ben, Thanks for library. After many years it is...Hi Ben, Thanks for library. After many years it is still my favourite.<br />Is it possible to add (or)change code for "quad step"? (4x mode like in "pjrc" library).<br /><br />MAcsp9mrnhttps://www.blogger.com/profile/16559837475196705085noreply@blogger.comtag:blogger.com,1999:blog-1257112335293436059.post-23783492483930225572017-10-10T08:51:32.548+11:002017-10-10T08:51:32.548+11:00Hello Ben,
Thanks to your article, I could correct...Hello Ben,<br />Thanks to your article, I could correct errors in a Proton PIC Basic program that reads a 600 ppr optical rotary encoder. Below you can see a part of the program. Thanks for your help. Regards, Franz<br />Device 16F874A 'The PIC is PIC16F874A.<br />Xtal = 16 'I am Using a 16 MHz Xtal<br />Config HS_OSC, WDTE_OFF , PWRTE_ON , BOREN_OFF ,_<br />CP_OFF<br />All_Digital = true 'All I/O are digital<br />On_Hardware_Interrupt Encoder 'On falling edge of A goto Encoder: <br />TRISB = %10000011<br />OPTION_REG.7 = 0 'Enable pull-up resistors<br />OPTION_REG.6 = 0 'Interruption at falling edge<br />INTCON.7 = 1 'Enable global interrutions<br />INTCON.4 =1 'Enable RB0/INT interruptions<br />Dim Counter As Word<br />Dim OldA As Bit 'To be used in the interruption routine<br />Dim OldB As Bit<br />PORTB = 0<br />Symbol A = PORTB.0 'Encoder's signal A<br />Symbol B = PORTB.1 'Encoder's signal B<br />'*********** INTERRUPTION *************<br />Encoder:<br />Context Save 'Save registry contents<br />'Checking the Gray code sequence mentioned by Ben:<br />'If A and B change at the same time, Counter is not affected.<br />If A <> OldA And B <> OldB Then NoChange<br />If INTCON.1 = 1 Then<br /> If B = 1 Then Inc Counter<br /> If B = 0 Then Dec Counter <br /> OldA = A<br /> OldB = B<br />EndIf<br />NoChange:<br />INTCON.1 = 0 'Clear RB0/INT flag<br />Context Restore 'Restore former registy values.Anonymoushttps://www.blogger.com/profile/10282715109349408100noreply@blogger.com