100% found this document useful (1 vote)
346 views

Reading Rotary Encoder On Arduino Circuits@Home

The document summarizes a method for reading the state of a quadrature rotary encoder connected to an Arduino board in an efficient manner. It presents code that uses a lookup table to convert the encoder's A and B pin states into a direction value (-1, 0, 1) without needing debouncing. This is done by storing the previous encoder pin states and comparing them to the current states. The example code is explained line-by-line. Using this method, the encoder can be read quickly and reliably in the main loop without interrupts. However, for applications where responsiveness is critical, an interrupt-driven approach may be better.

Uploaded by

sukaryadi1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
346 views

Reading Rotary Encoder On Arduino Circuits@Home

The document summarizes a method for reading the state of a quadrature rotary encoder connected to an Arduino board in an efficient manner. It presents code that uses a lookup table to convert the encoder's A and B pin states into a direction value (-1, 0, 1) without needing debouncing. This is done by storing the previous encoder pin states and comparing them to the current states. The example code is explained line-by-line. Using this method, the encoder can be read quickly and reliably in the main loop without interrupts. However, for applications where responsiveness is critical, an interrupt-driven approach may be better.

Uploaded by

sukaryadi1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Sparkfun2010AutonomousVehicleCompetition

DigitalcameracontrolusingArduinoUSBHostShield.
Part1basics.

ReadingrotaryencoderonArduino
ByOlegMazurov
Quadraturerotaryencoders,alsoknownasrotarypulsegenerators,
arepopularinputdevicesforembeddedplatforms,includingArduino.
SeveralrotaryencodercodeexamplesarepostedonArduinosite
andelsewhere,however,theytreatencoderasapairofswitches,
addingdecoding/debouncingoverhead.Formanyyears,Iusedan
algorithmbasedonthefactthatquadratureencoderisaGraycode
generatorandiftreatedassuch,canbereadreliablyin3straight
stepwithoutneedfordebouncing.Asaresult,thecodeImusingis
veryfastandsimple,worksverywellwithcheaplowquality
encoders,butissomewhatcrypticanddifficulttounderstand.Soon
afterpostingoneofmyprojectswhereIusedrotaryencodertoset
motorspeedistartedreceivingemailsaskingtoexplainthecode.
ThisarticleisasummaryofmyrepliesImpresentingsmall
examplewrittenforthepurposeofillustratingmymethod.Imalso
goingthroughthecodehighlightingimportantparts.

RotaryencoderconnectedtoArduino

Thehardwaresetupcanbeseenontitlepicture.Theencoderfrom
SparkfunisconnectedtoavintageAtmega168basedArduinoPro.Commonpinoftheencoderisconnectedtoground,
pinsAandBareconnectedtopins14and15,AKAAnalogpins0and1,configuredasdigitalinputs.Wealsoneeda
serialconnectiontothePCtoreceivepower,programtheArduino,andsendprogramoutputtotheterminal.Forthis
purpose,SparkfunFTDIbasicbreakoutisused.
Connectingencoderpinstopins0and1of8bitMCUportmakesencoderreadingcodeverysimple.Ifanalogpinsare
neededforsomethingelse,itispossibletomoveencodertodigitalpins8,9or0,1(losingserialport)withnomodification
ofcodelogic.Whiletechnicallyusinganytwoconsecutiveportpinsispossiblewithabitoftweaking,usingnon
consecutivepinsforencoderinputwiththismethodisnotrecommended.Lastly,itsometimeshardtodeterminewhich
encoderpinisAandwhichisBitiseasiertoconnectthematrandomandifdirectioniswrong,swapthepins.
Examplecodeispostedbelow.ItiscompletesketchyoucancopyitfromthispageandpasteintoArduinoIDE
window,compile,uploadandrun.Theresultofrotatingtheencodercanbeseeninterminalwindow.Notethatserial
speedinthesketchissetto115200,youwillneedtosetyourPCterminaltothatspeedaswell.Theexplanationofthe
codeisgivenafterthelisting.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/*Rotaryencoderreadexample*/
#defineENC_A14
#defineENC_B15
#defineENC_PORTPINC

voidsetup()
{
/*Setupencoderpinsasinputs*/
pinMode(ENC_A,INPUT);
digitalWrite(ENC_A,HIGH);
pinMode(ENC_B,INPUT);
digitalWrite(ENC_B,HIGH);
Serial.begin(115200);
Serial.println("Start");
}

voidloop()
{
staticuint8_tcounter=0;//thisvariablewillbechangedbyencoderinput

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

1/17

3/31/2015

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

ReadingrotaryencoderonArduinoCircuits@Home

int8_ttmpdata;
/**/
tmpdata=read_encoder();
if(tmpdata){
Serial.print("Countervalue:");
Serial.println(counter,DEC);
counter+=tmpdata;
}
}

/*returnschangeinencoderstate(1,0,1)*/
int8_tread_encoder()
{
staticint8_tenc_states[]={0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};
staticuint8_told_AB=0;
/**/
old_AB<<=2;//rememberpreviousstate
old_AB|=(ENC_PORT&0x03);//addcurrentstate
return(enc_states[(old_AB&0x0f)]);
}

Firstthree#definessetnamesforportpins.Thisway,ifyouwanttousedifferentpinsforyourencoder,youcandoit
herewithoutsiftingthroughcodelookingforpinnames.IfyoudliketomoveencoderpinstoArduinopins8and9,
ENC_PORTshallbedefinedasPINB,andforpins0,1asPIND.
Insetup()functionhardwareisinitialized.pinModesetsthepinasinputsowecanreaditanddigitalWriteturnsonpull
upresistoronthepinsoitwontdangleintheairwhenswitchisopen.Finally,theserialportisinitializedandmessageis
printedasanindicatorthatportisworkingifyoucantseeStartonyourterminalscreen,checkPCportsettings.
Letsgodowntoline30,whereread_encoder()functionstarts.enc_states[]arrayisalookuptableitisprefilledwith
encoderstates,with1or1beingvalidstatesand0beinginvalid.Weknowthattherecanbeonlytwovalid
combinationofpreviousandcurrentreadingsoftheencoderoneforthestepinaclockwisedirection,anotheronefor
counterclockwise.Anythingelse,whetheritsencoderthatdidntmovebetweenreadsoranincorrectcombinationdueto
switchbouncing,isreportedaszero.
Notethatold_ABisdeclaredstatic.Thismeansthatitsvaluewillberetainedbetweenfunctioncallsthereforeprevious
encoderreadingwillbepreserved.Whenfunctioniscalled,old_ABgetsshiftedlefttwotimes(line36)savingprevious
readingandsettingtwolowerbitsto0sothecurrentreadingcanbecorrectlyORedhere.ThenENC_PORT&003
readstheporttowhichencoderisconnectedandsetsallbuttwolowerbitstozerosowhenyouORitwithold_ABbits2
7wouldstayintact.ThenitgetsORedwithold_AB(line37,old_AB|=(ENC_PORT&003)).Atthispoint,wehave
previousreadingofencoderpinsinbits2,3ofold_AB,currentreadingsinbits0,1,andtogethertheyformindexof(AKA
pointerto)enc_states[]arrayelementcontainingcurrentstateeitherincrement,decrement,ornochange.Allthatisleft
todoisreturnthisstatetothecallingfunction,andline38doesjustthat.Upperhalfofold_ABgetszeroedbyold_AB&
0x0fifwedontdothis,wewillbereadingmemorypastenc_states[]array.
Theaboveparagraphwasprettylongexplanationformere5linesofcode(countingtwodeclarations)ifyouarereading
this,98%ofworkisdone.Therestofthecodeisveryeasy.Wearenowmovinguptoline17,whereloop()functionis
residing.countervariableistheonewhichismodifiedbyencoderandtmpdataisusedtoholdthereading.Online22,
encoderisread.Ifencoderstatehaschanged,i.e.,read_encoder()returnednonzero,currentvalueofcountervariableis
printedandthencounterisupdatedwithtmpdata.Thisisdonewithinconditionalstatementonlines2227.Theloopthen
endsandstartsagain.
Nowletsbrieflytalkaboutreallifeapplicationsofthismethod.IfyoureusingSparkfunencoder,youllnoticethatitgives
4incrementsperclickanditsimpossibletomakeitholdpositionbetweenclicks.Therefore,tocountclicksyouwillneed
todividecountervariableby4.Also,ifcounterlargerthan255isnecessary,thedeclarationforitwouldhavetobe
changedtouint16_torlonger.Anothernicemodification,leftouttokeepcodesimple,wouldbetomoveenc_states[]
arraytoprogrammemoryusingPROGMEMtypesavingseveralbytesofpreciousRAM.

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

2/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Rotaryencodersingingoutoftune

Inorderforthismethodtoworkwell,read_encoder()functionneeds
tobecalledfairlyoften.Toseewhathappenswhenloopisslow,
lowerserialportspeedgotoline13,change115200to9600,
recompilethesketchandrun(dontforgettoreconfiguretheterminal
onPCside).Pictureontheleftshowstheresult.Notethatencoder
goesdownfrom237to229,thenjumpsupto230,thencontinues
goingdown.Sometimesitcountscorrectlybutgives2or3states
perclickinsteadof4.Instabilitieslikethisaregoodindicationof
slowloop.Ifencoderisusedtothingslikesettingmotorspeedor
soundvolume,thisbehaviorwontdomuchharmbecauseencoder
willneverskipbackmorethanonestateandoverallcountingwould
stillbeintherightdirection.However,ifencoderisusedfor
interfacingwithdisplay,glitcheslikethatareveryannoying.
Therefore,foruserinterfaceapplications,looptimeshouldbekept
shortandinsomecasesitmaybeevennecessarytoconvert
encoderreadingfunctionintointerruptserviceroutine.Giventhesize
andspeedofencoderreadfunction,suchconversioncanbedone

withoutmuchdifficulty.
Tosummarize:Ipresentedamethodtoconvertquadraturerotaryencoderoutputintodirectioninformationusinglookup
table.Themethodmakesdebouncingunnecessary,andasaresult,conversionfunctionimplementedwiththismethodis
veryshort,fast,andworksverywellonsmall8bitMCUplatforms,suchasArduino.
Oleg.
[EDIT]IpostedanewarticledescribingreadinganencoderfromanISR.
Relatedposts:
1. Vigoriusstirringredefined.Part2electronics
April12th,2010|Tags:Arduino,rotaryencoder,sketch|Category:Arduino,MCU,programming|224comments

224commentstoReadingrotaryencoderonArduino
OlderComments 1 2 3

gabriella

November9,2012at11:39amReply
Okthanksalotthatisreallyhelpful.ButassoonasIintegratedthiscodewithsomemorecomplex
codeIhaveusingpulseIn()functiontounderstandtheinputofastandardRCreceiver,andamotordriver
controllingtwomotors,theencoderseemstotallyincorrect:WhenIhadthethesamefunctionsworkingonthe
encoder,Iwasgettingsupercleanvalues.ButwhenIhadmorecodeandtheencoderstuffrunningsidebyside,my
countervaluesaretotallyoff(seebelow,whenspinningtheencoderroundandround).Soitseemslikethetimingis
totallynotworking
ImwonderingwhatImightbedoingwrongbecausenothingtoohighlevelishappeninginmycode,andItookoutall
myprintlns.
Icanattachmycodeifthatdbehelpful,butwaswonderingyourthoughts/experience(reusing2encoderswithsome
otherprocessesgoingoninArduinoUNO)
Thankyousosomuchagainforallthehelpandexplanation.

Ready
Countervalue2:0
Countervalue2:255
Countervalue2:0
Countervalue2:255
Countervalue2:0
Countervalue2:255
Countervalue2:0
Countervalue2:255
Countervalue2:0
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

3/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Countervalue2:255
Countervalue2:254
Countervalue2:253
Countervalue2:254
Countervalue2:253
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:253
Countervalue2:252
Countervalue2:251
Countervalue2:252
Countervalue2:251
Countervalue2:250

oleg

November9,2012at11:49amReply
Thecodeyouveaddedisblockingsomewhere.Youneedtoeitherfixitorswitchtointerruptdriven
encoderreading,likethisone>https://www.circuitsathome.com/mcu/rotaryencoderinterrupt
serviceroutineforavrmicros

gabriella

November9,2012at12:13pmReply
Hm.YeaIcommentedeverythingoutandtheencodersworkgreat.WhenIaddbackinstufftoreadthe
receiver,thatsthepointatwhichtheencodersseemtostopworking:
Channel2Value=pulseIn(RX1,HIGH,20000)//readRCchannel2
Channel1Value=pulseIn(RX3,HIGH,20000)//readRCchannel2
//Serial.print(motor_body:)
Imwonderingwhatyoumeanbythecodeisblockingsomewhereorwhatafixwouldbe??
Thanksalotagain

oleg

November9,2012at12:50pmReply
Blockingiswhenapieceofcodeiswaitingforsomeeventtohappen,interruptingtheflowof
executionofthemainloop.Forexample,delay()isblockingtheprogramwontcontinueuntil
timespecifiedasdelayhasexpired.Ifyouhaveadelayofonesecondinyourmainloop,youcanrotateyour
encoderfullcircleandmisseverypulse.
Fixingmeansfindingblockingcodeandwritingitdifferently.Whatdoes20000meaninpulseIn?

gabriella

November9,2012at5:25pmReply
OkIguessIhavetouseaninterrupt?IwantedtobeabletouseArduinoUNOwiththetwoencoders.
WouldtherebeawaytousetwoencoderswithArduinoUNO,evenifthetwodefaultinteruptpinsare2
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

4/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

and3?
thethirdparameter(20000)isthetimeoutinmicroseconds.
justfyi,PulseIN():Readsapulse(eitherHIGHorLOW)onapin.Forexample,ifvalueisHIGH,pulseIn()waitsfor
thepintogoHIGH,startstiming,thenwaitsforthepintogoLOWandstopstiming.Returnsthelengthofthepulsein
microseconds.Givesupandreturns0ifnopulsestartswithinaspecifiedtimeout.soitseemstheproblemisit
delaysandwaits(ieblocking)

oleg

November10,2012at10:52amReply
Yes,tryinterruptcodeandseeifitworksforyou.Thecodeusesinterruptonchange,youcan
configureanypintobeasourceofthisinterrupt.

KyleRassweiler

November15,2012at12:22amReply
Iwaswonderingwhyyouneededatimeoutof2000?Wouldtheserialnotstillworkfinewithout?(I
thinkthattimeoutmaybeanexampleofblocking).

SteffanoGizzler

November30,2012at3:23pmReply
HiOleg
Ireallyappreciateyourtutorials,theyaregreatandamwonderingifyoucouldputmeintherightdirectionasIam
buildingabidirectionalpeoplesensorandcounterinaroomusingtwoinfraredsensors(S1andS2).WhatIwantisthe
firstsequenceonbreakingS1andS2thechangeshouldsignalentryandincrementacounterwhilstbreakingthe
beaminthesecondsequenceS2firstandS1willsignalexitanddecrementacounteranddisplaythecountvalueona
3digit7segmentdisplay.
Ihavethoughtofusingtheideaofreadingtworotaryencoderusingexternalinterruptsonanarduino.Isthistheright
waytogo??
MuchThanks.
Steffano.

oleg

November30,2012at4:04pmReply
Icantseeanyencoderapplicationhere.Yourprojectisquitestraightforward,justcodeyoursensor
statesdirectly.

SteffanoGizzler

December1,2012at10:45amReply
HiOleg,
Pleasecouldyoukindlyelaborateonwhatyoumeanbycodingthesensorstatesdirectly?sinceitsasequence.
amusingIRsensorswithmakeandbreakbeam.Iwillappreciateanymoreinformation.
Thankyou.
Staffano.

SteffanoGizzler

December3,2012at11:31amReply
HiOleg,
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

5/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Thisisthefarhavecomesofarandamserialprintingthecounts.AnyideahowIcouldholdoldvalueandupdatethis
oldvaluewiththecurrentvalcounttoa3digitsevensegmentdisplay?dependingonhowthesensorsaretripped?
Anycorrectionorsuggestionsamverywillingtolearn
intcounter,S1_SIG=0,S2_SIG=1
voidsetup(){
attachInterrupt(0,S1_RISE,RISING)//hookedtopin2onmega2560
attachInterrupt(1,S2_RISE,RISING)//hookedtopin3
Serial.begin(115200)
}//setup
voidloop(){
}
voidS1_RISE(){
detachInterrupt(0)
S1_SIG=1
if(S2_SIG==0)
counter++//entry
if(S2_SIG==1)
counter//exit
Serial.println(counter)
attachInterrupt(0,S1_FALL,FALLING)
}
voidS1_FALL(){
detachInterrupt(0)
S1_SIG=0
if(S2_SIG==1)
counter++//entry
if(S2_SIG==0)
counter//exit
Serial.println(counter)
attachInterrupt(0,S1_RISE,RISING)
}
voidS2_RISE(){
detachInterrupt(1)
S2_SIG=1
if(S1_SIG==1)
counter++//entry
if(S1_SIG==0)
counter//exit
Serial.println(counter)
attachInterrupt(1,S2_FALL,FALLING)
}
voidS2_FALL(){
detachInterrupt(1)
S2_SIG=0
if(S1_SIG==0)
counter++//entry
if(S1_SIG==1)
counter//exit
Serial.println(counter)
attachInterrupt(1,S2_RISE,RISING)
}
Steffano

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

6/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

steffano

December27,2012at4:36pmReply
Imanagedtodomy2ISRforthetwosensorsandthe3digitsevensegmentdisplay,howevertheonly
problemhavegotiswhenmysensorsarebrokenatfirstthecountgoesnegativefor2or3cyclesthen
comestopositive(normal)doesanyonehaveanideahowtocorrectthis??please.Ihavedeclaredstaticintiinloop.

Windsor

February1,2013at8:53pmReply
Hi,thanksforthegreattutorial.Iadaptedyourcode(withminorchanges)torunonanSTM32F100B
(ARM)micro.Worksflawlesslywithmyencoderwithouttheneedforanyhardwaredebouncingcircuitry!

Josh

February23,2013at9:03pmReply
HiMr.Oleg,
Gooddaytoyouandthanksforthegreatefforthelpingarookielikemetostartwiththearduino,Ihave
triedyourcodeusingUnoanditworksflawlesslybutwhenitrieditusingtheLeonardo,itdidntwork,wanderingwhat
couldbetheproblem.

Josh

February23,2013at10:14pmReply
HiMr.Oleg,
BelowisthecodeIusedwithUnoandLeonardo,itworkswithUnobutnotwithLeonardo.
/*Rotaryencoderreadexample*/
#defineENC_A14
#defineENC_B15
#defineENC_PORTPINC
//constantswontchange.Theyreusedhereto
//setpinnumbers:
constintbuttonPin=2//thenumberofthepushbuttonpin
constintledPin=13//thenumberoftheLEDpin
//variableswillchange:
intbuttonState=0//variableforreadingthepushbuttonstatus
intswitch0=0
voidsetup(){
/*Setupencoderpinsasinputs*/
pinMode(ENC_A,INPUT)
digitalWrite(ENC_A,HIGH)
pinMode(ENC_B,INPUT)
digitalWrite(ENC_B,HIGH)
//initializeserialcommunicationat9600bitspersecond:
Serial.begin(115200)
Serial.println(Start)
delay(1)
//initializetheLEDpinasanoutput:
pinMode(ledPin,OUTPUT)
//initializethepushbuttonpinasaninput:
pinMode(buttonPin,INPUT)
}
voidloop(){
staticuint8_tcounter=0//thisvariablewillbechangedbyencoderinput
int8_ttmpdata
/**/
tmpdata=read_encoder()
if(tmpdata){
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

7/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Serial.print(Countervalue:)
Serial.println(counter,DEC)
counter+=tmpdata
}
//readthestateofthepushbuttonvalue:
buttonState=digitalRead(buttonPin)
//checkifthepushbuttonispressed.
//ifitis,thebuttonStateisHIGH:
if(buttonState==LOW){
//turnLEDon:
digitalWrite(ledPin,HIGH)
//printoutthestateofthebutton:
if(switch0==0){
Serial.print(Pinindot)
delay(1)
Serial.println(buttonState)
delay(1)//delayinbetweenreadsforstability
switch0=1
}
}
else{
//turnLEDoff:
digitalWrite(ledPin,LOW)
if(switch0==1){
Serial.print(Pinindot)
delay(1)
Serial.println(buttonState)
delay(1)//delayinbetweenreadsforstability
switch0=0
}
}
}
/*returnschangeinencoderstate(1,0,1)*/
int8_tread_encoder()
{
staticint8_tenc_states[]={0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0}
staticuint8_told_AB=0
/**/
old_AB<<=2//rememberpreviousstate
old_AB|=(ENC_PORT&003)//addcurrentstate
return(enc_states[(old_AB&0x0f)])
}

Josh

February23,2013at10:22pmReply
ThedebouncedidnotworkformebutinsteadIusedtheswitchwhichisperfect.Theonlyoutputshownin
theSerialMonitoriswhentheswitchisbeingpressedbutnottheencoder,Iamusinganencoderwitha
switch.

Mike

March5,2013at1:18pmReply
Ok,IgetitandIlikeitalot.TheonlythingthatIcannotfigureoutishowtokeepitfromgoingfrom255to
0orfrom0to255.IsthereawaythatIcanstopitfromoverflowingtheregisterandjustparkitatmaxor
minuntiltheuserdecreasesthevalue?

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

8/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

alwerner

March14,2013at9:47amReply
UsingtwoormoreencoderwiththeArduino?
ItalldependsonthetotaloftasksbeingperformedbytheArduino,andthenumberof
pulsesreceivedbytheprocessor.
Sayforexampleyouhaveasmallslowmovingxytable,with2rotaryUSDigitalencodersgeneratingsay4000pulses
persecondanddrivingtwosteppermotorswithanEasydriverboardyouwouldsoonberunningoutofheadroomon
yourproject.
Mysuggestionswouldbetouse,twoTiny13chipsfromAtmeltoencodetherotaryencoders,andthanfeedthe
resultantsignalintoyourArduino,whereitwillgiveanexcellentperformance.Inmyhumbleopnionitmayeven
supportthreechannels,XYandZ.
Youwouldneedsomemachinecodeexperiencetodothis,butthiswouldbeworthlearning.
Goodluck.

Seif

April6,2013at1:04pmReply
Hi,
ThankyouforthisgreatusefularticleImwonderingifIcanuseyouideawithArduinoUno??Imeantousethe
rotaryencoderwithArduinoUnoinordertoselectthepowerofmyRCcarwhichImbuilding
thanxagain

oleg

April6,2013at1:26pmReply
UNOshouldwork.

SalvatoreAiello

April15,2013at12:49pmReply
Hi,
Sweetbitofcode!Iamusingitinaprojectatwork,usingtheencodertodisplayamotorspeedselection
onasevensegmentdisplayanditworksverynicelyindeed.Onceyouremovetheserial.printcommandsitisdifficult
tospinthebareencodershaftquicklyenoughtogenerateamisread.Withasuitablysizedknobontheshaftitisgoing
toslowrotationspeedandmakeitvirtuallyimpossibleforthecasualoperatortogetanerroneousreading
Thanks!

Marco

August1,2013at1:23pmReply
Hi,verynicejob
myR2D2Domesencodersensorhas3output,oneofthemreadsjustonespecialdentonthemotor
gear,likeaZEROPOSITION.
HowcanIimplementitinthecode?
AlsoHowcanImakeencoderscountto36or+18to18?
Thanksjustlearninghere

Alex

August14,2013at9:48amReply
Hereisthecodewithzeropositionand3outputs.
intcounter,S1_SIG=0,S2_SIG=1,S3_SIG=1
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

9/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

boolfirstinit=false
voidsetup()
{
attachInterrupt(0,S1_RISE,RISING)//hookedtopin2onmega2560
attachInterrupt(1,S2_RISE,RISING)//hookedtopin3
attachInterrupt(2,S3_RISE,RISING)//hookedtopin21
Serial.begin(115200)
}//setup
voidloop()
{
}
voidS1_RISE()
{
detachInterrupt(0)
S1_SIG=1
if(S2_SIG==0)
counter++//entry
if(S2_SIG==1)
counter//exit
Serial.println(counter)
attachInterrupt(0,S1_FALL,FALLING)
}
voidS1_FALL()
{
detachInterrupt(0)
S1_SIG=0
if(S2_SIG==1)
counter++//entry
if(S2_SIG==0)
counter//exit
Serial.println(counter)
attachInterrupt(0,S1_RISE,RISING)
}
voidS2_RISE()
{
detachInterrupt(1)
S2_SIG=1
if(S1_SIG==1)
counter++//entry
if(S1_SIG==0)
counter//exit
//Serial.println(counter)
attachInterrupt(1,S2_FALL,FALLING)
}
voidS2_FALL()
{
detachInterrupt(1)
S2_SIG=0
if(S1_SIG==0)
counter++//entry
if(S1_SIG==1)
counter//exit
Serial.println(counter)
attachInterrupt(1,S2_RISE,RISING)
}
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

10/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

voidS3_RISE()
{
S3_SIG=1
detachInterrupt(2)
if(!firstinit&&((S2_SIG==1&&S1_SIG==1)||(S1_SIG==0&&S2_SIG==1)))
{
counter=0
firstinit=true
}
attachInterrupt(2,S3_FALL,FALLING)
}
voidS3_FALL()
{
S3_SIG=0
detachInterrupt(2)
if(!firstinit&&((S2_SIG==1&&S1_SIG==1)||(S1_SIG==1&&S2_SIG==0)))
{
counter=0
firstinit=true
}
attachInterrupt(2,S3_RISE,RISING)
}

Marty

August30,2013at9:31pmReply
IamnewtoArduinosandamstartingtoplaywiththem.Ihaveseenmanyexamplesofrotaryencoder
code.ButnonthatusetheLeonardotooutputkeypresscommandswhenrotated.Myapplicationisa
smallCNCverticalmachiningcenter.Thecontrolitselfcannotacceptarotaryencoder(manualpulsegenerator)The
controlisPCbased.ItCANacceptkeypresses,forexample,tomovethetableinthesedirections:
X+Ctrl+RightArrowKey
XCtrl+LeftArrowKey
Y+Ctrl+UpArrowKey
YCtrl+DownArrowKey
Z+Ctrl+PageUpKey
ZCtrl+PageDownKey
A+Ctrl+Plus(+)Key
ACtrl+Minus()Key
IcanmakeitworkwithoutaCtrlkeypress,butbettertohavethecombinationifpossible.Iwasthinkingofusinga4
positionrotaryswitch.Eachpositionwouldbeforeachaxis,X,Y,ZandA.Whentheswitchisintheproperposition,
thendependingonwhichdirectiontheMPGhandwheelwasturned,Leonardowouldsendtheappropriatekeyboard
characterviathePCsUSBport.OnekeypressforeachpulseoftheMPGhandwheel.Itisa100PPRhandwheel.
Isthisdoableandmightsomeonebeabletohelpcutmylearningcurvedownwithanexampleofthecode?Thanks!

faultymonk

September15,2013at10:19pmReply
JustasanotetopeopletryingtouseaLeonardo(orMicro),thecodeexamplewillworkifyouuse:
#defineENC_AA4
#defineENC_BA5
#defineENC_PORTPINF

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

11/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

oleg

September15,2013at10:37pmReply
Thanks!

Ron

September17,2013at4:06amReply
Youmentionthis:
Sparkfunencoder,youllnoticethatitgives4incrementsperclickanditsimpossibletomakeithold
positionbetweenclicks.Therefore,tocountclicksyouwillneedtodividecountervariableby4
MyQuadratureencodersaregiving2countsperclick.Wouldyoumindaquicklessononjusthowtodothis,sincethe
variableisntadecimalnumber?
Manythanks!Yourcodeisforcingmetodiginandlearnmorethanjustthesimpleprogramming,asgivenonthe
Arduinositeexampleswhichiswhatteachingisallabout!

oleg

September17,2013at9:33amReply
Dowhatdivideby2?Thefastestwayistorightshiftonce.

Ron

September17,2013at8:06pmReply
Igotitoneofthosedoh!momentssorry!

Ron

September18,2013at12:48pmReply
(withregardtothesolutionfor24posencoderwhichgives2pulsesperclick)
WhathappenswhenIbitwiseshift(1bit)rightanegativenumber,aswhenImturningCCW?
Doesthesignbitstaywhereitssupposedto?
ImgettingverydifferentresultsCWfromCCW.

oleg

September18,2013at12:53pmReply
Youdontshiftnumbers,youshiftbytes.Whenyourightshifttheleftmostbitbecomeszero.Ifthis
bitrepresentedasign,itwillbegone.

oleg

September18,2013at5:44pmReply
Ifyourencoderclickseverysecondpulseyoucandetermineaclickpositionwithoutdividing.Even
incrementswillhavezeroinbit0andoddincrementswillhaveone.Thisistrueforbothsignedand
unsignedrepresentations.Also,checkingsinglebit,likeif(count&0x01){...,couldbefasterthan
shifting.

fbonan

October3,2013at7:46amReply
ThanksOleg,thissampleisgreatandsavemeyears:)
Manyrequestedacompleteworkingexamplewith2encoders,hereitis:
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

12/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

#defineENC_1_AA0
#defineENC_1_BA1
#defineENC_2_AA2
#defineENC_2_BA3
intencoder_1_value=0
intencoder_2_value=0
staticint8_tenc_states[]={0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0}
voidsetup(){
/*Setupencoderpinsasinputs*/
pinMode(ENC_1_A,INPUT)
digitalWrite(ENC_1_A,HIGH)
pinMode(ENC_1_B,INPUT)
digitalWrite(ENC_1_B,HIGH)
/*Setupencoderpinsasinputs*/
pinMode(ENC_2_A,INPUT)
digitalWrite(ENC_2_A,HIGH)
pinMode(ENC_2_B,INPUT)
digitalWrite(ENC_2_B,HIGH)
Serial.begin(115200)
Serial.println(************Start*************)
}
/*returnschangeinencoderstate(1,0,1)*/
int8_tread_encoder1(){
staticuint8_told_AB=0
old_AB<<=2
old_AB|=((digitalRead(ENC_1_B))?(1<<1):0)|((digitalRead(ENC_1_A))?(1<<0):0)
return(enc_states[(old_AB&0x0f)])
}
/*returnschangeinencoderstate(1,0,1)*/
int8_tread_encoder2(){
staticuint8_told_AB=0
old_AB<<=2
old_AB|=((digitalRead(ENC_2_B))?(1<<1):0)|((digitalRead(ENC_2_A))?(1<<0):0)
return(enc_states[(old_AB&0x0f)])
}
voidloop(){
int8_tencoderdata1
int8_tencoderdata2
encoderdata1=read_encoder1()
if(encoderdata1){
encoder_1_value+=encoderdata1
Serial.print("Encoder1:")
Serial.println(encoder_1_value)
}
encoderdata2=read_encoder2()
if(encoderdata2){
encoder_2_value+=encoderdata2
Serial.print("Encoder2:")
Serial.println(encoder_2_value)
}
}

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

13/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Fabrice

Brett

October25,2014at4:13pmReply
Forsomereasonyourcodeworkedformewhenolegswouldnot.Thankyouforpostingit!

prins

November2,2013at2:28pmReply
greattutorial.
IfoundHIDboardusingPIC18F4550chipcapableofreading16rotaryencoders(alltypesofrotary)inrealtime,and
noadditionalchip.anyoneknowshowtodothatinarduino.whatmethodisitimplementing,timerorinterrupt?

mark

November14,2013at4:09amReply
howcanIusethiscodeonmega2560.Igetserialtoprintstartbutthatsit.WhatpinedoIuse?

oleg

November14,2013at8:45amReply
For2560,youdontneedtodoanything,thepinsareswitchedinthecodeduringcompile.

mark

November20,2013at1:29amReply
Thanks,
SoImusinganalogpins14and15butgetnoresponsefromtheencoder.Tried14and15Digital,no
response.
IfyoudliketomoveencoderpinstoArduinopins8and9,ENC_PORTshallbedefinedasPINB,andfor
pins0,1asPIND.
whydoesENC_PORTchangewhenchangingpins,isthisuniquetotheboardyourusing?
whatsENC_PORTdo?

OlegMazurov

November20,2013at9:18amReply
ENC_PORTisa#defineforaportname.Doesitworkifyoureusingthesamepinsas
I?

Jay

October7,2014at8:57pm
HiOleg,IalsohavethesameproblemwithaMEGA256,Idontgetresponsefrom
theencoder.
TriedchangingENC_PORTtoPINBPINCandPIND,noneofthemwork.
Anyidea?

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

14/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

OlegMazurov

October7,2014at10:48pm
Makesureyourencoderisconnectedtotheportyoursketchisreading,portbits0
and1.

Jay

October8,2014at1:31pm
Yes,itsproperlywiredandconnectedtotherightpins

OlegMazurov

October8,2014at1:48pm
Itshouldworkthen,butitdoesnt.Maybeyourtestingneedstobechanged?
IncludetheArduinoitself.Forexample,makesureyoucanreadasingepin.
Connectapushbuttontoadatapinandwriteasketchwhichreadsthestateofthispinand
printsitout.Therearemanyexamplesonthenetdoingsimilarthings.Thenmovethebuttonto
oneofthepinsintendedfortheencoderandmakeitworkthere,thenmovetotheotherpin.
Thenconnecttheencoder,itsreallyapairofpushbuttonswithsomecleversequencer.Then
modifymysketchwithwhatyouhavelearneditwillwork.
PostagoodpictureofyoursetuptotheaccompanyingG+communitysothatotherpeoplecan
seeitandhelpyoutoo>https://plus.google.com/u/0/communities/113627505540902841340

Allan

November25,2013at4:18amReply
isitpossobletomeasurewheelspeedusingarotaryencoderincrementalwithoutputA,BanZ

OlegMazurov

November25,2013at9:16amReply
Yesbutyouwillneeddifferentlookuptable.

aditya

December10,2013at5:36amReply
Ihave12V,500RPM,15KgcmDCgearedmotorandencoder.HowcouldIcontroltheDCmotorto
rotateinforward,ReversedirectionandNoofrotationsofDCmotorshaft.

MikeKehrli

December18,2013at12:53pmReply
HiOleg,
IadaptedthiscodetoaPICchipprojectIwas/amworkingonmanymonthsago.Itmademyrotaryknobfunctionality
perfectlycleanforthefirsttime.Thecodewasmorecompactaswell.Ineverdidmentionit,butthiswasreallyhelpful
tome.Itworksveryverywellonarotaryencoderwithabsolutelynohardwaredebouncing.Thesignalisreallyugly.
Justwantedtosaythanks.Ivetriedlotsofdebouncecode.ThisisnotonlythebestIvefound,butthebestbyfar.

LiamGoudge

December22,2013at3:46amReply
HiOleg.
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

15/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

Whatanelegantalgorithmread_encoderisaverynicewaytoimplementthestatemachine.
Thanksforpublishingandsharingyourideas.
VerysimpleporttotheFreescaleplatformonARMsMBED.
WorkedverywellbutIdidneed100nFofantibounceonmyPanasonicEVEKE2F2024Bencoder,perhapsbecause
thisCPUisclockedsomuchfasterthantheATMEGAandAVRs.

JeffBeougher

February16,2014at10:13amReply
Iamattemptingtoconnect6encoderstoanArduinoLeonardowithaMCP23017I2cPortExpander.I
havebeenabletouseoneencoderontheArduinodirectly.WhatIamattemptingtodoisdependingifthe
encoderisturnedupordowntosendakeyboardscankeytotothecomputerforaproject.Iwashopingtohavesome
typeofmultiplexingtobeabletoreadeachencoderandknowiftheyhavebeenturned.TheMCP23017hasnot
helped.IknowitworksbecauseIhavebeenabletousetheexamplecodesandblinkanledandseebuttonpress
input.
SomyquestionishowcanImultiplex6rotaryencoders.EitherusingtheMCP23017oradifferentinputexpanderof
sometype.
LinkstotheencoderandMCP.
http://www.adafruit.com/products/377
http://www.adafruit.com/products/732

Neelam

April17,2014at10:55amReply
Hi,
Myprojectistocontrolthespeedofthedcmotor(Hardware)usingPIDcontrollerinLabVIEW.ForinterfacingLabview
withdcmotor,IamusingArduinoUno.Forencoder,IamusingOptocouplerandaschmitttrigger.Theencoderhas
threeterminals.Redbrown&black.redandblackarefor+5vandgroundrespectivelyandbrownwillreadthevalue
(i.eno.ofrotations)fromthedcmotor.Thisoutputshouldbeconnectedtoarduinowhichinturnwillpassthisvalueto
labview.PleasetellmeonwhichpinofarduinoIshouldconnectthatbrownwire.
Fromdigitalpin3ofarduino,IampassingPWMsignaltothedcmotor.Itriedtoconnectthatbrownwireofencoderto
pin5butIamgettinganunknownerror.
Pleasehelpmeinthis.

peter

January17,2015at11:22pmReply
HiOleg.
thanksforyourdemonstration.

Robert

March28,2015at1:34pmReply
ThanksOleg,yourcodeworksgreatontheSparkfunilluminatedRGBencoders.
TogetittoworkonmyMEGA2560,IusedA0andA1,changingthedefinitionsto:
#defineENC_AA0
#defineENC_BA1
#defineENC_PORTPINF

Herman

March30,2015at5:35pmReply
IamnewatArduino(Uno)andwritingcodesothisisagoodexampleforme.ThanksOleg!
Ihaveabagofencodersthatseemtoworkdifferent.IputsomeLEDsontheterminalstoseehowthey
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

16/17

3/31/2015

ReadingrotaryencoderonArduinoCircuits@Home

work.Whenturningclockwisebothoutputsbecomehighsimiltanious,thenonegoeslowandthentheothergoeslow.
Whenturningcounter/anticlockwisethefirstonebecomeshigh,thenthesecondoneandthentheybothgetlowatthe
sametime.Likethis:
010010010
011011011
IsthereaneasywayIcanchangethiscodesomyrotaryencoderswillwork?Ihopeyoucanhelpme.

OlegMazurov

March30,2015at6:25pmReply
Imnotsureabouteasyway.ThefundamentalpropertyofGreycodeencoderisthatonlyone
outputischangingatatimesothatwhenbothhaschangedsimultaneouslyyouwouldknowthat
theoutputsarewrongsomehow.Youcanchangethelookuptabletogiveproperincrement/decrementforyour
sequencebutthenyoudhavetoaddadebounce.

OlderComments 1 2 3

http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino

17/17

You might also like