package lejos.nxt.remote; import java.io.*; import lejos.robotics.TachoMotor; /* * WARNING: THIS CLASS IS SHARED BETWEEN THE classes AND pccomms PROJECTS. * DO NOT EDIT THE VERSION IN pccomms AS IT WILL BE OVERWRITTEN WHEN THE PROJECT IS BUILT. */ /** * Motor class. Contains three instances of Motor. * Usage: Motor.A.forward(500); * * @author <a href="mailto:bbagnall@mts.net">Brian Bagnall</a> * */ public class RemoteMotor implements TachoMotor, NXTProtocol { private int id; private byte power; private int mode; private int regulationMode; public byte turnRatio; private int runState; private boolean _rotating = false; private NXTCommand nxtCommand; public RemoteMotor(NXTCommand nxtCommand, int id) { this.id = id; this.power = 80; // 80% power by default. Is this speed too? this.mode = BRAKE + REGULATED; // Brake mode and regulation default this.regulationMode = REGULATION_MODE_MOTOR_SPEED; this.turnRatio = 0; // 0 = even power/speed distro between motors this.runState = MOTOR_RUN_STATE_IDLE; this.nxtCommand = nxtCommand; } /** * Get the ID of the motor. One of 'A', 'B' or 'C'. */ public final char getId() { char port = 'A'; switch(id) { case 0: port='A'; break; case 1: port='B'; break; case 2: port='C'; break; } return port; } public void forward() { this.runState = MOTOR_RUN_STATE_RUNNING; try { nxtCommand.setOutputState(id, power, this.mode + MOTORON, regulationMode, turnRatio, runState, 0); } catch (IOException ioe) { System.out.println(ioe.getMessage()); //return -1; } } public void backward() { this.runState = MOTOR_RUN_STATE_RUNNING; try { nxtCommand.setOutputState(id, (byte)-power, this.mode + MOTORON, regulationMode, turnRatio, runState, 0); } catch (IOException ioe) { System.out.println(ioe.getMessage()); //return -1; } } public void setSpeed(int speed) { if(speed > 900|speed < 0) return; speed = (speed * 100) / 900; this.power = (byte)speed; } /** * Sets the power of the motor * @param power the power (-100 to +100) */ public void setPower(int power) { this.power = (byte)power; } public int getSpeed() { return (this.power * 900) / 100; } /** * Return the power that the motor is set to * @return the power (-100 to +100) */ public int getPower() { return power; } public int getTachoCount() { try { OutputState state = nxtCommand.getOutputState(id); return state.rotationCount; } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } } /** * Returns the rotation count for the motor. The rotation count is something * like the trip odometer on your car. This count is reset each time a new function * is called in Pilot. * @deprecated * @return rotation count. */ public int getRotationCount() { // !! Consider making this protected to keep off limits from users. return getTachoCount(); } /** * Block Encoder Count is the count used to synchronize motors * with one another. * NOTE: If you are using leJOS NXJ firmware this will * always return 0 because this variable is not used in * in leJOS NXJ firmware. Use getRotationCount() instead. * @deprecated * @return Block Encoder count. */ public int getBlockTacho() { try { OutputState state = nxtCommand.getOutputState(id); return state.blockTachoCount; } catch (IOException ioe) { System.out.println(ioe.getMessage()); return 0; } } public void rotate(int count, boolean returnNow) { this.runState = MOTOR_RUN_STATE_RUNNING; // ** Really this can accept a ULONG value for count. Too lazy to properly convert right now: byte status = 0; // !! This used to say power > 0, apparently not working. //if(power > 0) try { if(count > 0) nxtCommand.setOutputState(id, power, this.mode + MOTORON, regulationMode, turnRatio, runState, count); // Note using tachoLimit with Lego FW else nxtCommand.setOutputState(id, (byte)-power, this.mode + MOTORON, regulationMode, turnRatio, runState, Math.abs(count)); // Note using tachoLimit with Lego FW } catch (IOException ioe) { System.out.println(ioe.getMessage()); } if(returnNow) { //return status; } else { // Check if mode is moving until done while(isMoving()) {Thread.yield();} //return status; } } public boolean isMoving() { try { OutputState o = nxtCommand.getOutputState(id); // return ((MOTORON & o.mode) == MOTORON); return o.runState != MOTOR_RUN_STATE_IDLE; // Peter's bug fix } catch (IOException ioe) { System.out.println(ioe.getMessage()); return false; } } /** * CURRENTLY NOT IMPLEMENTED! Use isMoving() for now. *returns true when motor is rotating toward a specified angle */ public boolean isRotating() { // Should probably use Tacho Limit value from // get output state return _rotating; } public void rotate(int count) { rotate(count, false); } /** * This method determines if and how the motor will be regulated. * REGULATION_MODE_IDLE turns off regulation * REGULATION_MODE_MOTOR_SPEED regulates the speed (I think) * REGULATION_MODE_MOTOR_SYNC synchronizes this and any other motor with SYNC enabled. * @param mode See NXTProtocol for enumerations: REGULATION_MODE_MOTOR_SYNC, * REGULATION_MODE_MOTOR_SPEED, REGULATION_MODE_IDLE */ public void setRegulationMode(int mode) { // !! Consider removing this method! No need, confusing, makes other forward methods unreliable. this.regulationMode = mode; } public void rotateTo(int limitAngle) { rotateTo(limitAngle, false); } public void rotateTo(int limitAngle, boolean returnNow) { // !! Probably inaccuracy can creep into this if // rotateTo is called while motor moving. int tachometer = this.getTachoCount(); rotate(limitAngle - tachometer, returnNow); } public void resetTachoCount() { try { nxtCommand.resetMotorPosition(this.id, false); } catch (IOException ioe) { System.out.println(ioe.getMessage()); //return -1; } } /** * Resets the block tachometer. * NOTE: If you are using leJOS NXJ firmware this will not do anything * because BlockTacho is not used in the leJOS NXJ firmware. * Use resetRotationCounter() instead. * @deprecated * @return Error value. 0 means success. See lejos.pc.comm.ErrorMessages for details. */ public int resetBlockTacho() { // Note: This method can also reset tachometer relative to last position. // I didn't include this because it seems unintuitive, but the // functionality could be added, maybe with a resetTachoRelative() method. // Just change false to true in statement below for relative reset. // @param relative TRUE: position relative to last movement, FALSE: absolute position try { nxtCommand.resetMotorPosition(this.id, true); } catch (IOException ioe) { System.out.println(ioe.getMessage()); return -1; } return 0; } public void stop() { this.runState = MOTOR_RUN_STATE_RUNNING; //this.regulationMode = REGULATION_MODE_MOTOR_SPEED; try { // NOTE: Setting power to 0 seems to make it lock motor, not float it. nxtCommand.setOutputState(id, (byte)0, BRAKE + MOTORON + REGULATED, regulationMode, turnRatio, runState, 0); } catch (IOException ioe) { System.out.println(ioe.getMessage()); //return -1; } } public void flt() { this.runState = MOTOR_RUN_STATE_IDLE; //this.regulationMode = REGULATION_MODE_MOTOR_SPEED; this.mode = MOTOR_RUN_STATE_IDLE; try { nxtCommand.setOutputState(id, (byte)0, 0x00, regulationMode, turnRatio, runState, 0); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } public void regulateSpeed(boolean yes) { // TODO Currently a dummy for remote motors. } public void smoothAcceleration(boolean yes) { // TODO Currently a dummy for remote motors. } public int getRotationSpeed() { // TODO Currently dummy for remote motors - returns the speed that has been set. return getSpeed(); } }