Reading Rotary Encoder on Arduino « Circuits@Home
-
Upload
sukaryadi1 -
Category
Documents
-
view
85 -
download
4
description
Transcript of Reading Rotary Encoder on Arduino « Circuits@Home
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 1/17
Sparkfun2010AutonomousVehicleCompetition DigitalcameracontrolusingArduinoUSBHostShield.Part1basics.
RotaryencoderconnectedtoArduino
ReadingrotaryencoderonArduinoByOlegMazurov
Quadraturerotaryencoders,alsoknownasrotarypulsegenerators,arepopularinputdevicesforembeddedplatforms,includingArduino.SeveralrotaryencodercodeexamplesarepostedonArduinositeandelsewhere,however,theytreatencoderasapairofswitches,addingdecoding/debouncingoverhead.Formanyyears,IusedanalgorithmbasedonthefactthatquadratureencoderisaGraycodegeneratorandiftreatedassuch,canbereadreliablyin3straightstepwithoutneedfordebouncing.Asaresult,thecodeImusingisveryfastandsimple,worksverywellwithcheaplowqualityencoders,butissomewhatcrypticanddifficulttounderstand.SoonafterpostingoneofmyprojectswhereIusedrotaryencodertosetmotorspeedistartedreceivingemailsaskingtoexplainthecode.ThisarticleisasummaryofmyrepliesImpresentingsmallexamplewrittenforthepurposeofillustratingmymethod.Imalsogoingthroughthecodehighlightingimportantparts.
Thehardwaresetupcanbeseenontitlepicture.TheencoderfromSparkfunisconnectedtoavintageAtmega168basedArduinoPro.Commonpinoftheencoderisconnectedtoground,pinsAandBareconnectedtopins14and15,AKAAnalogpins0and1,configuredasdigitalinputs.WealsoneedaserialconnectiontothePCtoreceivepower,programtheArduino,andsendprogramoutputtotheterminal.Forthispurpose,SparkfunFTDIbasicbreakoutisused.
Connectingencoderpinstopins0and1of8bitMCUportmakesencoderreadingcodeverysimple.Ifanalogpinsareneededforsomethingelse,itispossibletomoveencodertodigitalpins8,9or0,1(losingserialport)withnomodificationofcodelogic.Whiletechnicallyusinganytwoconsecutiveportpinsispossiblewithabitoftweaking,usingnonconsecutivepinsforencoderinputwiththismethodisnotrecommended.Lastly,itsometimeshardtodeterminewhichencoderpinisAandwhichisBitiseasiertoconnectthematrandomandifdirectioniswrong,swapthepins.
Examplecodeispostedbelow.ItiscompletesketchyoucancopyitfromthispageandpasteintoArduinoIDEwindow,compile,uploadandrun.Theresultofrotatingtheencodercanbeseeninterminalwindow.Notethatserialspeedinthesketchissetto115200,youwillneedtosetyourPCterminaltothatspeedaswell.Theexplanationofthecodeisgivenafterthelisting.
12345678910111213141516171819
/*Rotaryencoderreadexample*/#defineENC_A14#defineENC_B15#defineENC_PORTPINCvoidsetup(){/*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
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 2/17
2021222324252627282930313233343536373839
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
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 3/17
Rotaryencodersingingoutoftune
Inorderforthismethodtoworkwell,read_encoder()functionneedstobecalledfairlyoften.Toseewhathappenswhenloopisslow,lowerserialportspeedgotoline13,change115200to9600,recompilethesketchandrun(dontforgettoreconfiguretheterminalonPCside).Pictureontheleftshowstheresult.Notethatencodergoesdownfrom237to229,thenjumpsupto230,thencontinuesgoingdown.Sometimesitcountscorrectlybutgives2or3statesperclickinsteadof4.Instabilitieslikethisaregoodindicationofslowloop.Ifencoderisusedtothingslikesettingmotorspeedorsoundvolume,thisbehaviorwontdomuchharmbecauseencoderwillneverskipbackmorethanonestateandoverallcountingwouldstillbeintherightdirection.However,ifencoderisusedforinterfacingwithdisplay,glitcheslikethatareveryannoying.Therefore,foruserinterfaceapplications,looptimeshouldbekeptshortandinsomecasesitmaybeevennecessarytoconvertencoderreadingfunctionintointerruptserviceroutine.Giventhesizeandspeedofencoderreadfunction,suchconversioncanbedone
withoutmuchdifficulty.
Tosummarize:Ipresentedamethodtoconvertquadraturerotaryencoderoutputintodirectioninformationusinglookuptable.Themethodmakesdebouncingunnecessary,andasaresult,conversionfunctionimplementedwiththismethodisveryshort,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
gabriellaNovember9,2012at11:39amReply
Okthanksalotthatisreallyhelpful.ButassoonasIintegratedthiscodewithsomemorecomplexcodeIhaveusingpulseIn()functiontounderstandtheinputofastandardRCreceiver,andamotordriver
controllingtwomotors,theencoderseemstotallyincorrect:WhenIhadthethesamefunctionsworkingontheencoder,Iwasgettingsupercleanvalues.ButwhenIhadmorecodeandtheencoderstuffrunningsidebyside,mycountervaluesaretotallyoff(seebelow,whenspinningtheencoderroundandround).SoitseemslikethetimingistotallynotworkingImwonderingwhatImightbedoingwrongbecausenothingtoohighlevelishappeninginmycode,andItookoutallmyprintlns.
Icanattachmycodeifthatdbehelpful,butwaswonderingyourthoughts/experience(reusing2encoderswithsomeotherprocessesgoingoninArduinoUNO)Thankyousosomuchagainforallthehelpandexplanation.
ReadyCountervalue2:0Countervalue2:255Countervalue2:0Countervalue2:255Countervalue2:0Countervalue2:255Countervalue2:0Countervalue2:255Countervalue2:0
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 4/17
Countervalue2:255Countervalue2:254Countervalue2:253Countervalue2:254Countervalue2:253Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:253Countervalue2:252Countervalue2:251Countervalue2:252Countervalue2:251Countervalue2:250
olegNovember9,2012at11:49amReply
Thecodeyouveaddedisblockingsomewhere.Youneedtoeitherfixitorswitchtointerruptdrivenencoderreading,likethisone>https://www.circuitsathome.com/mcu/rotaryencoderinterrupt
serviceroutineforavrmicros
gabriellaNovember9,2012at12:13pmReply
Hm.YeaIcommentedeverythingoutandtheencodersworkgreat.WhenIaddbackinstufftoreadthereceiver,thatsthepointatwhichtheencodersseemtostopworking:
Channel2Value=pulseIn(RX1,HIGH,20000)//readRCchannel2
Channel1Value=pulseIn(RX3,HIGH,20000)//readRCchannel2//Serial.print(motor_body:)
Imwonderingwhatyoumeanbythecodeisblockingsomewhereorwhatafixwouldbe??
Thanksalotagain
olegNovember9,2012at12:50pmReply
Blockingiswhenapieceofcodeiswaitingforsomeeventtohappen,interruptingtheflowofexecutionofthemainloop.Forexample,delay()isblockingtheprogramwontcontinueuntil
timespecifiedasdelayhasexpired.Ifyouhaveadelayofonesecondinyourmainloop,youcanrotateyourencoderfullcircleandmisseverypulse.
Fixingmeansfindingblockingcodeandwritingitdifferently.Whatdoes20000meaninpulseIn?
gabriellaNovember9,2012at5:25pmReply
OkIguessIhavetouseaninterrupt?IwantedtobeabletouseArduinoUNOwiththetwoencoders.WouldtherebeawaytousetwoencoderswithArduinoUNO,evenifthetwodefaultinteruptpinsare2
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 5/17
and3?thethirdparameter(20000)isthetimeoutinmicroseconds.
justfyi,PulseIN():Readsapulse(eitherHIGHorLOW)onapin.Forexample,ifvalueisHIGH,pulseIn()waitsforthepintogoHIGH,startstiming,thenwaitsforthepintogoLOWandstopstiming.Returnsthelengthofthepulseinmicroseconds.Givesupandreturns0ifnopulsestartswithinaspecifiedtimeout.soitseemstheproblemisitdelaysandwaits(ieblocking)
olegNovember10,2012at10:52amReply
Yes,tryinterruptcodeandseeifitworksforyou.Thecodeusesinterruptonchange,youcanconfigureanypintobeasourceofthisinterrupt.
KyleRassweilerNovember15,2012at12:22amReply
Iwaswonderingwhyyouneededatimeoutof2000?Wouldtheserialnotstillworkfinewithout?(Ithinkthattimeoutmaybeanexampleofblocking).
SteffanoGizzlerNovember30,2012at3:23pmReply
HiOleg
Ireallyappreciateyourtutorials,theyaregreatandamwonderingifyoucouldputmeintherightdirectionasIambuildingabidirectionalpeoplesensorandcounterinaroomusingtwoinfraredsensors(S1andS2).WhatIwantisthefirstsequenceonbreakingS1andS2thechangeshouldsignalentryandincrementacounterwhilstbreakingthebeaminthesecondsequenceS2firstandS1willsignalexitanddecrementacounteranddisplaythecountvalueona3digit7segmentdisplay.Ihavethoughtofusingtheideaofreadingtworotaryencoderusingexternalinterruptsonanarduino.Isthistherightwaytogo??
MuchThanks.
Steffano.
olegNovember30,2012at4:04pmReply
Icantseeanyencoderapplicationhere.Yourprojectisquitestraightforward,justcodeyoursensorstatesdirectly.
SteffanoGizzlerDecember1,2012at10:45amReply
HiOleg,
Pleasecouldyoukindlyelaborateonwhatyoumeanbycodingthesensorstatesdirectly?sinceitsasequence.amusingIRsensorswithmakeandbreakbeam.Iwillappreciateanymoreinformation.
Thankyou.Staffano.
SteffanoGizzlerDecember3,2012at11:31amReply
HiOleg,
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 6/17
Thisisthefarhavecomesofarandamserialprintingthecounts.AnyideahowIcouldholdoldvalueandupdatethisoldvaluewiththecurrentvalcounttoa3digitsevensegmentdisplay?dependingonhowthesensorsaretripped?Anycorrectionorsuggestionsamverywillingtolearn
intcounter,S1_SIG=0,S2_SIG=1
voidsetup(){attachInterrupt(0,S1_RISE,RISING)//hookedtopin2onmega2560attachInterrupt(1,S2_RISE,RISING)//hookedtopin3Serial.begin(115200)}//setup
voidloop(){
}
voidS1_RISE(){detachInterrupt(0)S1_SIG=1
if(S2_SIG==0)counter++//entryif(S2_SIG==1)counter//exitSerial.println(counter)attachInterrupt(0,S1_FALL,FALLING)}
voidS1_FALL(){detachInterrupt(0)S1_SIG=0
if(S2_SIG==1)counter++//entryif(S2_SIG==0)counter//exitSerial.println(counter)attachInterrupt(0,S1_RISE,RISING)}
voidS2_RISE(){detachInterrupt(1)S2_SIG=1
if(S1_SIG==1)counter++//entryif(S1_SIG==0)counter//exitSerial.println(counter)attachInterrupt(1,S2_FALL,FALLING)}
voidS2_FALL(){detachInterrupt(1)S2_SIG=0
if(S1_SIG==0)counter++//entryif(S1_SIG==1)counter//exitSerial.println(counter)attachInterrupt(1,S2_RISE,RISING)}
Steffano
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 7/17
steffanoDecember27,2012at4:36pmReply
Imanagedtodomy2ISRforthetwosensorsandthe3digitsevensegmentdisplay,howevertheonlyproblemhavegotiswhenmysensorsarebrokenatfirstthecountgoesnegativefor2or3cyclesthen
comestopositive(normal)doesanyonehaveanideahowtocorrectthis??please.Ihavedeclaredstaticintiinloop.
WindsorFebruary1,2013at8:53pmReply
Hi,thanksforthegreattutorial.Iadaptedyourcode(withminorchanges)torunonanSTM32F100B(ARM)micro.Worksflawlesslywithmyencoderwithouttheneedforanyhardwaredebouncingcircuitry!
JoshFebruary23,2013at9:03pmReply
HiMr.Oleg,Gooddaytoyouandthanksforthegreatefforthelpingarookielikemetostartwiththearduino,Ihave
triedyourcodeusingUnoanditworksflawlesslybutwhenitrieditusingtheLeonardo,itdidntwork,wanderingwhatcouldbetheproblem.
JoshFebruary23,2013at10:14pmReply
HiMr.Oleg,BelowisthecodeIusedwithUnoandLeonardo,itworkswithUnobutnotwithLeonardo.
/*Rotaryencoderreadexample*/#defineENC_A14#defineENC_B15#defineENC_PORTPINC//constantswontchange.Theyreusedhereto//setpinnumbers:constintbuttonPin=2//thenumberofthepushbuttonpinconstintledPin=13//thenumberoftheLEDpin
//variableswillchange:intbuttonState=0//variableforreadingthepushbuttonstatusintswitch0=0voidsetup(){/*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//thisvariablewillbechangedbyencoderinputint8_ttmpdata/**/tmpdata=read_encoder()if(tmpdata){
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 8/17
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)//delayinbetweenreadsforstabilityswitch0=1}}else{//turnLEDoff:digitalWrite(ledPin,LOW)if(switch0==1){Serial.print(Pinindot)delay(1)Serial.println(buttonState)delay(1)//delayinbetweenreadsforstabilityswitch0=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
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 9/17
alwernerMarch14,2013at9:47amReply
UsingtwoormoreencoderwiththeArduino?
ItalldependsonthetotaloftasksbeingperformedbytheArduino,andthenumberofpulsesreceivedbytheprocessor.
Sayforexampleyouhaveasmallslowmovingxytable,with2rotaryUSDigitalencodersgeneratingsay4000pulsespersecondanddrivingtwosteppermotorswithanEasydriverboardyouwouldsoonberunningoutofheadroomonyourproject.
Mysuggestionswouldbetouse,twoTiny13chipsfromAtmeltoencodetherotaryencoders,andthanfeedtheresultantsignalintoyourArduino,whereitwillgiveanexcellentperformance.Inmyhumbleopnionitmayevensupportthreechannels,XYandZ.
Youwouldneedsomemachinecodeexperiencetodothis,butthiswouldbeworthlearning.
Goodluck.
SeifApril6,2013at1:04pmReply
Hi,
ThankyouforthisgreatusefularticleImwonderingifIcanuseyouideawithArduinoUno??ImeantousetherotaryencoderwithArduinoUnoinordertoselectthepowerofmyRCcarwhichImbuilding
thanxagain
olegApril6,2013at1:26pmReply
UNOshouldwork.
SalvatoreAielloApril15,2013at12:49pmReply
Hi,Sweetbitofcode!Iamusingitinaprojectatwork,usingtheencodertodisplayamotorspeedselection
onasevensegmentdisplayanditworksverynicelyindeed.Onceyouremovetheserial.printcommandsitisdifficulttospinthebareencodershaftquicklyenoughtogenerateamisread.Withasuitablysizedknobontheshaftitisgoingtoslowrotationspeedandmakeitvirtuallyimpossibleforthecasualoperatortogetanerroneousreading
Thanks!
MarcoAugust1,2013at1:23pmReply
Hi,verynicejobmyR2D2Domesencodersensorhas3output,oneofthemreadsjustonespecialdentonthemotor
gear,likeaZEROPOSITION.HowcanIimplementitinthecode?AlsoHowcanImakeencoderscountto36or+18to18?Thanksjustlearninghere
AlexAugust14,2013at9:48amReply
Hereisthecodewithzeropositionand3outputs.
intcounter,S1_SIG=0,S2_SIG=1,S3_SIG=1
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 10/17
boolfirstinit=false
voidsetup(){attachInterrupt(0,S1_RISE,RISING)//hookedtopin2onmega2560attachInterrupt(1,S2_RISE,RISING)//hookedtopin3attachInterrupt(2,S3_RISE,RISING)//hookedtopin21Serial.begin(115200)}//setup
voidloop(){
}
voidS1_RISE(){detachInterrupt(0)S1_SIG=1
if(S2_SIG==0)counter++//entryif(S2_SIG==1)counter//exitSerial.println(counter)attachInterrupt(0,S1_FALL,FALLING)}
voidS1_FALL(){detachInterrupt(0)S1_SIG=0
if(S2_SIG==1)counter++//entryif(S2_SIG==0)counter//exitSerial.println(counter)attachInterrupt(0,S1_RISE,RISING)}
voidS2_RISE(){detachInterrupt(1)S2_SIG=1
if(S1_SIG==1)counter++//entryif(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++//entryif(S1_SIG==1)counter//exitSerial.println(counter)attachInterrupt(1,S2_RISE,RISING)}
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 11/17
voidS3_RISE(){S3_SIG=1detachInterrupt(2)
if(!firstinit&&((S2_SIG==1&&S1_SIG==1)||(S1_SIG==0&&S2_SIG==1))){counter=0firstinit=true}
attachInterrupt(2,S3_FALL,FALLING)}
voidS3_FALL(){S3_SIG=0detachInterrupt(2)
if(!firstinit&&((S2_SIG==1&&S1_SIG==1)||(S1_SIG==1&&S2_SIG==0))){counter=0firstinit=true}
attachInterrupt(2,S3_RISE,RISING)}
MartyAugust30,2013at9:31pmReply
IamnewtoArduinosandamstartingtoplaywiththem.Ihaveseenmanyexamplesofrotaryencodercode.ButnonthatusetheLeonardotooutputkeypresscommandswhenrotated.Myapplicationisa
smallCNCverticalmachiningcenter.Thecontrolitselfcannotacceptarotaryencoder(manualpulsegenerator)ThecontrolisPCbased.ItCANacceptkeypresses,forexample,tomovethetableinthesedirections:X+Ctrl+RightArrowKeyXCtrl+LeftArrowKeyY+Ctrl+UpArrowKeyYCtrl+DownArrowKeyZ+Ctrl+PageUpKeyZCtrl+PageDownKeyA+Ctrl+Plus(+)KeyACtrl+Minus()Key
IcanmakeitworkwithoutaCtrlkeypress,butbettertohavethecombinationifpossible.Iwasthinkingofusinga4positionrotaryswitch.Eachpositionwouldbeforeachaxis,X,Y,ZandA.Whentheswitchisintheproperposition,thendependingonwhichdirectiontheMPGhandwheelwasturned,LeonardowouldsendtheappropriatekeyboardcharacterviathePCsUSBport.OnekeypressforeachpulseoftheMPGhandwheel.Itisa100PPRhandwheel.
Isthisdoableandmightsomeonebeabletohelpcutmylearningcurvedownwithanexampleofthecode?Thanks!
faultymonkSeptember15,2013at10:19pmReply
JustasanotetopeopletryingtouseaLeonardo(orMicro),thecodeexamplewillworkifyouuse:
#defineENC_AA4#defineENC_BA5#defineENC_PORTPINF
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 12/17
olegSeptember15,2013at10:37pmReply
Thanks!
RonSeptember17,2013at4:06amReply
Youmentionthis:Sparkfunencoder,youllnoticethatitgives4incrementsperclickanditsimpossibletomakeithold
positionbetweenclicks.Therefore,tocountclicksyouwillneedtodividecountervariableby4
MyQuadratureencodersaregiving2countsperclick.Wouldyoumindaquicklessononjusthowtodothis,sincethevariableisntadecimalnumber?
Manythanks!Yourcodeisforcingmetodiginandlearnmorethanjustthesimpleprogramming,asgivenontheArduinositeexampleswhichiswhatteachingisallabout!
olegSeptember17,2013at9:33amReply
Dowhatdivideby2?Thefastestwayistorightshiftonce.
RonSeptember17,2013at8:06pmReply
Igotitoneofthosedoh!momentssorry!
RonSeptember18,2013at12:48pmReply
(withregardtothesolutionfor24posencoderwhichgives2pulsesperclick)
WhathappenswhenIbitwiseshift(1bit)rightanegativenumber,aswhenImturningCCW?Doesthesignbitstaywhereitssupposedto?
ImgettingverydifferentresultsCWfromCCW.
olegSeptember18,2013at12:53pmReply
Youdontshiftnumbers,youshiftbytes.Whenyourightshifttheleftmostbitbecomeszero.Ifthisbitrepresentedasign,itwillbegone.
olegSeptember18,2013at5:44pmReply
Ifyourencoderclickseverysecondpulseyoucandetermineaclickpositionwithoutdividing.Evenincrementswillhavezeroinbit0andoddincrementswillhaveone.Thisistrueforbothsignedand
unsignedrepresentations.Also,checkingsinglebit,likeif(count&0x01){...,couldbefasterthanshifting.
fbonanOctober3,2013at7:46amReply
ThanksOleg,thissampleisgreatandsavemeyears:)Manyrequestedacompleteworkingexamplewith2encoders,hereitis:
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 13/17
#defineENC_1_AA0#defineENC_1_BA1
#defineENC_2_AA2#defineENC_2_BA3
intencoder_1_value=0intencoder_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
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 14/17
Fabrice
BrettOctober25,2014at4:13pmReply
Forsomereasonyourcodeworkedformewhenolegswouldnot.Thankyouforpostingit!
prinsNovember2,2013at2:28pmReply
greattutorial.
IfoundHIDboardusingPIC18F4550chipcapableofreading16rotaryencoders(alltypesofrotary)inrealtime,andnoadditionalchip.anyoneknowshowtodothatinarduino.whatmethodisitimplementing,timerorinterrupt?
markNovember14,2013at4:09amReply
howcanIusethiscodeonmega2560.Igetserialtoprintstartbutthatsit.WhatpinedoIuse?
olegNovember14,2013at8:45amReply
For2560,youdontneedtodoanything,thepinsareswitchedinthecodeduringcompile.
markNovember20,2013at1:29amReply
Thanks,
SoImusinganalogpins14and15butgetnoresponsefromtheencoder.Tried14and15Digital,noresponse.
IfyoudliketomoveencoderpinstoArduinopins8and9,ENC_PORTshallbedefinedasPINB,andforpins0,1asPIND.
whydoesENC_PORTchangewhenchangingpins,isthisuniquetotheboardyourusing?
whatsENC_PORTdo?
OlegMazurovNovember20,2013at9:18amReply
ENC_PORTisa#defineforaportname.DoesitworkifyoureusingthesamepinsasI?
JayOctober7,2014at8:57pm
HiOleg,IalsohavethesameproblemwithaMEGA256,Idontgetresponsefromtheencoder.
TriedchangingENC_PORTtoPINBPINCandPIND,noneofthemwork.Anyidea?
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 15/17
OlegMazurovOctober7,2014at10:48pm
Makesureyourencoderisconnectedtotheportyoursketchisreading,portbits0and1.
JayOctober8,2014at1:31pm
Yes,itsproperlywiredandconnectedtotherightpins
OlegMazurovOctober8,2014at1:48pm
Itshouldworkthen,butitdoesnt.Maybeyourtestingneedstobechanged?IncludetheArduinoitself.Forexample,makesureyoucanreadasingepin.
Connectapushbuttontoadatapinandwriteasketchwhichreadsthestateofthispinandprintsitout.Therearemanyexamplesonthenetdoingsimilarthings.Thenmovethebuttontooneofthepinsintendedfortheencoderandmakeitworkthere,thenmovetotheotherpin.Thenconnecttheencoder,itsreallyapairofpushbuttonswithsomecleversequencer.Thenmodifymysketchwithwhatyouhavelearneditwillwork.
PostagoodpictureofyoursetuptotheaccompanyingG+communitysothatotherpeoplecanseeitandhelpyoutoo>https://plus.google.com/u/0/communities/113627505540902841340
AllanNovember25,2013at4:18amReply
isitpossobletomeasurewheelspeedusingarotaryencoderincrementalwithoutputA,BanZ
OlegMazurovNovember25,2013at9:16amReply
Yesbutyouwillneeddifferentlookuptable.
adityaDecember10,2013at5:36amReply
Ihave12V,500RPM,15KgcmDCgearedmotorandencoder.HowcouldIcontroltheDCmotortorotateinforward,ReversedirectionandNoofrotationsofDCmotorshaft.
MikeKehrliDecember18,2013at12:53pmReply
HiOleg,
IadaptedthiscodetoaPICchipprojectIwas/amworkingonmanymonthsago.Itmademyrotaryknobfunctionalityperfectlycleanforthefirsttime.Thecodewasmorecompactaswell.Ineverdidmentionit,butthiswasreallyhelpfultome.Itworksveryverywellonarotaryencoderwithabsolutelynohardwaredebouncing.Thesignalisreallyugly.
Justwantedtosaythanks.Ivetriedlotsofdebouncecode.ThisisnotonlythebestIvefound,butthebestbyfar.
LiamGoudgeDecember22,2013at3:46amReply
HiOleg.
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 16/17
Whatanelegantalgorithmread_encoderisaverynicewaytoimplementthestatemachine.Thanksforpublishingandsharingyourideas.VerysimpleporttotheFreescaleplatformonARMsMBED.WorkedverywellbutIdidneed100nFofantibounceonmyPanasonicEVEKE2F2024Bencoder,perhapsbecausethisCPUisclockedsomuchfasterthantheATMEGAandAVRs.
JeffBeougherFebruary16,2014at10:13amReply
Iamattemptingtoconnect6encoderstoanArduinoLeonardowithaMCP23017I2cPortExpander.IhavebeenabletouseoneencoderontheArduinodirectly.WhatIamattemptingtodoisdependingifthe
encoderisturnedupordowntosendakeyboardscankeytotothecomputerforaproject.Iwashopingtohavesometypeofmultiplexingtobeabletoreadeachencoderandknowiftheyhavebeenturned.TheMCP23017hasnothelped.IknowitworksbecauseIhavebeenabletousetheexamplecodesandblinkanledandseebuttonpressinput.
SomyquestionishowcanImultiplex6rotaryencoders.EitherusingtheMCP23017oradifferentinputexpanderofsometype.
LinkstotheencoderandMCP.
http://www.adafruit.com/products/377http://www.adafruit.com/products/732
NeelamApril17,2014at10:55amReply
Hi,
Myprojectistocontrolthespeedofthedcmotor(Hardware)usingPIDcontrollerinLabVIEW.ForinterfacingLabviewwithdcmotor,IamusingArduinoUno.Forencoder,IamusingOptocouplerandaschmitttrigger.Theencoderhasthreeterminals.Redbrown&black.redandblackarefor+5vandgroundrespectivelyandbrownwillreadthevalue(i.eno.ofrotations)fromthedcmotor.Thisoutputshouldbeconnectedtoarduinowhichinturnwillpassthisvaluetolabview.PleasetellmeonwhichpinofarduinoIshouldconnectthatbrownwire.
Fromdigitalpin3ofarduino,IampassingPWMsignaltothedcmotor.Itriedtoconnectthatbrownwireofencodertopin5butIamgettinganunknownerror.
Pleasehelpmeinthis.
peterJanuary17,2015at11:22pmReply
HiOleg.thanksforyourdemonstration.
RobertMarch28,2015at1:34pmReply
ThanksOleg,yourcodeworksgreatontheSparkfunilluminatedRGBencoders.
TogetittoworkonmyMEGA2560,IusedA0andA1,changingthedefinitionsto:#defineENC_AA0#defineENC_BA1#defineENC_PORTPINF
HermanMarch30,2015at5:35pmReply
IamnewatArduino(Uno)andwritingcodesothisisagoodexampleforme.ThanksOleg!Ihaveabagofencodersthatseemtoworkdifferent.IputsomeLEDsontheterminalstoseehowthey
-
3/31/2015 ReadingrotaryencoderonArduinoCircuits@Home
http://www.circuitsathome.com/mcu/readingrotaryencoderonarduino 17/17
work.Whenturningclockwisebothoutputsbecomehighsimiltanious,thenonegoeslowandthentheothergoeslow.Whenturningcounter/anticlockwisethefirstonebecomeshigh,thenthesecondoneandthentheybothgetlowatthesametime.Likethis:010010010011011011
IsthereaneasywayIcanchangethiscodesomyrotaryencoderswillwork?Ihopeyoucanhelpme.
OlegMazurovMarch30,2015at6:25pmReply
Imnotsureabouteasyway.ThefundamentalpropertyofGreycodeencoderisthatonlyoneoutputischangingatatimesothatwhenbothhaschangedsimultaneouslyyouwouldknowthat
theoutputsarewrongsomehow.Youcanchangethelookuptabletogiveproperincrement/decrementforyoursequencebutthenyoudhavetoaddadebounce.
OlderComments 1 2 3