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:
Peli de Halleux 2017-12-18 14:13:38 -08:00 committed by GitHub
parent 04275ee35c
commit f1445c6e89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 132 additions and 93 deletions

84
docs/tests/motors.md Normal file
View 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)
})
```

View File

@ -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)
})

View File

@ -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",

View File

@ -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",

View File

@ -17,7 +17,8 @@
"control.cpp",
"control.ts",
"serial.cpp",
"serial.ts"
"serial.ts",
"console.ts"
],
"testFiles": [
"test.ts"

View File

@ -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``",

View File

@ -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",

View File

@ -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;
}
/**