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:
parent
04275ee35c
commit
f1445c6e89
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user