Motor pause until ready (#108)
* adding command to pause until ready * adding console API * adding ready support for motors * fix time output scale * fixing angle
This commit is contained in:
		
							
								
								
									
										84
									
								
								docs/tests/motors.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								docs/tests/motors.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
```typescript
 | 
			
		||||
let errors: string[] = [];
 | 
			
		||||
let tachoB = 0;
 | 
			
		||||
let tachoC = 0;
 | 
			
		||||
 | 
			
		||||
function assert(name: string, condition: boolean) {
 | 
			
		||||
    if (!condition) {
 | 
			
		||||
        errors.push(name)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertClose(name: string, expected: number, actual: number, tolerance = 5) {
 | 
			
		||||
    const diff = Math.abs(expected - actual);
 | 
			
		||||
    assert(name + ` ${expected}vs${actual}`, diff < tolerance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function state(name: string, motor: motors.SingleMotor, line: number) {
 | 
			
		||||
    brick.print(`${name}: ${motor.speed()}%,${motor.angle()}deg`, 0, 12 * line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function test(name: string, f: () => void, check?: () => void) {
 | 
			
		||||
    motors.stopAllMotors();
 | 
			
		||||
    motors.largeB.clearCount()
 | 
			
		||||
    motors.largeC.clearCount()
 | 
			
		||||
    motors.largeB.setBrake(false)
 | 
			
		||||
    motors.largeC.setBrake(false)
 | 
			
		||||
    loops.pause(500);
 | 
			
		||||
    tachoB = motors.largeB.angle()
 | 
			
		||||
    tachoC = motors.largeC.angle()
 | 
			
		||||
    brick.clearScreen()
 | 
			
		||||
    brick.print(name, 0, 0)
 | 
			
		||||
    state("B", motors.largeB, 1)
 | 
			
		||||
    state("C", motors.largeC, 2)
 | 
			
		||||
    f();
 | 
			
		||||
    loops.pause(3000);
 | 
			
		||||
    motors.largeB.setReversed(false);
 | 
			
		||||
    motors.largeC.setReversed(false);
 | 
			
		||||
    motors.mediumA.setReversed(false);
 | 
			
		||||
    state("B", motors.largeB, 3)
 | 
			
		||||
    state("C", motors.largeC, 4)
 | 
			
		||||
    if (check)
 | 
			
		||||
        check()
 | 
			
		||||
    motors.stopAllMotors();
 | 
			
		||||
    loops.pause(1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
 | 
			
		||||
    test("lgB set speed 10", () => {
 | 
			
		||||
        motors.largeB.setSpeed(10)
 | 
			
		||||
    }, () => assertClose("speedB", 10, motors.largeB.speed()));
 | 
			
		||||
    test("lgB set speed 25 (reversed)", () => {
 | 
			
		||||
        motors.largeB.setReversed(true)
 | 
			
		||||
        motors.largeB.setSpeed(25)
 | 
			
		||||
    }, () => assertClose("speedB", -25, motors.largeB.speed()));
 | 
			
		||||
    test("lgBC set speed 5", () => {
 | 
			
		||||
        motors.largeBC.setSpeed(5)
 | 
			
		||||
    }, () => {
 | 
			
		||||
        assertClose("speedB", 5, motors.largeB.speed());
 | 
			
		||||
        assertClose("speedC", 5, motors.largeC.speed());
 | 
			
		||||
    });
 | 
			
		||||
    test("lgBC steer 50% 2x", () => {
 | 
			
		||||
        motors.largeBC.setBrake(true)
 | 
			
		||||
        motors.largeBC.steer(50, 50, 2, MoveUnit.Rotations)
 | 
			
		||||
    }, () => assertClose("largeB", 720, motors.largeB.angle()));
 | 
			
		||||
    test("lgBC steer 50% 500deg", () => {
 | 
			
		||||
        motors.largeBC.setBrake(true)
 | 
			
		||||
        motors.largeBC.steer(50, 50, 500, MoveUnit.Degrees)
 | 
			
		||||
    }, () => assertClose("largeB", 500, motors.largeB.angle()));
 | 
			
		||||
    test("lgBC steer 50% 2s", () => {
 | 
			
		||||
        motors.largeBC.setBrake(true)
 | 
			
		||||
        motors.largeBC.steer(50, 50, 2000, MoveUnit.MilliSeconds)
 | 
			
		||||
    })
 | 
			
		||||
    test("lgBC tank 50% 720deg", () => {
 | 
			
		||||
        motors.largeBC.setBrake(true)
 | 
			
		||||
        motors.largeBC.tank(50, 50, 720, MoveUnit.Degrees)
 | 
			
		||||
    }, () => assertClose("largeB", 720, motors.largeB.angle()));
 | 
			
		||||
 | 
			
		||||
    brick.clearScreen()
 | 
			
		||||
    brick.print(`${errors.length} errors`, 0, 0)
 | 
			
		||||
    let l = 1;
 | 
			
		||||
    for (const error of errors)
 | 
			
		||||
        brick.print(`error: ${error}`, 0, l++ * 12)
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
@@ -1,66 +0,0 @@
 | 
			
		||||
let errors: string[] = [];
 | 
			
		||||
let tachoB = 0;
 | 
			
		||||
let tachoC = 0;
 | 
			
		||||
 | 
			
		||||
function assert(name: string, condition: boolean) {
 | 
			
		||||
    if (!condition) {
 | 
			
		||||
        errors.push(name)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function assertClose(name: string, expected: number, actual: number, tolerance = 10) {
 | 
			
		||||
    assert(name + ` ${expected}/${actual}`, Math.abs(expected - actual) < tolerance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function test(name: string, f: () => void, check?: () => void) {
 | 
			
		||||
    motors.stopAllMotors();
 | 
			
		||||
    loops.pause(500);
 | 
			
		||||
    tachoB = motors.largeB.tachoCount()
 | 
			
		||||
    tachoC = motors.largeB.tachoCount()
 | 
			
		||||
    brick.clearScreen()
 | 
			
		||||
    brick.print(name, 0, 0)
 | 
			
		||||
    f();
 | 
			
		||||
    loops.pause(3000);
 | 
			
		||||
    motors.stopAllMotors();
 | 
			
		||||
    motors.largeB.setReversed(false);
 | 
			
		||||
    motors.largeC.setReversed(false);
 | 
			
		||||
    motors.mediumA.setReversed(false);
 | 
			
		||||
    loops.pause(1000);
 | 
			
		||||
    if (check)
 | 
			
		||||
        check()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
 | 
			
		||||
    test("lgB set speed 100", () => {
 | 
			
		||||
        motors.largeB.setSpeed(100)
 | 
			
		||||
    });
 | 
			
		||||
    test("lgB set speed (reversed)", () => {
 | 
			
		||||
        motors.largeB.setReversed(true)
 | 
			
		||||
        motors.largeB.setSpeed(100)
 | 
			
		||||
    })
 | 
			
		||||
    test("lgBC set speed 100", () => {
 | 
			
		||||
        motors.largeBC.setSpeed(100)
 | 
			
		||||
    })
 | 
			
		||||
    test("lgBC steer 50% 2x", () => {
 | 
			
		||||
        motors.largeBC.steer(50, 50, 2, MoveUnit.Rotations)
 | 
			
		||||
    }, () => {
 | 
			
		||||
        assertClose("largeB", 720, motors.largeB.tachoCount() - tachoB)
 | 
			
		||||
    });
 | 
			
		||||
    test("lgBC steer 50% 500deg", () => {
 | 
			
		||||
        motors.largeBC.steer(50, 50, 500, MoveUnit.Degrees)
 | 
			
		||||
    }, () => {
 | 
			
		||||
        assertClose("largeB", 500, motors.largeB.tachoCount() - tachoB)
 | 
			
		||||
    });
 | 
			
		||||
    test("lgBC steer 50% 2s", () => {
 | 
			
		||||
        motors.largeBC.steer(50, 50, 2, MoveUnit.Seconds)
 | 
			
		||||
    })
 | 
			
		||||
    test("lgBC tank 50% 2s", () => {
 | 
			
		||||
        motors.largeBC.tank(50, 50, 720, MoveUnit.Degrees)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    brick.clearScreen()
 | 
			
		||||
    brick.print(`${errors.length} errors`, 0, 0)
 | 
			
		||||
    let l = 1;
 | 
			
		||||
    for(const error of errors)
 | 
			
		||||
        brick.print(`error: ${error}`, 0, l++ * 12)
 | 
			
		||||
})
 | 
			
		||||
@@ -123,6 +123,11 @@
 | 
			
		||||
  "String.substr": "Return a substring of the current string.",
 | 
			
		||||
  "String.substr|param|length": "number of characters to extract",
 | 
			
		||||
  "String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
 | 
			
		||||
  "console": "Reading and writing data to the console output.",
 | 
			
		||||
  "console.log": "Write a line of text to the console output.",
 | 
			
		||||
  "console.logValue": "Write a name:value pair as a line of text to the console output.",
 | 
			
		||||
  "console.logValue|param|name": "name of the value stream, eg: \"x\"",
 | 
			
		||||
  "console.logValue|param|value": "to write",
 | 
			
		||||
  "control": "Program controls and events.",
 | 
			
		||||
  "control.AnimationQueue.cancel": "Cancels the current running animation and clears the queue",
 | 
			
		||||
  "control.AnimationQueue.runUntilDone": "Runs 'render' in a loop until it returns false or the 'stop' function is called",
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,9 @@
 | 
			
		||||
  "String.length|block": "length of %VALUE",
 | 
			
		||||
  "String.substr|block": "substring of %this=text|from %start|of length %length",
 | 
			
		||||
  "String|block": "String",
 | 
			
		||||
  "console.logValue|block": "console|log value %name|= %value",
 | 
			
		||||
  "console.log|block": "console|log %text",
 | 
			
		||||
  "console|block": "console",
 | 
			
		||||
  "control.assert|block": "assert %cond|with value %code",
 | 
			
		||||
  "control.deviceSerialNumber|block": "device serial number",
 | 
			
		||||
  "control.millis|block": "millis (ms)",
 | 
			
		||||
@@ -43,6 +46,7 @@
 | 
			
		||||
  "{id:category}Arrays": "Arrays",
 | 
			
		||||
  "{id:category}Boolean": "Boolean",
 | 
			
		||||
  "{id:category}Buffer": "Buffer",
 | 
			
		||||
  "{id:category}Console": "Console",
 | 
			
		||||
  "{id:category}Control": "Control",
 | 
			
		||||
  "{id:category}Helpers": "Helpers",
 | 
			
		||||
  "{id:category}Loops": "Loops",
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,8 @@
 | 
			
		||||
        "control.cpp",
 | 
			
		||||
        "control.ts",
 | 
			
		||||
        "serial.cpp",
 | 
			
		||||
        "serial.ts"
 | 
			
		||||
        "serial.ts",
 | 
			
		||||
        "console.ts"
 | 
			
		||||
    ],
 | 
			
		||||
    "testFiles": [
 | 
			
		||||
        "test.ts"
 | 
			
		||||
 
 | 
			
		||||
@@ -51,10 +51,13 @@
 | 
			
		||||
  "control.raiseEvent": "Announce that an event happened to registered handlers.",
 | 
			
		||||
  "control.raiseEvent|param|src": "ID of the Component that generated the event",
 | 
			
		||||
  "control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
 | 
			
		||||
  "motors.Motor.isReady": "Returns a value indicating if the motor is still running a previous command.",
 | 
			
		||||
  "motors.Motor.move": "Moves the motor by a number of rotations, degress or seconds",
 | 
			
		||||
  "motors.Motor.move|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
 | 
			
		||||
  "motors.Motor.move|param|unit": "the meaning of the value",
 | 
			
		||||
  "motors.Motor.move|param|value": "the move quantity, eg: 2",
 | 
			
		||||
  "motors.Motor.pauseUntilReady": "Pauses the execution until the previous command finished.",
 | 
			
		||||
  "motors.Motor.pauseUntilReady|param|timeOut": "optional maximum pausing time in milliseconds",
 | 
			
		||||
  "motors.Motor.reset": "Resets the motor(s).",
 | 
			
		||||
  "motors.Motor.setBrake": "Sets the automatic brake on or off when the motor is off",
 | 
			
		||||
  "motors.Motor.setBrake|param|brake": "a value indicating if the motor should break when off",
 | 
			
		||||
@@ -62,10 +65,9 @@
 | 
			
		||||
  "motors.Motor.setSpeed": "Sets the speed of the motor.",
 | 
			
		||||
  "motors.Motor.setSpeed|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
 | 
			
		||||
  "motors.Motor.stop": "Stops the motor(s).",
 | 
			
		||||
  "motors.SingleMotor.angle": "Gets motor ration angle.",
 | 
			
		||||
  "motors.SingleMotor.clearCount": "Clears the motor count",
 | 
			
		||||
  "motors.SingleMotor.count": "Gets motor step count.",
 | 
			
		||||
  "motors.SingleMotor.speed": "Gets motor actual speed.",
 | 
			
		||||
  "motors.SingleMotor.tachoCount": "Gets motor tacho count.",
 | 
			
		||||
  "motors.SynchedMotorPair.steer": "Turns the motor and the follower motor by a number of rotations",
 | 
			
		||||
  "motors.SynchedMotorPair.steer|param|speed": "the speed from ``100`` full forward to ``-100`` full backward, eg: 50",
 | 
			
		||||
  "motors.SynchedMotorPair.steer|param|steering": "the ratio of power sent to the follower motor, from ``-100`` to ``100``",
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@
 | 
			
		||||
  "LightsPattern.RedPulse|block": "Pulsing Red",
 | 
			
		||||
  "LightsPattern.Red|block": "Red",
 | 
			
		||||
  "MoveUnit.Degrees|block": "degrees",
 | 
			
		||||
  "MoveUnit.MilliSeconds|block": "milliseconds",
 | 
			
		||||
  "MoveUnit.Rotations|block": "rotations",
 | 
			
		||||
  "MoveUnit.Seconds|block": "seconds",
 | 
			
		||||
  "Output.AB|block": "A+B",
 | 
			
		||||
  "Output.AD|block": "A+D",
 | 
			
		||||
  "Output.ALL|block": "All",
 | 
			
		||||
@@ -44,12 +44,12 @@
 | 
			
		||||
  "control.raiseEvent|block": "raise event|from %src|with value %value",
 | 
			
		||||
  "control|block": "control",
 | 
			
		||||
  "motors.Motor.move|block": "move `icons.motorLarge` %motor|for %value|%unit|at %speed|%",
 | 
			
		||||
  "motors.Motor.pauseUntilReady|block": "%motor|pause until ready",
 | 
			
		||||
  "motors.Motor.setBrake|block": "set `icons.motorLarge` %motor|brake %brake",
 | 
			
		||||
  "motors.Motor.setReversed|block": "set `icons.motorLarge` %motor|reversed %reversed",
 | 
			
		||||
  "motors.Motor.setSpeed|block": "set speed of `icons.motorLarge` %motor|to %speed|%",
 | 
			
		||||
  "motors.SingleMotor.count|block": "`icons.motorLarge` %motor|count",
 | 
			
		||||
  "motors.SingleMotor.angle|block": "`icons.motorLarge` %motor|angle",
 | 
			
		||||
  "motors.SingleMotor.speed|block": "`icons.motorLarge` %motor|speed",
 | 
			
		||||
  "motors.SingleMotor.tachoCount|block": "`icons.motorLarge` %motor|tacho count",
 | 
			
		||||
  "motors.SynchedMotorPair.steer|block": "steer %chassis|%steering|%|at speed %speed|%|by %value|%unit",
 | 
			
		||||
  "motors.SynchedMotorPair.tank|block": "tank %chassis|left %speedLeft|%|right %speedRight|%|by %value|%unit",
 | 
			
		||||
  "motors.largeAB|block": "large A+B",
 | 
			
		||||
 
 | 
			
		||||
@@ -30,8 +30,8 @@ enum MoveUnit {
 | 
			
		||||
    Rotations,
 | 
			
		||||
    //% block="degrees"
 | 
			
		||||
    Degrees,
 | 
			
		||||
    //% block="seconds"
 | 
			
		||||
    Seconds
 | 
			
		||||
    //% block="milliseconds"
 | 
			
		||||
    MilliSeconds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace motors {
 | 
			
		||||
@@ -65,9 +65,9 @@ namespace motors {
 | 
			
		||||
        pwmMM.write(buf)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function readPWM(buf: Buffer): void {
 | 
			
		||||
    function readPWM(buf: Buffer): number {
 | 
			
		||||
        init()
 | 
			
		||||
        pwmMM.read(buf);
 | 
			
		||||
        return pwmMM.read(buf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function mkCmd(out: Output, cmd: number, addSize: number) {
 | 
			
		||||
@@ -220,6 +220,27 @@ namespace motors {
 | 
			
		||||
 | 
			
		||||
            this._move(useSteps, stepsOrTime, speed);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Returns a value indicating if the motor is still running a previous command.
 | 
			
		||||
         */
 | 
			
		||||
        //%
 | 
			
		||||
        isReady(): boolean {
 | 
			
		||||
            this.init();
 | 
			
		||||
            const r = readPWM(mkCmd(this._port, DAL.opOutputTest, 0))
 | 
			
		||||
            // 0 = ready, 1 = busy
 | 
			
		||||
            return r == 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Pauses the execution until the previous command finished.
 | 
			
		||||
         * @param timeOut optional maximum pausing time in milliseconds
 | 
			
		||||
         */
 | 
			
		||||
        //% blockId=motorPauseUntilRead block="%motor|pause until ready"
 | 
			
		||||
        //% group="Motion"
 | 
			
		||||
        pauseUntilReady(timeOut: number = -1) {
 | 
			
		||||
            pauseUntil(() => this.isReady(), timeOut);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //% fixedInstances
 | 
			
		||||
@@ -248,7 +269,7 @@ namespace motors {
 | 
			
		||||
            b.setNumber(NumberFormat.Int8LE, 2, speed)
 | 
			
		||||
            writePWM(b)
 | 
			
		||||
            if (speed) {
 | 
			
		||||
                writePWM(mkCmd(this._port, DAL.opOutputStart, 0))    
 | 
			
		||||
                writePWM(mkCmd(this._port, DAL.opOutputStart, 0))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -276,27 +297,15 @@ namespace motors {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Gets motor step count.
 | 
			
		||||
         * Gets motor ration angle.
 | 
			
		||||
         * @param motor the port which connects to the motor
 | 
			
		||||
         */
 | 
			
		||||
        //% blockId=motorCount block="`icons.motorLarge` %motor|count"
 | 
			
		||||
        //% weight=71 blockGap=8
 | 
			
		||||
        //% group="Sensors"
 | 
			
		||||
        count(): number {
 | 
			
		||||
            this.init();
 | 
			
		||||
            return getMotorData(this._port).count;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Gets motor tacho count.
 | 
			
		||||
         * @param motor the port which connects to the motor
 | 
			
		||||
         */
 | 
			
		||||
        //% blockId=motorTachoCount block="`icons.motorLarge` %motor|tacho count"
 | 
			
		||||
        //% blockId=motorTachoCount block="`icons.motorLarge` %motor|angle"
 | 
			
		||||
        //% weight=70
 | 
			
		||||
        //% group="Sensors"
 | 
			
		||||
        tachoCount(): number {
 | 
			
		||||
        angle(): number {
 | 
			
		||||
            this.init();
 | 
			
		||||
            return getMotorData(this._port).tachoCount;
 | 
			
		||||
            return getMotorData(this._port).count;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user