RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
SmartMotor.java
1package robotCore;
2
3import java.nio.ByteBuffer;
4import java.nio.ByteOrder;
5import java.util.ArrayList;
6
7import robotCore.Encoder.EncoderType;
8
9// import javax.management.RuntimeErrorException;
10
11// import robotCore.TwoWire.HardwareException;
12
24public class SmartMotor extends MotorBase {
44
64
65 private static int k_maxSpeed = 10000; // Maximum allowable speed
66
67 private class Processor {
68 private int m_addr;
69 private int m_nextMotor = 0;
70 private SmartMotor[] m_motors = null;
71 // private long m_validPins = 0;
72 // private long m_validPWMPins = 0;
73 // private int m_usedPins = 0;
74 private int m_maxMotors = 0;
75
76 Processor(int addr) {
77 m_addr = addr;
78 }
79
80 void periodic() {
81 // Logger.log("SmartMotor", 1, "periodic()");
82 if (Device.m_boardVersion == 4) {
83 // Does not support setting multiple values
84 for (SmartMotor motor : m_motors) {
85 if ((motor != null) && motor.m_changed) {
86 // Logger.log("SmartMotor", 1, String.format("setMotor %d=%d", motor.m_motorNo, motor.m_currentValue));
87 m_device.sendCommand(m_i2cAddr, TwoWire.k_setMotor, (byte) motor.m_motorNo, (short) motor.m_currentValue);
88 motor.m_changed = false;
89 }
90 }
91 }
92 else {
93 int count = 0;
94 for (SmartMotor motor : m_motors) {
95 if ((motor != null) && motor.m_changed) {
96 if (Math.abs(motor.m_currentValue) < 32000) {
97 count++;
98 }
99 else {
100 // Must send a 32 bit value
101 if (Device.m_boardSubVersion == 0) {
102 throw new TwoWire.HardwareException("Operation not supported by hardware: update firmware");
103 }
104 m_device.sendCommand(m_i2cAddr, TwoWire.k_setMotor32, (byte) motor.m_motorNo, motor.m_currentValue);
105 }
106 }
107 }
108
109 if (count != 0) {
110 byte[] data = new byte[(3 * count) + 1];
111 ByteBuffer buffer = ByteBuffer.wrap(data, 0, data.length);
112 buffer.order(ByteOrder.LITTLE_ENDIAN);
113
114 buffer.put((byte) count);
115 for (SmartMotor motor : m_motors) {
116 if ((motor != null) && motor.m_changed) {
117 // Logger.log("SmartMotor", 1, String.format("periodic: %d", motor.m_currentValue));
118 buffer.put((byte) motor.m_motorNo);
119 buffer.putShort((short) motor.m_currentValue);
120
121 motor.m_changed = false;
122 }
123 }
124
125 // Logger.log("SmartMotor", 1, String.format("Combine: count=%d, len=%d", count, data.length));
126
127 m_device.sendCommand(m_addr, TwoWire.k_setMultipleMotors, data);
128 }
129 }
130 }
131
132 private int getMaxMotors() {
133 if (m_maxMotors == 0) {
134 m_maxMotors = m_device.getByte(m_addr, TwoWire.k_getMaxMotors);
135 }
136
137 // System.out.println(String.format("maxMotors = %d", m_maxMotors));
138
139 return (m_maxMotors);
140 }
141
142 private void verifyPin(int pin, boolean pwm) {
143 // long validPins = pwm ? getValidPWMPins() : getValidOutputPins();
144
145 // Logger.log("SmartMotor", 1, String.format("p=%d,v=%x,b=%x", pin, validPins, 1L << pin));
146
147 // /*
148 // * Check if pin is valid for this processor
149 // */
150 // if ((pin < 0) || (pin >= 64) || (((1L << pin) & validPins) == 0)) {
151 // throw new TwoWire.HardwareException(
152 // String.format("SmartMotor: Invalid%s pin: %d", pwm ? " PWM" : "", pin));
153 // }
154 if (!m_device.isPinValid(m_addr, pin, pwm ? Device.PinType.PWMPin : Device.PinType.OutputPin)) {
155 throw new TwoWire.HardwareException(
156 String.format("SmartMotor: Invalid %s pin: %d", pwm ? "PWM" : "DIR", pin));
157 }
158
159 /*
160 * Check if pin is currently in use
161 */
162 if (m_device.checkUsedPin(m_addr, pin)) {
163 throw new TwoWire.HardwareException(String.format("SmartMotor: Pin %d is in use", pin));
164 }
165 }
166 }
167
168 static ArrayList<Processor> m_processors = new ArrayList<Processor>();
169
170 static void periodic() {
171 for (Processor processor : m_processors) {
172 processor.periodic();
173 }
174 }
175
176 Processor getProcessor(int addr) {
177 Processor processor;
178
179 for (int i = 0; i < m_processors.size(); i++) {
180 processor = m_processors.get(i);
181
182 if (processor.m_addr == addr) {
183 return (processor);
184 }
185 }
186
187 processor = new Processor(addr);
188 m_processors.add(processor);
189
190 return (processor);
191 }
192
193 private Processor m_processor;
194 private Device m_device = null;
195 // private ArduinoConnection m_arduino = null;
196// private SmartMotorType m_type = SmartMotorType.Unknown;
197 private SmartMotorMode m_mode = SmartMotorMode.Power;
198 private int m_motorNo;
199 private int m_currentValue;
200 private int m_i2cAddr = 0;
201 private double m_maxSpeed = 0;
202 private boolean m_changed = false;
203
204 private Encoder m_encoder = null;
205
206 private void init(SmartMotorType type, int pwmPin, int dirPin, int min, int zero, int max, int i2cAddr) {
207 // if (RobotBase.TW)
208 // {
209 initTW(type, pwmPin, dirPin, min, zero, max, i2cAddr);
210 // }
211 // else
212 // {
213 // initArduino(type, pwmPin, dirPin, min, zero, max);
214 // }
215 }
216
217 private void initTW(SmartMotorType type, int pwmPin, int dirPin, int min, int zero, int max, int i2cAddr) {
218 if (pwmPin == dirPin) {
219 throw new TwoWire.HardwareException(String.format("SmartMotor: The pwmPin and dirPin must be different"));
220 }
221
222 m_device = Device.getInstance();
223 m_processor = getProcessor(i2cAddr);
224 int maxMotors = m_processor.getMaxMotors();
225
226 // System.out.println(String.format("SmartMotor init: addr = %d", i2cAddr));
227
228 m_processor.verifyPin(pwmPin, true);
229 if (dirPin != 0) {
230 m_processor.verifyPin(dirPin, false);
231 }
232
233 if (((type != SmartMotorType.PWM) && (type != SmartMotorType.Servo))
234 || (m_processor.m_nextMotor >= maxMotors)) {
235 throw new TwoWire.HardwareException("Invalid motor param");
236 }
237
238 if (m_processor.m_motors == null) {
239 m_processor.m_motors = new SmartMotor[maxMotors];
240 }
241
242// m_type = type;
243 m_motorNo = m_processor.m_nextMotor++;
244 m_processor.m_motors[m_motorNo] = this;
245 m_i2cAddr = i2cAddr;
246
247 m_device.setUsedPin(m_i2cAddr, pwmPin);
248
249 if (dirPin != 0) {
250 m_device.setUsedPin(m_i2cAddr, dirPin);
251 }
252
253 switch (type) {
254 case PWM:
255 // SendCommand(String.format("m%dcp %d %d", m_motorNo, pwmPin, dirPin));
256 m_device.sendCommand(m_i2cAddr, TwoWire.k_configureMotor, (byte) m_motorNo,
257 (byte) SmartMotorType.PWM.ordinal(), (byte) pwmPin, (byte) dirPin);
258 break;
259
260 // case Servo:
261 // sendCommand(String.format("m%dcs %d %d %d %d", m_motorNo, pwmPin, min, zero,
262 // max));
263 // break;
264
265 default:
266 break;
267 }
268 }
269
279 public SmartMotor(SmartMotorType type, int pwmPin, int dirPin) {
280 init(type, pwmPin, dirPin, 1000, 1500, 2000, Device.k_mainTwoWireId);
281 }
282
283 // Used for creating DummyMotor
284 public SmartMotor() {
285
286 }
287
299 public SmartMotor(SmartMotorType type, int pwmPin, int dirPin, int i2cAddr) {
300 init(type, pwmPin, dirPin, 1000, 1500, 2000, i2cAddr);
301 }
302
311 public SmartMotor(int pin, int min, int zero, int max) {
312 init(SmartMotorType.Servo, pin, 0, min, zero, max, Device.k_mainTwoWireId);
313 }
314
325 public SmartMotor(int pin, int min, int zero, int max, int i2cAddr) {
326 init(SmartMotorType.Servo, pin, 0, min, zero, max, i2cAddr);
327 }
328
335 public void setMaxSpeed(double maxSpeed) {
336 m_maxSpeed = maxSpeed;
337 }
338
349 public void set(double value) {
350 int send = 0;
351
352 switch (m_mode) {
353 case Power:
354 if (value > 1.0) {
355 value = 1.0;
356 } else if (value < -1.0) {
357 value = -1.0;
358 }
359
360 send = (int) (value * 1000);
361 break;
362
363 case Speed:
364 if (m_encoder == null) {
365 throw new TwoWire.HardwareException("Setting Speed with no encoder specified");
366 }
367 if (m_maxSpeed != 0) {
368 value *= m_maxSpeed;
369 }
370 // Since we are sending a 16 bit value we must make sure that the speed is not too large
371 send = (int) ((value > k_maxSpeed) ? k_maxSpeed * Math.signum(value) : value);
372 break;
373
374 case Position:
375 if (m_encoder == null) {
376 throw new TwoWire.HardwareException("Setting Position with no encoder specified");
377 }
378 if (m_encoder.getType() == EncoderType.AnalogRotational) {
379 value = Gyro.normalize(value + m_encoder.getZero(), m_encoder.getRange());
380 }
381 else {
382 value += m_encoder.getZero();
383 }
384 send = (int) (value * 10); // TODO - really should get rid of this x10
385 break;
386
387 default:
388 Logger.log("SmartMotor", 3, "Invalid motor type: " + m_mode);
389 return;
390 }
391
392 if (send != m_currentValue) {
393 // Logger.log("SmartMotor", 1, String.format("setPower: %d", send));
394 m_currentValue = send;
395 m_changed = true;
396 }
397 }
398
404 public void setFeedbackDevice(Encoder encoder) {
405 m_encoder = encoder;
406
407 // SendCommand(String.format("m%dd %d", m_motorNo, encoder.getEncoderNo()));
408 m_device.sendCommand(m_i2cAddr, TwoWire.k_setFeedbackDevice, (byte) m_motorNo, (byte) encoder.getEncoderNo());
409 }
410
416 return (m_encoder);
417 }
418
423 public void setControlMode(SmartMotorMode mode) {
424 if (mode != m_mode) {
425 m_mode = mode;
426 m_currentValue = 10000;
427 // SendCommand(String.format("m%dm %d", m_motorNo, mode.ordinal()));
428 // Logger.log("SmartMotor", 1, String.format("m_mode = %d", m_mode.ordinal()));
429 m_device.sendCommand(m_i2cAddr, TwoWire.k_setMotorMode, (byte) m_motorNo, (byte) m_mode.ordinal());
430 }
431 }
432
437 public void setFTerm(double f) {
438 // FloatParams params = new FloatParams(f);
439
440 // SendCommand(String.format("m%df %d %d", m_motorNo, params.value,
441 // params.divisor));
442 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDFTerm, (byte) m_motorNo, (float) f);
443 }
444
449 public void setITerm(double i) {
450 // FloatParams params = new FloatParams(i);
451
452 // SendCommand(String.format("m%di %d %d", m_motorNo, params.value,
453 // params.divisor));
454 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDITerm, (byte) m_motorNo, (float) i);
455 }
456
461 public void setPTerm(double p) {
462 // FloatParams params = new FloatParams(p);
463
464 // SendCommand(String.format("m%dp %d %d", m_motorNo, params.value,
465 // params.divisor));
466 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDPTerm, (byte) m_motorNo, (float) p);
467 }
468
474 public void setIZone(double z) {
475 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDIZone, (byte) m_motorNo, (float) z);
476 }
477
482 public void setInverted(boolean invert) {
483 m_device.sendCommand(m_i2cAddr, TwoWire.k_setMotorInverted, (byte) m_motorNo, (byte) (invert ? 1 : 0));
484 }
485
490 public void setDTerm(double d) {
491 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDDTerm, (byte) m_motorNo, (float) d);
492 }
493
494 // /**
495 // *
496 // * @param wrap - When using position control this specifies that the position
497 // * wraps modulo wrap
498 // */
499 // public void setWrap(double wrap) {
500 // m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDWrap, (byte) m_motorNo,
501 // (float) wrap);
502 // }
503
508 public void setMinPower(double minPower) {
509 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDMinPower, (byte) m_motorNo, (float) minPower);
510 }
511
518 public void setDeadZone(double deadZone) {
519 m_device.sendCommand(m_i2cAddr, TwoWire.k_setPIDDeadZone, (byte) m_motorNo, (float) deadZone);
520 }
521}
The Encoder interface is implemented by classes which track an relative position.
Definition Encoder.java:36
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
Smart motor controller class.
void setFTerm(double f)
void setControlMode(SmartMotorMode mode)
void setInverted(boolean invert)
void setIZone(double z)
void setITerm(double i)
void setFeedbackDevice(Encoder encoder)
SmartMotor(SmartMotorType type, int pwmPin, int dirPin, int i2cAddr)
SmartMotor(int pin, int min, int zero, int max, int i2cAddr)
Encoder getFeedbackDevice()
void setPTerm(double p)
void setDTerm(double d)
SmartMotor(SmartMotorType type, int pwmPin, int dirPin)
void setMaxSpeed(double maxSpeed)
SmartMotor(int pin, int min, int zero, int max)
void setMinPower(double minPower)
void setDeadZone(double deadZone)
Specifies the type of encoder.
Definition Encoder.java:45
Specifies the type of control.
Specifies the type of motor.