You are on page 1of 30

Hands-On Arduino

Incremental Encoders I

Overview
• Motion Input!
• Encoder Basics!
• Unidirectional Decoding!
• Bi-Directional Decoding!
• Using Pin Change Interrupts!
• Using Assembly Language
Hands On Arduino: Encoders

How Can We Input Motion?
• We need something that will change when the
thing we want to measure moving moves.!
• Generally, something electrical!
• Example: Potentiometers

(Resistance Changes)
Hands On Arduino: Encoders

Types of Motion Input • Position! • Encoder! • Potentiometer! • Velocity! • Tachometer! • Rate Gyro! • Estimator! • Acceleration! • Accelerometer Hands On Arduino: Encoders .

What is an Encoder? • A General concept.! • Implementation depends on the application! • Used for! • Data Compression! • Information Security Hands On Arduino: Encoders .

or I & Q.! • The resolution depends upon the number of pulses in a specified distance! • If measuring only in one direction. two “channels” are needed: A & B.What does the Encoder Encode? • Converts a change in position to digital signals. only one “channel” is required. Hands On Arduino: Encoders .! • If measuring in both directions.

Pulse Technology • Magnetic! • Switch Contacts! • Optical Reflective! • Optical Transmissive Hands On Arduino: Encoders .

Encoder & Decoder Encoder Hands On Arduino: Encoders Decoder .

”! • Often based on a Gray code. thus requires n channels.! • More complicated to work with! • Exact position is always known.! • No data compression.Absolute Encoders • Encoders where each position provides a unique “code. where the codes for adjacent positions differ by at most 1 bit. Hands On Arduino: Encoders .

Absolute Encoders • 8 bit absolute encoder disc! • each ring corresponds to a different bit.! • The number of PPR is 28 = 256! • Requires 8 channels! • only get 1x decoding! • know where you are at startup! Hands On Arduino: Encoders • Gray code decoding .

Single Direction: Encode Detector Emitter A Number of! Pulses per ! Revolution! (PPR): N 1x Resolution: 360°/N! 2x Resolution: 180°/N Hands On Arduino: Encoders .

Single Direction: Decode • Count the pulses (1x)! • Count the transitions (2x)! • The counting can be done by either:! • polling the channel! • using the channel to trigger interrupts An unsigned  long  (uint32_t) is recommended for the! counter! Hands On Arduino: Encoders .

     if  (A^Ap)//is  there  a  difference?      {          count++.begin(9600).      if  (etime  >  1000000)//every  1  sec      {          Serial.  time.   ! void  setup()   {      Serial.   unsigned  long  timep.//reset  timer      }   } .Ap.   byte  A.Sample Code: Polling unsigned  long  count=0.          timep  =  time.  etime.        //set  the  initial  value  of  A      Ap  =  digitalRead(3).//if  so.  increment.   }   Hands On Arduino: Encoders void  loop()   {      A  =  digitalRead(3).  INPUT).      //connect  Channel  A  to  pin  3      pinMode(3.      etime  =  time  -­‐  timep.println(count).      }      Ap  =  A.      //set  the  initial  time          timep  =  micros().      time  =  micros().

     etime  =  time  -­‐  timep.println(count).Sample Code: Using Interrupts unsigned  long  count=0.  time.      //set  the  initial  time      timep  =  micros().   }   ! Hands On Arduino: Encoders void  loop()   {      time  =  micros().  //reset  timer      }   }   .   unsigned  long  timep.     }   ! void  transition()   {      count++.begin(9600).   void  setup()   {      Serial.      if  (etime  >  1000000)//  1  second      {          Serial.  INPUT).        attachInterrupt(1.  CHANGE).transition.      //connect  Channel  A  to  pin  3      pinMode(3.          timep  =  time.  etime.

    }   ! void  transition()   {      count++.   unsigned  long  timep.      //connect  Channel  A  to  pin  3      pinMode(3.   }   ! Hands On Arduino: Encoders void  loop()   {      time  =  micros().        attachInterrupt(1.  //reset  timer      }   }   .   unsigned  long  count=0.transition.      if  (etime  >  1000000)//  1  second      {          Serial.println(count).  etime.begin(9600).      //reset  the  counter          timep  =  time.Sample Code: Velocity Estimation //This  displays  the  number  of  transitions   //  per  second.   void  setup()   {      Serial.  CHANGE).  INPUT).      //set  the  initial  time      timep  =  micros().  time.      etime  =  time  -­‐  timep.          count  =  0.

! • The encoders have a fixed construction:! • Linear: pulses per inch. Hands On Arduino: Encoders .! • The units relate to what the relevant quantity is. Unite! • Units are essential information for real systems. pulses per mm! • Rotary: pulses per revolution. Units.Units.

Units. there are 512x2 = 1024 transitions per revolution.! • for 2x decoding. each count means the motor has turned 
 360/512 = 0.Units. then ! • for 1x decoding.! • Since one revolution equals 360°.7031°.3516° Hands On Arduino: Encoders . and each count corresponds to 
 360/1024 = 0. Unite! • Example: a rotary encoder on a motor shaft with 512 pulses per revolution.

! • No data compression.Absolute Encoders • Encoders where each position provides a unique “code. where the codes for adjacent positions differ by at most 1 bit.”! • Often based on a Gray code. thus requires n channels. Hands On Arduino: Encoders .

BiDirectional Encoding Detectors Emitters A 1 1 0 0 1 1 0 0 In-Phase 1 0 0 1 0 0 Quadrature B Hands On Arduino: Encoders 1 1 .

BiDirectional Encoding Hands On Arduino: Encoders .

BiDirectional Encoding A 1 1 0 0 1 1 0 0 B 1 0 0 1 1 0 0 1 state: 1 2 3 4 1 2 3 4 Hands On Arduino: Encoders State A B 1 1 1 2 1 0 3 0 0 4 0 1 .

BiDirectional Encoding A FORWARD: t B switches before A B t A Reverse t B A switches before B t Hands On Arduino: Encoders .

A 1 1 0 0 1 1 0 0 B 1 0 0 1 1 0 0 1 state: 1 2 3 4 1 2 3 4 Hands On Arduino: Encoders Edge counter A-­‐rising increment A-­‐falling decrement .BiDirectional (1x) Decoding • When B = 1. use the transitions of A to determine whether to increment or decrement the counter.

BiDirectional (2x) Decoding A B 1 1 0 0 1 1 0 0 B 1 0 0 1 1 0 0 1 state: 1 2 3 4 1 2 3 4 Hands On Arduino: Encoders Edge counter 0 A-­‐rising decrement 0 A-­‐falling increment 1 A-­‐falling decrement 1 A-­‐rising increment .

BiDirectional (4x) Decoding prior! state 1 present state AB 11 1 11 X dec X inc 2 10 inc X dec X 3 00 X inc x dec 4 01 dec X inc x Hands On Arduino: Encoders 2 10 3 00 4 01 A 1 1 0 0 1 1 0 0 1 0 0 1 1 0 0 1 state: 1 2 3 4 1 2 3 4 B X  =  do  nothing. .

BiDirectional (4x) Decoding • switch…case ! • if…else…else! • Array! • Pin Position Hands On Arduino: Encoders .

     etime  =  time  -­‐  timep.          timep  =  time.   boolean  A.B.   unsigned  long  timep.      if  ((A==LOW)&&(B==HIGH))  statep  =  4.      pinMode(2.CHANGE).//Channel  A      pinMode(3.BD4x: Switch…Case long  count=0.CHANGE).    //set  the  initial  time      //read  the  initial  value  of  A  &  B      A  =  digitalRead(2).        B  =  digitalRead(3).  statep.Achange.      if  ((A==HIGH)&&(B==LOW))  statep  =  2.      if  ((A==LOW)&&(B==LOW))  statep  =  3.//Channel  B      attachInterrupt(0.   void  setup()   {      Serial.        //set  initial  state  value      if  ((A==HIGH)&&(B==HIGH))  statep  =  1.      }   }   .Bchange.      attachInterrupt(1.println(count).   } Hands On Arduino: Encoders void  loop()   {      time  =  micros().begin(9600).      if  (etime  >  1000000)      {          Serial.      timep  =  micros().  etime.  INPUT).   byte  state.  INPUT).  time.

  } .BD4x: Switch…Case void  Achange()   {      A  =  digitalRead(2).              if  (statep  ==  4)  count++.              break.          }   Hands On Arduino: Encoders      case  2:          {              if  (statep  ==  1)  count++.              break.          }      }      statep  =  state.      if  ((A==HIGH)&&(B==LOW))  state  =  2.      switch  (state)      {          case  1:          {              if  (statep  ==  2)  count-­‐-­‐.          }          default:          {              if  (statep  ==  1)  count-­‐-­‐.        B  =  digitalRead(3).      if  ((A==LOW)&&(B==LOW))  state  =  3.          }          case  3:          {              if  (statep  ==  2)  count++.        //determine  state  value      if  ((A==HIGH)&&(B==HIGH))  state  =  1.              break.              if  (statep  ==  4)  count-­‐-­‐.              if  (statep  ==  3)  count++.      if  ((A==LOW)&&(B==HIGH))  state  =  4.              if  (statep  ==  3)  count-­‐-­‐.

count  =  count  +  QEM[Index]. Hands On Arduino: Encoders .0.-­‐1.0.1.-­‐1.-­‐1.1.0.BD4x: Array State present 0 1 2 3 prior AB 11 10 00 01 0 11 X inc X dec 1 10 dec X inc X 2 00 X dec x inc 3 01 inc X dec x Quadrature  Encoder  Matrix  (Array):     QEM[16]  =  {0.1.1.0.0.0.0} Index  =  4*state  +  statep.-­‐1.

     if  ((A==LOW)&&(B==HIGH))  state  =  3.      count  =  count  +  QEM[index].        B  =  digitalRead(3).      count  =  count  +  QEM[index].        //determine  state  value      if  ((A==HIGH)&&(B==HIGH))  state  =  0.      if  ((A==LOW)&&(B==LOW))  state  =  2.      if  ((A==LOW)&&(B==LOW))  state  =  2.        //determine  state  value      if  ((A==HIGH)&&(B==HIGH))  state  =  0.BD4x: Array void  Achange()   {      A  =  digitalRead(2).      statep  =  state.      statep  =  state.      if  ((A==HIGH)&&(B==LOW))  state  =  1.      if  ((A==LOW)&&(B==HIGH))  state  =  3.      index  =  4*state  +  statep.        B  =  digitalRead(3).   }   Hands On Arduino: Encoders void  Bchange()   {      A  =  digitalRead(2).      index  =  4*state  +  statep.   }   .      if  ((A==HIGH)&&(B==LOW))  state  =  1.