Reading Rotary Encoder on Arduino « Circuits@Home

Post on 29-Sep-2015

87 views 4 download

description

code

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