Pololu3piPlus32U4 library
Pololu3piPlus32U4Encoders.cpp
1 // Copyright (C) Pololu Corporation. See www.pololu.com for details.
2 
4 #include <FastGPIO.h>
5 #include <avr/interrupt.h>
6 #include <Arduino.h>
7 
8 #define LEFT_XOR 8
9 #define LEFT_B IO_E2
10 #define RIGHT_XOR 7
11 #define RIGHT_B 23
12 
13 namespace Pololu3piPlus32U4
14 {
15 
16 static volatile bool lastLeftA;
17 static volatile bool lastLeftB;
18 static volatile bool lastRightA;
19 static volatile bool lastRightB;
20 
21 static volatile bool errorLeft;
22 static volatile bool errorRight;
23 
24 // These count variables are uint16_t instead of int16_t because
25 // signed integer overflow is undefined behavior in C++.
26 static volatile uint16_t countLeft;
27 static volatile uint16_t countRight;
28 
29 ISR(PCINT0_vect)
30 {
31  bool newLeftB = FastGPIO::Pin<LEFT_B>::isInputHigh();
32  bool newLeftA = FastGPIO::Pin<LEFT_XOR>::isInputHigh() ^ newLeftB;
33 
34  countLeft += (newLeftA ^ lastLeftB) - (lastLeftA ^ newLeftB);
35 
36  if((lastLeftA ^ newLeftA) & (lastLeftB ^ newLeftB))
37  {
38  errorLeft = true;
39  }
40 
41  lastLeftA = newLeftA;
42  lastLeftB = newLeftB;
43 }
44 
45 static void rightISR()
46 {
47  bool newRightB = FastGPIO::Pin<RIGHT_B>::isInputHigh();
48  bool newRightA = FastGPIO::Pin<RIGHT_XOR>::isInputHigh() ^ newRightB;
49 
50  countRight += (newRightA ^ lastRightB) - (lastRightA ^ newRightB);
51 
52  if((lastRightA ^ newRightA) & (lastRightB ^ newRightB))
53  {
54  errorRight = true;
55  }
56 
57  lastRightA = newRightA;
58  lastRightB = newRightB;
59 }
60 
61 void Encoders::init2()
62 {
63  // Set the pins as pulled-up inputs.
64  FastGPIO::Pin<LEFT_XOR>::setInputPulledUp();
65  FastGPIO::Pin<LEFT_B>::setInputPulledUp();
66  FastGPIO::Pin<RIGHT_XOR>::setInputPulledUp();
67  FastGPIO::Pin<RIGHT_B>::setInputPulledUp();
68 
69  // Enable pin-change interrupt on PB4 for left encoder, and disable other
70  // pin-change interrupts.
71  PCICR = (1 << PCIE0);
72  PCMSK0 = (1 << PCINT4);
73  PCIFR = (1 << PCIF0); // Clear its interrupt flag by writing a 1.
74 
75  // Enable interrupt on PE6 for the right encoder. We use attachInterrupt
76  // instead of defining ISR(INT6_vect) ourselves so that this class will be
77  // compatible with other code that uses attachInterrupt.
78  attachInterrupt(4, rightISR, CHANGE);
79 
80  // Initialize the variables. It's good to do this after enabling the
81  // interrupts in case the interrupts fired by accident as we were enabling
82  // them.
83  lastLeftB = FastGPIO::Pin<LEFT_B>::isInputHigh();
84  lastLeftA = FastGPIO::Pin<LEFT_XOR>::isInputHigh() ^ lastLeftB;
85  countLeft = 0;
86  errorLeft = 0;
87 
88  lastRightB = FastGPIO::Pin<RIGHT_B>::isInputHigh();
89  lastRightA = FastGPIO::Pin<RIGHT_XOR>::isInputHigh() ^ lastRightB;
90  countRight = 0;
91  errorRight = 0;
92 }
93 
94 bool Encoders::flip;
95 
97 {
98  flip = f;
99 }
100 
102 {
103  init();
104 
105  cli();
106  int16_t counts = countLeft;
107  sei();
108  return flip ? -counts : counts;
109 }
110 
112 {
113  init();
114 
115  cli();
116  int16_t counts = countRight;
117  sei();
118  return flip ? -counts : counts;
119 }
120 
122 {
123  init();
124 
125  cli();
126  int16_t counts = countLeft;
127  countLeft = 0;
128  sei();
129  return flip ? -counts : counts;
130 }
131 
133 {
134  init();
135 
136  cli();
137  int16_t counts = countRight;
138  countRight = 0;
139  sei();
140  return flip ? -counts : counts;
141 }
142 
144 {
145  init();
146 
147  bool error = errorLeft;
148  errorLeft = 0;
149  return error;
150 }
151 
153 {
154  init();
155 
156  bool error = errorRight;
157  errorRight = 0;
158  return error;
159 }
160 
161 }
static void flipEncoders(bool flip)
Flips the direction of the encoders.
static bool checkErrorRight()
Returns true if an error was detected on the right-side encoder.
static int16_t getCountsRight()
Returns the number of counts that have been detected from the right-side encoder.
static bool checkErrorLeft()
Returns true if an error was detected on the left-side encoder.
static int16_t getCountsAndResetRight()
Returns the number of counts that have been detected from the left-side encoder and clears the counts...
static int16_t getCountsAndResetLeft()
Returns the number of counts that have been detected from the left-side encoder and clears the counts...
static int16_t getCountsLeft()
Returns the number of counts that have been detected from the left-side encoder.
static void init()
Initializes the encoders (called automatically).
Top-level namespace for the Pololu3piPlus32U4 library.