RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
Encoder.java
1/*
2 * Copyright (C) 2016 John H. Gaby
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Contact: robotics@gabysoft.com
17 */
18
19package robotCore;
20
21import java.nio.ByteBuffer;
22
23import robotCore.Device.Processor;
24import robotCore.Device.RequestType;
25
26//import robot.Robot;
27
36public class Encoder {
37 private Object m_lock = new Object();
38
44
45 public enum EncoderType {
50
55
61
66
71
72 /*
73 * The encoder is quadrature but measures position rather than speed
74 */
75 QuadraturePosition,
76
77 /*
78 * The encoder is attached to the microcontroller via i2c
79 */
80 I2CRotational
81 }
82
83 private Device m_device = null;
84 private int m_encoderNo = -1;
85 private int m_zeroPosition = 0;
86 private int m_i2cAddr = 0;
87 private Processor m_processor;
88 private boolean m_group = false;
89 private EncoderType m_type;
90 private int m_range = 0;
91
92 private Encoder m_encoder = null;
93
94 private void getIntCallback(ByteBuffer buffer, Object object) {
95 // Logger.log("Encoder", 1, "getIntCallback()");
96
97 Encoder encoder = (Encoder) object;
98 int pos = buffer.getInt();
99
100 synchronized (m_lock) {
101 encoder.m_lastPos = pos;
102 }
103 }
104
105 public EncoderType getType() {
106 return m_type;
107 }
108
109 // This function will be called from a different thread
110 void groupCallback(ByteBuffer data, Object object) {
111 Encoder encoder = (Encoder) object;
112 byte pos = data.get();
113
114 if (pos == -128) {
115 // delta is too large, get full value
116 // Logger.log("Encoder", 1, String.format("Encoder %d overflow", encoder.m_encoderNo));
117 m_device.getInt(m_i2cAddr, TwoWire.k_getEncoderPos, (byte) encoder.m_encoderNo,
118 (b, o) -> getIntCallback(b, o), encoder);
119 } else {
120 synchronized (m_lock) {
121 encoder.m_lastPos += pos;
122 }
123 }
124 }
125
126 private void verifyPin(int pin, Device.PinType type) {
127 if (!m_device.isPinValid(m_i2cAddr, pin, type)) {
128 throw new TwoWire.HardwareException(
129 String.format("Encoder: Invalid %s pin: %d", type.toString(), pin));
130 }
131
132 /*
133 * Check if pin is currently in use
134 */
135 if (m_device.checkUsedPin(m_i2cAddr, pin)) {
136 throw new TwoWire.HardwareException(String.format("Encoder: Pin %d is in use", pin));
137 }
138 }
139
140 private void init(EncoderType type, int pin1, int pin2, int i2cAddr, boolean group) {
141 if (pin1 == pin2) {
142 throw new TwoWire.HardwareException(String.format("Encoder: The two pins must be different"));
143 }
144
145 if (type == EncoderType.QuadraturePosition && Device.m_boardSubVersion == 0) {
146 throw new TwoWire.HardwareException("The hardware does not support positional quadrature encoders, update firmware");
147 }
148
149 m_device = Device.getInstance();
150
151 m_processor = m_device.getProcessor(i2cAddr);
152
153 m_i2cAddr = i2cAddr;
154 m_group = group;
155 m_type = type;
156
157 /*
158 * MUSTFIX - Probably need to get range after encoder has been initialized?
159 */
160 if ((type == EncoderType.AnalogRotational) || (type == EncoderType.I2CRotational)) {
161 m_range = m_device.getEncoderRange(m_i2cAddr);
162 }
163
164 /*
165 * For I2C encoders, pin1 is the i2c address. For all others, we must verify pin numbers
166 */
167 if (type != EncoderType.I2CRotational) {
168 verifyPin(pin1, (type == EncoderType.AnalogRotational) ? Device.PinType.AnalogPin : Device.PinType.InterruptPin);
169 m_device.setUsedPin(m_i2cAddr, pin1);
170
171 if (pin2 >= 0) {
172 // m_processor.verifyPin(pin2, false); // type == EncoderType.Analog);
173 verifyPin(pin2, (type == EncoderType.AnalogRotational) ? Device.PinType.AnalogPin : Device.PinType.InputPin);
174 m_device.setUsedPin(m_i2cAddr, pin2);
175 }
176 }
177
178 m_encoderNo = m_processor.getNextEncoderNo();
179
180 m_device.sendCommand(m_i2cAddr, TwoWire.k_configureEncoder, (byte) m_encoderNo, (byte) type.ordinal(),
181 (byte) pin1, (byte) pin2);
182
183 if (group) {
184 m_processor.addGroupRequest(RequestType.EncoderRelativePosition, m_encoderNo, (d, c) -> groupCallback(d, c),
185 this);
186 Device.startGroupRequests();
187 }
188 }
189
190 // To support DummyEncoder
191 public Encoder() {
192 }
193
202 public Encoder(EncoderType type, int pin1, int pin2, int i2cAddr) {
203 init(type, pin1, pin2, i2cAddr, false);
204 }
205
219 public Encoder(EncoderType type, int pin1, int pin2, int i2cAddr, boolean group) {
220 init(type, pin1, pin2, i2cAddr, group);
221 }
222
230 public Encoder(EncoderType type, int pin1, int pin2) {
231 init(type, pin1, pin2, Device.k_mainTwoWireId, false);
232 }
233
246 public Encoder(EncoderType type, int pin1, int pin2, boolean group) {
247 init(type, pin1, pin2, Device.k_mainTwoWireId, group);
248 }
249
257 public int getRange() {
258 return m_range;
259 }
260
261 // ! @cond PRIVATE
262 public int getEncoderNo() {
263 return (m_encoderNo);
264 }
265 // ! @endcond
266
273 public int get() {
274 return getPosition();
275 }
276
277 int m_lastPos = 0;
278
279 private int getRawPosition() {
280 if (m_encoder != null) {
281 return (m_encoder.getRawPosition());
282 }
283
284 if (!m_group) {
285 m_lastPos = m_device.getInt(m_i2cAddr, TwoWire.k_getEncoderPos, (byte) m_encoderNo);
286 }
287
288 synchronized (m_lock) {
289 return (m_lastPos);
290 }
291 }
292
298 public int getPosition() {
299 int pos = getRawPosition() - m_zeroPosition;
300
301 if (m_range != 0) {
302 pos = (int) Gyro.normalize(pos, m_range);
303 }
304
305 return pos;
306 }
307
313 public int getSpeed() {
314 return getSpeedTW();
315 }
316
317 private int getSpeedTW() {
318 if (m_encoder != null) {
319 return (m_encoder.getSpeed());
320 }
321
322 return (m_device.getShort(m_i2cAddr, TwoWire.k_getEncoderSpeed, (byte) m_encoderNo));
323 }
324
328 public void reset() {
329 m_zeroPosition = getRawPosition();
330 }
331
338 public void reset(int position) {
339 m_zeroPosition = getRawPosition() - position;
340 }
341
348 public void setZero(int zero) {
349 m_zeroPosition = zero;
350 }
351
352 public int getZero() {
353 return m_zeroPosition;
354 }
355
360 public void setInverted(boolean invert) {
361 Logger.log("Encoder", 1, String.format("setInverted(%b)", invert));
362 m_device.sendCommand(m_i2cAddr, TwoWire.k_setEncoderInverted, (byte) m_encoderNo, (byte) (invert ? 1 : 0));
363 }
364}
void setZero(int zero)
Definition Encoder.java:348
Encoder(EncoderType type, int pin1, int pin2, int i2cAddr, boolean group)
Definition Encoder.java:219
Encoder(EncoderType type, int pin1, int pin2)
Definition Encoder.java:230
Encoder(EncoderType type, int pin1, int pin2, int i2cAddr)
Definition Encoder.java:202
void setInverted(boolean invert)
Definition Encoder.java:360
void reset(int position)
Definition Encoder.java:338
Encoder(EncoderType type, int pin1, int pin2, boolean group)
Definition Encoder.java:246
The Gyro class measures the orientation of the robot.
Definition Gyro.java:35
static double normalize(double angle, double range)
Definition Gyro.java:104
The Logger class provides a mechanism to log messages.
Definition Logger.java:54
static void log(String tag, int level, String message, boolean noLogToConsole)
Definition Logger.java:161
Specifies the type of encoder.
Definition Encoder.java:45