From 16a025f3a051edbc6810721dbd5b6272f5ad7694 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 30 Oct 2017 21:29:18 -0700 Subject: [PATCH 1/2] simplified motor API --- libs/core/_locales/core-jsdoc-strings.json | 9 ++- libs/core/_locales/core-strings.json | 9 +-- libs/core/output.ts | 73 ++++++++++++++-------- libs/ev3/ns.ts | 8 +-- 4 files changed, 63 insertions(+), 36 deletions(-) diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index 846a4582..1182a9f9 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -42,14 +42,17 @@ "control.raiseEvent|param|value": "Component specific code indicating the cause of the event.", "motors.Motor.clearCount": "Clears the motor count", "motors.Motor.count": "Gets motor step count.", - "motors.Motor.on": "Power on or off the motor.", + "motors.Motor.move": "Moves the motor by a number of degrees", + "motors.Motor.move|param|angle": "the degrees to rotate, eg: 360", + "motors.Motor.move|param|power": "the power from ``100`` full forward to ``-100`` full backward, eg: 50", + "motors.Motor.power": "Sets the motor power level from ``-100`` to ``100``.", + "motors.Motor.power|param|power": "the power from ``100`` full forward to ``-100`` full backward, eg: 50", "motors.Motor.reset": "Resets the motor.", "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", - "motors.Motor.setPower": "Sets the motor power level from ``-100`` to ``100``.", - "motors.Motor.setPower|param|power": "the desired speed to use. eg: 50", "motors.Motor.setReversed": "Reverses the motor polarity", "motors.Motor.speed": "Gets motor actual speed.", + "motors.Motor.stop": "Stops the motor", "motors.Motor.tachoCount": "Gets motor tacho count.", "motors.stopAllMotors": "Stops all motors", "output.createBuffer": "Create a new zero-initialized buffer.", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index c43033cd..1a61d9b9 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -46,11 +46,12 @@ "control.raiseEvent|block": "raise event|from %src|with value %value", "control|block": "control", "motors.Motor.count|block": "%motor|count", - "motors.Motor.on|block": "%motor|%onOrOff", - "motors.Motor.setBrake|block": "%motor|set brake %brake", - "motors.Motor.setPower|block": "%motor|set power to %speed", - "motors.Motor.setReversed|block": "%motor|set reversed %reversed", + "motors.Motor.move|block": "move %motor|by %angle|degrees at %power|%", + "motors.Motor.power|block": "power %motor|to %power|%", + "motors.Motor.setBrake|block": "set %motor|brake %brake", + "motors.Motor.setReversed|block": "set %motor|reversed %reversed", "motors.Motor.speed|block": "%motor|speed", + "motors.Motor.stop|block": "stop %motor", "motors.Motor.tachoCount|block": "%motor|tacho count", "motors.largeMotorA|block": "large motor A", "motors.largeMotorB|block": "large motor B", diff --git a/libs/core/output.ts b/libs/core/output.ts index 3454768c..f3c68e5a 100644 --- a/libs/core/output.ts +++ b/libs/core/output.ts @@ -87,43 +87,66 @@ namespace motors { } /** - * Power on or off the motor. - * @param motor the motor to turn on - * @param power the motor power level from ``-100`` to ``100``, eg: 50 + * Sets the motor power level from ``-100`` to ``100``. + * @param motor the output connection that the motor is connected to + * @param power the power from ``100`` full forward to ``-100`` full backward, eg: 50 */ - //% blockId=outputMotorOn block="%motor|%onOrOff" - //% onOrOff.fieldEditor=toggleonoff + //% blockId=motorSetPower block="power %motor|to %power|%" //% weight=99 group="Motors" blockGap=8 - on(onOrOff: boolean = true) { - if (onOrOff) { + //% power.min=-100 power.max=100 + power(power: number) { + power = Math.clamp(-100, 100, power >> 0); + + const b = mkCmd(this.port, DAL.opOutputPower, 1) + b.setNumber(NumberFormat.Int8LE, 2, power) + writePWM(b) + if (power) { const b = mkCmd(this.port, DAL.opOutputStart, 0) writePWM(b); } else { - const b = mkCmd(this.port, DAL.opOutputStop, 1) - b.setNumber(NumberFormat.UInt8LE, 2, this.brake ? 1 : 0) - writePWM(b) + this.stop(); } } /** - * Sets the motor power level from ``-100`` to ``100``. - * @param motor the output connection that the motor is connected to - * @param power the desired speed to use. eg: 50 + * Moves the motor by a number of degrees + * @param degrees the angle to turn the motor + * @param angle the degrees to rotate, eg: 360 + * @param power the power from ``100`` full forward to ``-100`` full backward, eg: 50 */ - //% blockId=motorSetPower block="%motor|set power to %speed" - //% weight=62 group="Motors" blockGap=8 - //% speed.min=-100 speed.max=100 - setPower(power: number) { - const b = mkCmd(this.port, DAL.opOutputPower, 1) - b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power)) - writePWM(b) + //% blockId=motorMove block="move %motor|by %angle|degrees at %power|%" + //% weight=98 group="Motors" blockGap=8 + //% power.min=-100 power.max=100 + move(angle: number, power: number) { + angle = angle >> 0; + power = Math.clamp(-100, 100, power >> 0); + + step(this.port, { + speed: power, + step1: 0, + step2: angle, + step3: 0, + useSteps: true, + useBrake: this.brake + }) } + /** + * Stops the motor + */ + //% blockId=motorStop block="stop %motor" + //% weight=97 group="Motors" + stop() { + const b = mkCmd(this.port, DAL.opOutputStop, 1) + b.setNumber(NumberFormat.UInt8LE, 2, this.brake ? 1 : 0) + writePWM(b); + } + /** * Sets the automatic brake on or off when the motor is off * @param brake a value indicating if the motor should break when off */ - //% blockId=outputMotorSetBrakeMode block="%motor|set brake %brake" + //% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake" //% brake.fieldEditor=toggleonoff //% weight=60 group="Motors" blockGap=8 setBrake(brake: boolean) { @@ -133,7 +156,7 @@ namespace motors { /** * Reverses the motor polarity */ - //% blockId=motorSetReversed block="%motor|set reversed %reversed" + //% blockId=motorSetReversed block="set %motor|reversed %reversed" //% reversed.fieldEditor=toggleonoff //% weight=59 group="Motors" setReversed(reversed: boolean) { @@ -147,7 +170,7 @@ namespace motors { * @param motor the port which connects to the motor */ //% blockId=motorSpeed block="%motor|speed" - //% weight=50 group="Motors" blockGap=8 + //% weight=72 group="Motors" blockGap=8 speed(): number { return getMotorData(this.port).actualSpeed; } @@ -157,7 +180,7 @@ namespace motors { * @param motor the port which connects to the motor */ //% blockId=motorCount block="%motor|count" - //% weight=49 group="Motors" blockGap=8 + //% weight=71 group="Motors" blockGap=8 count(): number { return getMotorData(this.port).count; } @@ -167,7 +190,7 @@ namespace motors { * @param motor the port which connects to the motor */ //% blockId=motorTachoCount block="%motor|tacho count" - //% weight=48 group="Motors" + //% weight=70 group="Motors" tachoCount(): number { return getMotorData(this.port).tachoCount; } diff --git a/libs/ev3/ns.ts b/libs/ev3/ns.ts index f1348216..13ca4520 100644 --- a/libs/ev3/ns.ts +++ b/libs/ev3/ns.ts @@ -5,12 +5,12 @@ namespace brick { } -//% color="#8AC044" weight=95 icon="\uf185" -namespace motors { +//% color="#D42878" weight=95 +namespace sensors { } -//% color="#D42878" weight=90 -namespace sensors { +//% color="#8AC044" weight=90 icon="\uf185" +namespace motors { } //% color="#DF5014" weight=80 From 329a1e15eac87cda4be6b7936c39c88ae5dea07e Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 30 Oct 2017 21:39:50 -0700 Subject: [PATCH 2/2] simplified IR API --- libs/core/_locales/core-jsdoc-strings.json | 10 +++-- libs/core/_locales/core-strings.json | 12 ++++-- libs/core/ir.ts | 37 ++++++++++++----- libs/core/ultrasonic.ts | 47 ++++++++++++++-------- 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index 1182a9f9..1da6db92 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -68,10 +68,11 @@ "sensors.ColorSensor.reflectedLight": "Get current reflected light value from the color sensor.", "sensors.GyroSensor.angle": "Get the current angle from the gyroscope.", "sensors.GyroSensor.rate": "Get the current rotation rate from the gyroscope.", - "sensors.InfraredSensor.onObjectNear": "Registers code to run when an object is getting near.", - "sensors.InfraredSensor.onObjectNear|param|handler": "the code to run when detected", + "sensors.InfraredSensor.on": "Registers code to run when an object is getting near.", + "sensors.InfraredSensor.on|param|handler": "the code to run when detected", "sensors.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)", "sensors.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.", + "sensors.InfraredSensor.wait": "Waits for the event to occur", "sensors.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.", "sensors.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down", "sensors.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised", @@ -80,8 +81,9 @@ "sensors.TouchSensor.onEvent": "Do something when a touch sensor is touched...", "sensors.TouchSensor.onEvent|param|body": "code to run when the event is raised", "sensors.UltraSonicSensor.distance": "Gets the distance from the sonar in millimeters", - "sensors.UltraSonicSensor.onObjectNear": "Registers code to run when the given color is close", - "sensors.UltraSonicSensor.onObjectNear|param|handler": "the code to run when detected", + "sensors.UltraSonicSensor.on": "Registers code to run when the given color is close", + "sensors.UltraSonicSensor.on|param|handler": "the code to run when detected", + "sensors.UltraSonicSensor.wait": "Waits for the event to occur", "sensors.remoteButtonBottomLeft": "Remote bottom-left button.", "sensors.remoteButtonBottomRight": "Remote bottom-right button.", "sensors.remoteButtonCenter": "Remote beacon (center) button.", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index 1a61d9b9..a92fb75d 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -10,6 +10,8 @@ "ColorSensorColor.Red|block": "red", "ColorSensorColor.White|block": "white", "ColorSensorColor.Yellow|block": "yellow", + "InfraredSensorEvent.ObjectDetected|block": "object detected", + "InfraredSensorEvent.ObjectNear|block": "object near", "LightsPattern.GreenFlash|block": "Flashing Green", "LightsPattern.GreenPulse|block": "Pulsing Green", "LightsPattern.Green|block": "Green", @@ -25,11 +27,11 @@ "Output.B|block": "B", "Output.C|block": "C", "Output.D|block": "D", - "PromixityEvent.ObjectDetected|block": "object detected", - "PromixityEvent.ObjectNear|block": "object near", "TouchSensorEvent.Bumped|block": "bumped", "TouchSensorEvent.Pressed|block": "pressed", "TouchSensorEvent.Released|block": "released", + "UltrasonicSensorEvent.ObjectDetected|block": "object detected", + "UltrasonicSensorEvent.ObjectNear|block": "object near", "brick.Button.isPressed|block": "%button|is pressed", "brick.Button.onEvent|block": "on %button|%event", "brick.Button.wasPressed|block": "%button|was pressed", @@ -71,16 +73,18 @@ "sensors.ColorSensor.reflectedLight|block": "%color| reflected light", "sensors.GyroSensor.angle|block": "%sensor|angle", "sensors.GyroSensor.rate|block": "%sensor|rotation rate", - "sensors.InfraredSensor.onObjectNear|block": "on %sensor|object near", + "sensors.InfraredSensor.on|block": "on %sensor|%event", "sensors.InfraredSensor.proximity|block": "%infrared|proximity", "sensors.InfraredSensor.remoteCommand|block": "%infrared|remote command", + "sensors.InfraredSensor.wait|block": "wait %sensor|for %event", "sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed", "sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event", "sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed", "sensors.TouchSensor.isTouched|block": "%sensor|is touched", "sensors.TouchSensor.onEvent|block": "on %sensor|%event", "sensors.UltraSonicSensor.distance|block": "%sensor|distance", - "sensors.UltraSonicSensor.onObjectNear|block": "on %sensor|object near", + "sensors.UltraSonicSensor.on|block": "on %sensor|%event", + "sensors.UltraSonicSensor.wait|block": "wait %sensor|for %event", "sensors.color1|block": "color sensor 1", "sensors.color2|block": "color sensor 2", "sensors.color3|block": "color sensor 3", diff --git a/libs/core/ir.ts b/libs/core/ir.ts index d952a9f1..35406f79 100644 --- a/libs/core/ir.ts +++ b/libs/core/ir.ts @@ -21,6 +21,13 @@ const enum IrRemoteButton { BottomRight = 0x10, } +const enum InfraredSensorEvent { + //% block="object near" + ObjectNear = 1, + //% block="object detected" + ObjectDetected = 2 +} + namespace sensors { function mapButton(v: number) { switch (v) { @@ -148,8 +155,8 @@ namespace sensors { return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel)); else if (this.mode == IrSensorMode.Proximity) { const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff; - return d < this.proximityThreshold ? PromixityEvent.ObjectNear - : d > this.proximityThreshold + 5 ? PromixityEvent.ObjectDetected + return d < this.proximityThreshold ? UltrasonicSensorEvent.ObjectNear + : d > this.proximityThreshold + 5 ? UltrasonicSensorEvent.ObjectDetected : 0; } return 0 @@ -185,21 +192,31 @@ namespace sensors { * Registers code to run when an object is getting near. * @param handler the code to run when detected */ - //% help=input/infrared/on-object-near - //% block="on %sensor|object near" - //% blockId=infraredOnObjectNear + //% help=input/infrared/on + //% block="on %sensor|%event" + //% blockId=infraredOn //% parts="infraredsensor" //% blockNamespace=sensors //% weight=100 blockGap=8 //% group="Infrared Sensor" - onObjectNear(handler: () => void) { - control.onEvent(this._id, PromixityEvent.ObjectNear, handler); - if (this.proximity() == PromixityEvent.ObjectNear) + on(event: InfraredSensorEvent, handler: () => void) { + control.onEvent(this._id, InfraredSensorEvent.ObjectNear, handler); + if ( this.proximity() == InfraredSensorEvent.ObjectNear) control.runInBackground(handler); } - setObjectNearThreshold(distance: number) { - this.proximityThreshold = Math.max(1, Math.min(95, distance)); + /** + * Waits for the event to occur + */ + //% help=input/ultrasonic/wait + //% block="wait %sensor|for %event" + //% blockId=ultrasonicWait + //% parts="infraredsensor" + //% blockNamespace=sensors + //% weight=99 blockGap=8 + //% group="Ultrasonic Sensor" + wait(event: InfraredSensorEvent) { + // TODO } /** diff --git a/libs/core/ultrasonic.ts b/libs/core/ultrasonic.ts index 559d4c1e..fe32a12f 100644 --- a/libs/core/ultrasonic.ts +++ b/libs/core/ultrasonic.ts @@ -1,4 +1,4 @@ -const enum PromixityEvent { +const enum UltrasonicSensorEvent { //% block="object near" ObjectNear = 1, //% block="object detected" @@ -10,10 +10,12 @@ namespace sensors { //% fixedInstances export class UltraSonicSensor extends internal.UartSensor { private promixityThreshold: number; + private movementThreshold: number; constructor(port: number) { super(port) this.promixityThreshold = 10; + this.movementThreshold = 1; } _deviceType() { @@ -21,36 +23,49 @@ namespace sensors { } _query(): number { - const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff; - return d < this.promixityThreshold ? PromixityEvent.ObjectNear - : d > this.promixityThreshold + 5 ? PromixityEvent.ObjectDetected - : 0; + return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff; } _update(prev: number, curr: number) { - if (curr) - control.raiseEvent(this._id, curr); + // is there an object near? + if (prev >= this.promixityThreshold && curr < this.promixityThreshold) + control.raiseEvent(this._id, UltrasonicSensorEvent.ObjectNear); // TODO proper HI-LO sensor + + // did something change? + if (Math.abs(prev - curr) > this.movementThreshold) + control.raiseEvent(this._id, UltrasonicSensorEvent.ObjectDetected); // TODO debouncing } /** * Registers code to run when the given color is close * @param handler the code to run when detected */ - //% help=input/ultrasonic/on-object-near - //% block="on %sensor|object near" - //% blockId=ultrasonicOnObjectClose + //% help=input/ultrasonic/on + //% block="on %sensor|%event" + //% blockId=ultrasonicOn //% parts="infraredsensor" //% blockNamespace=sensors //% weight=100 blockGap=8 //% group="Ultrasonic Sensor" - onObjectNear(handler: () => void) { - control.onEvent(this._id, PromixityEvent.ObjectNear, handler); - if (this.distance() == PromixityEvent.ObjectNear) + on(event: UltrasonicSensorEvent, handler: () => void) { + control.onEvent(this._id, event, handler); + if (event == UltrasonicSensorEvent.ObjectNear + && this.distance() < this.promixityThreshold) control.runInBackground(handler); } - setObjectNearThreshold(distance: number) { - this.promixityThreshold = Math.max(1, Math.min(250, distance)); + /** + * Waits for the event to occur + */ + //% help=input/ultrasonic/wait + //% block="wait %sensor|for %event" + //% blockId=ultrasonicWait + //% parts="infraredsensor" + //% blockNamespace=sensors + //% weight=99 blockGap=8 + //% group="Ultrasonic Sensor" + wait(event: UltrasonicSensorEvent) { + // TODO } /** @@ -65,7 +80,7 @@ namespace sensors { //% weight=65 blockGap=8 //% group="Ultrasonic Sensor" distance() { - // it supposedly also has an inch mode, but we stick to mm + // it supposedly also has an inch mode, but we stick to cm this._setMode(0) return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff; }