Compare commits

..

23 Commits

Author SHA1 Message Date
a47988913e 0.0.25 2017-10-26 21:27:51 -07:00
ea72dba6c7 Merge pull request #17 from Microsoft/irevents
Ultrasonic + IR events + Remote events
2017-10-27 06:25:02 +02:00
215e846a54 refactored remote button 2017-10-26 21:10:37 -07:00
21b34cb459 simplified events 2017-10-26 20:57:18 -07:00
282134f5dc refactoring IR 2017-10-26 20:51:13 -07:00
6b44352839 event for ultrasonic module 2017-10-26 20:38:17 -07:00
9a883d5672 Merge branch 'master' into irevents 2017-10-26 20:21:06 -07:00
59ce4338d3 renaming IR events 2017-10-26 20:20:24 -07:00
90560050b8 Merge pull request #16 from Microsoft/fonts
Mounting events on various sensors
2017-10-27 05:19:36 +02:00
2c72173bfe Use the _query() infrastructure for polling 2017-10-25 13:34:05 +02:00
1a5992408b added event for color changes 2017-10-24 23:10:27 -07:00
0e1a3b7e6b adding setpixel 2017-10-24 22:05:24 -07:00
ea6bfa03bd touched -> pressed 2017-10-24 21:55:37 -07:00
20d584db2b 0.0.24 2017-10-24 21:18:16 -07:00
0e4e0d8899 0.0.23 2017-10-24 21:09:56 -07:00
a18a690417 Merge pull request #12 from Microsoft/motors
Converting motors to fixed instances
2017-10-25 06:09:27 +02:00
c9d57c5e8d enabling banner 2017-10-24 21:08:02 -07:00
7e9d42a571 reset motors on start 2017-10-24 20:28:31 -07:00
1b51320edb pausing while running motor 2017-10-24 20:20:07 -07:00
4f44238237 use fixed instances for motors 2017-10-24 20:16:33 -07:00
c8ffa0ded7 fixed test 2017-10-24 18:49:15 -07:00
6b07d5f716 0.0.22 2017-10-24 18:48:30 -07:00
8784e23b60 fixed build link 2017-10-24 17:01:36 -07:00
15 changed files with 444 additions and 230 deletions

View File

@ -1,6 +1,6 @@
# LEGO Mindstorms EV3 target for PXT
[![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_pink/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_pink/job/master/job/pxt-ev3_Push/)
[![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_rainbow/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/job/pxt-ev3_Push/)
This repo contains the editor target hosted at https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/

BIN
docs/static/hero.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -21,51 +21,57 @@
"input": "Respond to and read data from buttons and sensors.",
"input.Button": "Generic button class, for device buttons and sensors.",
"input.Button.isPressed": "Check if button is currently pressed or not.",
"input.Button.onEvent": "Do something when a button or sensor is clicked, double clicked, etc...",
"input.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
"input.Button.onEvent|param|body": "code to run when the event is raised",
"input.Button.wasPressed": "See if the button was pressed again since the last time you checked.",
"input.ColorSensor.ambientLight": "Get current ambient light value from the color sensor.",
"input.ColorSensor.color": "Get the current color from the color sensor.",
"input.ColorSensor.onColorDetected": "Registers code to run when the given color is detected",
"input.ColorSensor.onColorDetected|param|color": "the color to dtect",
"input.ColorSensor.onColorDetected|param|handler": "the code to run when detected",
"input.ColorSensor.reflectedLight": "Get current reflected light value from the color sensor.",
"input.GyroSensor.angle": "Get the current angle from the gyroscope.",
"input.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
"input.IrSensor.distance": "Get the distance measured by the infrared sensor.",
"input.IrSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
"input.InfraredSensor.onObjectNear": "Registers code to run when an object is getting near.",
"input.InfraredSensor.onObjectNear|param|handler": "the code to run when detected",
"input.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)",
"input.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
"input.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
"input.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
"input.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",
"input.RemoteInfraredBeaconButton.wasPressed": "See if the remote button was pressed again since the last time you checked.",
"input.TouchSensor.isTouched": "Check if touch sensor is touched.",
"input.TouchSensor.onEvent": "Do something when a touch sensor is touched...",
"input.TouchSensor.onEvent|param|body": "code to run when the event is raised",
"input.UltraSonicSensor.distance": "Gets the distance from the sonar in millimeters",
"input.UltraSonicSensor.onObjectNear": "Registers code to run when the given color is close",
"input.UltraSonicSensor.onObjectNear|param|handler": "the code to run when detected",
"input.buttonDown": "Down button on the EV3 Brick.",
"input.buttonEnter": "Enter button on the EV3 Brick.",
"input.buttonLeft": "Left button on the EV3 Brick.",
"input.buttonRight": "Right button on the EV3 Brick.",
"input.buttonUp": "Up button on the EV3 Brick.",
"input.remoteBottomLeft": "Remote bottom-left button.",
"input.remoteBottomRight": "Remote bottom-right button.",
"input.remoteCenter": "Remote beacon (center) button.",
"input.remoteTopLeft": "Remote top-left button.",
"input.remoteTopRight": "Remote top-right button.",
"input.remoteButtonBottomLeft": "Remote bottom-left button.",
"input.remoteButtonBottomRight": "Remote bottom-right button.",
"input.remoteButtonCenter": "Remote beacon (center) button.",
"input.remoteButtonTopLeft": "Remote top-left button.",
"input.remoteButtonTopRight": "Remote top-right button.",
"output.Motor.off": "Power off the motor.",
"output.Motor.on": "Power on the motor.",
"output.Motor.onForTime": "Power on the motor for a specified number of milliseconds.",
"output.Motor.onForTime|param|brake": "whether or not to use the brake",
"output.Motor.onForTime|param|ms": "the number of milliseconds to turn the motor on, eg: 500",
"output.Motor.onForTime|param|power": "the motor power level from ``-100`` to ``100``, eg: 50",
"output.Motor.on|param|power": "the motor power level from ``-100`` to ``100``, eg: 50",
"output.Motor.setPower": "Sets the motor power level from ``-100`` to ``100``.",
"output.Motor.setPower|param|power": "the desired speed to use. eg: 50",
"output.Motor.speed": "Gets motor actual speed.",
"output.createBuffer": "Create a new zero-initialized buffer.",
"output.createBuffer|param|size": "number of bytes in the buffer",
"output.getCurrentSpeed": "Get motor speed.",
"output.getCurrentSpeed|param|out": "the output connection that the motor is connected to",
"output.pattern": "Pattern block.",
"output.pattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
"output.powerMotor": "Switch the motor on or off.",
"output.powerMotor|param|on": "1 to turn the motor on, 0 to turn it off",
"output.powerMotor|param|out": "the output connection that the motor is connected to",
"output.setPower": "Set motor power.",
"output.setPower|param|out": "the output connection that the motor is connected to",
"output.setPower|param|power": "the desired power to use. eg: 100",
"output.setSpeed": "Set motor speed.",
"output.setSpeed|param|out": "the output connection that the motor is connected to",
"output.setSpeed|param|speed": "the desired speed to use. eg: 100",
"output.setStatusLight": "Set lights.",
"output.setStatusLight|param|pattern": "the lights pattern to use.",
"output.turn": "Turn a motor on for a specified number of milliseconds.",
"output.turn|param|ms": "the number of milliseconds to turn the motor on, eg: 500",
"output.turn|param|out": "the output connection that the motor is connected to",
"output.turn|param|useBrake": "whether or not to use the brake, defaults to false",
"screen.clear": "Clear screen and reset font to normal.",
"screen.doubleIcon": "Double size of an icon.",
"screen.drawIcon": "Draw an icon on the screen.",
@ -73,6 +79,10 @@
"screen.print|param|text": "the text to print on the screen, eg: \"Hello world\"",
"screen.print|param|x": "the starting position's x coordinate, eg: 0",
"screen.print|param|y": "the starting position's x coordinate, eg: 0",
"screen.setPixel": "Sets a pixel on or off",
"screen.setPixel|param|on": "a value indicating if the pixel should be on or off",
"screen.setPixel|param|x": "the starting position's x coordinate, eg: 0",
"screen.setPixel|param|y": "the starting position's x coordinate, eg: 0",
"serial": "Reading and writing data over a serial connection.",
"serial.writeDmesg": "Send DMESG debug buffer over serial."
}

View File

@ -2,6 +2,14 @@
"ButtonEvent.Click|block": "click",
"ButtonEvent.Down|block": "down",
"ButtonEvent.Up|block": "up",
"ColorSensorColor.Black|block": "black",
"ColorSensorColor.Blue|block": "blue",
"ColorSensorColor.Brown|block": "brown",
"ColorSensorColor.Green|block": "green",
"ColorSensorColor.None|block": "none",
"ColorSensorColor.Red|block": "red",
"ColorSensorColor.White|block": "white",
"ColorSensorColor.Yellow|block": "yellow",
"LightsPattern.GreenFlash|block": "Flashing Green",
"LightsPattern.GreenPulse|block": "Pulsing Green",
"LightsPattern.Green|block": "Green",
@ -12,9 +20,16 @@
"LightsPattern.RedFlash|block": "Flashing Red",
"LightsPattern.RedPulse|block": "Pulsing Red",
"LightsPattern.Red|block": "Red",
"Output.ALL|block": "All",
"Output.A|block": "A",
"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",
"TouchSensorEvent.Touched|block": "touched",
"control.raiseEvent|block": "raise event|from %src|with value %value",
"control|block": "control",
"input.Button.isPressed|block": "%button|is pressed",
@ -22,14 +37,20 @@
"input.Button.wasPressed|block": "%button|was pressed",
"input.ColorSensor.ambientLight|block": "%color| ambient light",
"input.ColorSensor.color|block": "%color| color",
"input.ColorSensor.onColorDetected|block": "on %sensor|detected %color",
"input.ColorSensor.reflectedLight|block": "%color| reflected light",
"input.GyroSensor.angle|block": "%sensor|angle",
"input.GyroSensor.rate|block": "%sensor|rotation rate",
"input.IrSensor.distance|block": "%infrared|distance",
"input.IrSensor.remoteCommand|block": "%infrared|remote command",
"input.InfraredSensor.onObjectNear|block": "on %sensor|object near",
"input.InfraredSensor.proximity|block": "%infrared|proximity",
"input.InfraredSensor.remoteCommand|block": "%infrared|remote command",
"input.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
"input.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
"input.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
"input.TouchSensor.isTouched|block": "%sensor|is touched",
"input.TouchSensor.onEvent|block": "on %sensor|%event",
"input.UltraSonicSensor.distance|block": "%sensor|distance",
"input.UltraSonicSensor.onObjectNear|block": "on %sensor|object near",
"input.buttonDown|block": "brick button down",
"input.buttonEnter|block": "brick button enter",
"input.buttonLeft|block": "brick button left",
@ -43,11 +64,15 @@
"input.gyro2|block": "gyro sensor 2",
"input.gyro3|block": "gyro sensor 3",
"input.gyro4|block": "gyro sensor 4",
"input.remoteBottomLeft|block": "remote bottom-left",
"input.remoteBottomRight|block": "remote bottom-right",
"input.remoteCenter|block": "remote center",
"input.remoteTopLeft|block": "remote top-left",
"input.remoteTopRight|block": "remote top-right",
"input.infraredSensor1|block": "infrared sensor 1",
"input.infraredSensor2|block": "infrared sensor 2",
"input.infraredSensor3|block": "infrared sensor 3",
"input.infraredSensor4|block": "infrared sensor 4",
"input.remoteButtonBottomLeft|block": "remote button bottom-left",
"input.remoteButtonBottomRight|block": "remote button bottom-right",
"input.remoteButtonCenter|block": "remote button center",
"input.remoteButtonTopLeft|block": "remote button top-left",
"input.remoteButtonTopRight|block": "remote button top-right",
"input.touchSensor1|block": "touch sensor 1",
"input.touchSensor2|block": "touch sensor 2",
"input.touchSensor3|block": "touch sensor 3",
@ -57,15 +82,20 @@
"input.ultrasonic3|block": "ultrasonic sensor 3",
"input.ultrasonic4|block": "ultrasonic sensor 4",
"input|block": "input",
"output.getCurrentSpeed|block": "motor %out|speed",
"output.Motor.off|block": "%motor|OFF then brake %brake",
"output.Motor.onForTime|block": "%motor|ON at power %power|for %ms=timePicker|ms then brake %brake",
"output.Motor.on|block": "%motor|ON at power %power",
"output.Motor.setPower|block": "%motor|set power to %speed",
"output.Motor.speed|block": "%motor|speed",
"output.motorA|block": "motor A",
"output.motorB|block": "motor B",
"output.motorC|block": "motor C",
"output.motorD|block": "motor D",
"output.pattern|block": "%pattern",
"output.powerMotor|block": "power motor %out|%on",
"output.setPower|block": "set motor %out| power to %power",
"output.setSpeed|block": "set motor %out| speed to %speed",
"output.setStatusLight|block": "set status light %pattern=led_pattern",
"output.turn|block": "turn motor %out| on for %ms=timePicker|milliseconds",
"output|block": "output",
"screen.print|block": "print %text| at x: %x| y: %y",
"screen.setPixel|block": "set pixel %on| at x: %x| y: %y",
"screen|block": "screen",
"serial|block": "serial",
"{id:category}Control": "Control",
@ -79,6 +109,7 @@
"{id:group}Gyro Sensor": "Gyro Sensor",
"{id:group}Infrared Sensor": "Infrared Sensor",
"{id:group}Motors": "Motors",
"{id:group}Remote Infrared Beacon": "Remote Infrared Beacon",
"{id:group}Touch Sensor": "Touch Sensor",
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
}

View File

@ -65,7 +65,7 @@ namespace input {
}
//% hidden
update(curr: boolean) {
_update(curr: boolean) {
if (this._isPressed == curr) return
this._isPressed = curr
if (curr) {
@ -112,7 +112,7 @@ namespace input {
}
/**
* Do something when a button or sensor is clicked, double clicked, etc...
* Do something when a button or sensor is clicked, up or down.
* @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
@ -159,7 +159,7 @@ namespace input {
if (curr & DAL.BUTTON_ID_ESCAPE)
control.reset()
for (let b of buttons)
b.update(!!(curr & b.mask))
b._update(!!(curr & b.mask))
})
control.dmesg("runtime started, " + control.deviceFirmwareVersion())
}

View File

@ -9,13 +9,21 @@ const enum ColorSensorMode {
}
const enum ColorSensorColor {
//% block="none"
None,
//% block="black"
Black,
//% block="blue"
Blue,
//% block="green"
Green,
//% block="yellow"
Yellow,
//% block="red"
Red,
//% block="white"
White,
//% block="brown"
Brown,
}
@ -35,6 +43,35 @@ namespace input {
this._setMode(m)
}
_query() {
if (this.mode == ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0)
return 0
}
_update(prev: number, curr: number) {
control.raiseEvent(this._id, curr);
}
/**
* Registers code to run when the given color is detected
* @param color the color to dtect
* @param handler the code to run when detected
*/
//% help=input/color/on-color-detected
//% block="on %sensor|detected %color"
//% blockId=colorOnColorDetected
//% parts="colorsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Color Sensor"
onColorDetected(color: ColorSensorColor, handler: () => void) {
control.onEvent(this._id, <number>color, handler);
this.setMode(ColorSensorMode.Color)
if (this.color() == color)
control.runInBackground(handler)
}
/**
* Get current ambient light value from the color sensor.
* @param color the color sensor to query the request

View File

@ -40,24 +40,24 @@ namespace input {
}
}
let buttons: Button[]
let buttons: RemoteInfraredBeaconButton[]
function create(ir: IrSensor) {
function create(ir: InfraredSensor) {
// it's created by referencing it
}
export function irButton(id: IrRemoteButton) {
export function irButton(id: IrRemoteButton): RemoteInfraredBeaconButton {
if (buttons == null) {
buttons = []
for (let i = 0; i < 5; ++i) {
buttons.push(new Button())
buttons.push(new RemoteInfraredBeaconButton(new Button()))
}
// make sure sensors are up
create(ir1)
create(ir2)
create(ir3)
create(ir4)
create(infraredSensor1)
create(infraredSensor2)
create(infraredSensor3)
create(infraredSensor4)
}
let num = -1
@ -69,29 +69,101 @@ namespace input {
return buttons[num]
}
//% fixedInstance
export class IrSensor extends internal.UartSensor {
private channel: IrRemoteChannel
//% fixedInstances
export class RemoteInfraredBeaconButton extends control.Component {
private button: Button;
constructor(button: Button) {
super();
this.button = button;
}
_update(curr: boolean) {
this.button._update(curr);
}
/**
* Check if a remote button is currently pressed or not.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/is-pressed
//% block="%button|is pressed"
//% blockId=remoteButtonIsPressed
//% parts="remote"
//% blockNamespace=input
//% weight=81 blockGap=8
//% group="Remote Infrared Beacon"
isPressed() {
return this.button.isPressed();
}
/**
* See if the remote button was pressed again since the last time you checked.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/was-pressed
//% block="%button|was pressed"
//% blockId=remotebuttonWasPressed
//% parts="remote"
//% blockNamespace=input
//% weight=80 blockGap=8
//% group="Remote Infrared Beacon"
wasPressed() {
return this.button.wasPressed();
}
/**
* Do something when a button or sensor is clicked, up or down
* @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/remote-infrared-beacon/on-event
//% blockId=remotebuttonEvent block="on %button|%event"
//% parts="remote"
//% blockNamespace=input
//% weight=99 blockGap=8
//% group="Remote Infrared Beacon"
onEvent(ev: ButtonEvent, body: () => void) {
this.button.onEvent(ev, body);
}
}
//% fixedInstances
export class InfraredSensor extends internal.UartSensor {
private channel: IrRemoteChannel;
private proximityThreshold: number;
constructor(port: number) {
super(port)
this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = 10;
irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work
this.mode = IrSensorMode.RemoteControl
this.mode = IrSensorMode.RemoteControl;
}
_query() {
if (this.mode == IrSensorMode.RemoteControl)
return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel))
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
: 0;
}
return 0
}
_update(prev: number, curr: number) {
for (let i = 0; i < buttons.length; ++i) {
let v = !!(curr & (1 << i))
buttons[i].update(v)
if (this.mode == IrSensorMode.RemoteControl) {
for (let i = 0; i < buttons.length; ++i) {
let v = !!(curr & (1 << i))
buttons[i]._update(v)
}
} else {
if (curr)
control.raiseEvent(this._id, curr);
}
}
@ -102,26 +174,47 @@ namespace input {
setRemoteChannel(c: IrRemoteChannel) {
c = Math.clamp(0, 3, c | 0)
this.channel = c
this.setMode(IrSensorMode.RemoteControl)
this._setMode(IrSensorMode.RemoteControl)
}
setMode(m: IrSensorMode) {
_setMode(m: IrSensorMode) {
this._setMode(m)
}
/**
* Get the distance measured by the infrared sensor.
* 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
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Infrared Sensor"
onObjectNear(handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.proximity() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.proximityThreshold = Math.max(1, Math.min(95, distance));
}
/**
* Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)
* @param ir the infrared sensor
*/
//% help=input/infrared/distance
//% block="%infrared|distance"
//% blockId=infraredGetDistance
//% help=input/infrared/proximity
//% block="%infrared|proximity"
//% blockId=infraredGetProximity
//% parts="infrared"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Infrared Sensor"
distance() {
this.setMode(IrSensorMode.Proximity)
proximity() {
this._setMode(IrSensorMode.Proximity)
return this.getNumber(NumberFormat.UInt8LE, 0)
}
@ -137,56 +230,57 @@ namespace input {
//% weight=65 blockGap=8
//% group="Infrared Sensor"
remoteCommand() {
this.setMode(IrSensorMode.RemoteControl)
this._setMode(IrSensorMode.RemoteControl)
return this.getNumber(NumberFormat.UInt8LE, this.channel)
}
// TODO
getDirectionAndDistance() {
this.setMode(IrSensorMode.Seek)
this._setMode(IrSensorMode.Seek)
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
}
}
//% whenUsed
export const ir1: IrSensor = new IrSensor(1)
//% fixedInstance whenUsed block="infrared sensor 1"
export const infraredSensor1: InfraredSensor = new InfraredSensor(1)
//% whenUsed
export const ir2: IrSensor = new IrSensor(2)
//% fixedInstance whenUsed block="infrared sensor 2"
export const infraredSensor2: InfraredSensor = new InfraredSensor(2)
//% whenUsed
export const ir3: IrSensor = new IrSensor(3)
//% fixedInstance whenUsed block="infrared sensor 3"
export const infraredSensor3: InfraredSensor = new InfraredSensor(3)
//% whenUsed
export const ir4: IrSensor = new IrSensor(4)
//% fixedInstance whenUsed block="infrared sensor 4"
export const infraredSensor4: InfraredSensor = new InfraredSensor(4)
/**
* Remote top-left button.
*/
//% whenUsed block="remote top-left" weight=95 fixedInstance
export const remoteTopLeft = irButton(IrRemoteButton.TopLeft)
/**
* Remote top-right button.
*/
//% whenUsed block="remote top-right" weight=95 fixedInstance
export const remoteTopRight = irButton(IrRemoteButton.TopRight)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote bottom-left" weight=95 fixedInstance
export const remoteBottomLeft = irButton(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote bottom-right" weight=95 fixedInstance
export const remoteBottomRight = irButton(IrRemoteButton.BottomRight)
/**
* Remote beacon (center) button.
*/
//% whenUsed block="remote center" weight=95 fixedInstance
export const remoteCenter = irButton(IrRemoteButton.CenterBeacon)
//% whenUsed block="remote button center" weight=95 fixedInstance
export const remoteButtonCenter = irButton(IrRemoteButton.CenterBeacon)
/**
* Remote top-left button.
*/
//% whenUsed block="remote button top-left" weight=95 fixedInstance
export const remoteButtonTopLeft = irButton(IrRemoteButton.TopLeft)
/**
* Remote top-right button.
*/
//% whenUsed block="remote button top-right" weight=95 fixedInstance
export const remoteButtonTopRight = irButton(IrRemoteButton.TopRight)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote button bottom-left" weight=95 fixedInstance
export const remoteButtonBottomLeft = irButton(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote button bottom-right" weight=95 fixedInstance
export const remoteButtonBottomRight = irButton(IrRemoteButton.BottomRight)
}

View File

@ -1,5 +1,5 @@
//% color="#B4009E" weight=98 icon="\uf192"
//% groups='["Touch Sensor", "Gyro Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote", "Brick"]'
//% groups='["Brick", "Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]'
namespace input {
}

View File

@ -1,8 +1,13 @@
enum Output {
//% block="A"
A = 0x01,
//% block="B"
B = 0x02,
//% block="C"
C = 0x04,
//% block="D"
D = 0x08,
//% block="All"
ALL = 0x0f
}
@ -15,7 +20,6 @@ enum OutputType {
namespace output {
let pwmMM: MMap
let motorMM: MMap
let currentSpeed: number[] = []
const enum MotorDataOff {
TachoCounts = 0, // int32
@ -31,19 +35,13 @@ namespace output {
if (!pwmMM) control.fail("no PWM file")
motorMM = control.mmap("/dev/lms_motor", MotorDataOff.Size * DAL.NUM_OUTPUTS, 0)
stop(Output.ALL)
currentSpeed[Output.A] = -1;
currentSpeed[Output.B] = -1;
currentSpeed[Output.C] = -1;
currentSpeed[Output.D] = -1;
currentSpeed[Output.ALL] = -1;
resetMotors()
let buf = output.createBuffer(1)
buf[0] = DAL.opProgramStart
writePWM(buf)
}
function writePWM(buf: Buffer): void {
init()
pwmMM.write(buf)
@ -55,81 +53,117 @@ namespace output {
}
function mkCmd(out: Output, cmd: number, addSize: number) {
let b = createBuffer(2 + addSize)
const b = createBuffer(2 + addSize)
b.setNumber(NumberFormat.UInt8LE, 0, cmd)
b.setNumber(NumberFormat.UInt8LE, 1, out)
return b
}
/**
* Turn a motor on for a specified number of milliseconds.
* @param out the output connection that the motor is connected to
* @param ms the number of milliseconds to turn the motor on, eg: 500
* @param useBrake whether or not to use the brake, defaults to false
*/
//% blockId=output_turn block="turn motor %out| on for %ms=timePicker|milliseconds"
//% weight=100 group="Motors"
export function turn(out: Output, ms: number, useBrake = false) {
// TODO: use current power / speed configuration
output.step(out, {
speed: 100,
step1: 0,
step2: ms,
step3: 0,
useSteps: false,
useBrake: useBrake
})
}
function resetMotors() {
reset(Output.ALL)
}
/**
* Switch the motor on or off.
* @param out the output connection that the motor is connected to
* @param on 1 to turn the motor on, 0 to turn it off
*/
//% blockId=outputMotorPowerOnOff block="power motor %out|%on"
//% weight=90 group="Motors"
//% on.fieldEditor="toggleonoff"
export function powerMotor(out: Output, on: boolean, useBrake = false) {
if (on) {
output.start(out);
} else {
output.stop(out, useBrake);
//% fixedInstances
export class Motor extends control.Component {
port: Output;
constructor(port: Output) {
super();
this.port = port;
}
/**
* Power off the motor.
* @param motor the motor to turn off
*/
//% blockId=outputMotorOf block="%motor|OFF then brake %brake"
//% brake.fieldEditor=toggleonoff
//% weight=100 group="Motors" blockGap=8
off(brake = false) {
const b = mkCmd(this.port, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, brake ? 1 : 0)
writePWM(b)
}
/**
* Power on the motor.
* @param motor the motor to turn on
* @param power the motor power level from ``-100`` to ``100``, eg: 50
*/
//% blockId=outputMotorOn block="%motor|ON at power %power"
//% power.min=-100 power.max=100
//% weight=99 group="Motors" blockGap=8
on(power: number = 50) {
this.setPower(power);
const b = mkCmd(this.port, DAL.opOutputStart, 0)
writePWM(b);
}
/**
* Power on the motor for a specified number of milliseconds.
* @param motor the motor to turn on
* @param power the motor power level from ``-100`` to ``100``, eg: 50
* @param ms the number of milliseconds to turn the motor on, eg: 500
* @param brake whether or not to use the brake
*/
//% blockId=outputMotorOnForTime block="%motor|ON at power %power|for %ms=timePicker|ms then brake %brake"
//% power.min=-100 power.max=100
//% brake.fieldEditor=toggleonoff
//% weight=98 group="Motors" blockGap=8
onForTime(power: number, ms: number, brake = false) {
step(this.port, {
power,
step1: 0,
step2: ms,
step3: 0,
useSteps: false,
useBrake: brake
})
loops.pause(ms);
}
/**
* 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
*/
//% blockId=motorSetPower block="%motor|set power to %speed"
//% weight=60 group="Motors"
//% 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)
}
/**
* Gets motor actual speed.
* @param motor the port which connects to the motor
*/
//% blockId=motorSpeed block="%motor|speed"
//% weight=50 group="Motors" blockGap=8
speed() {
return getMotorData(this.port).actualSpeed;
}
}
/**
* Turn motor off.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_stop block="turn motor %out|off"
//% weight=90 group="Motors"
//% deprecated=1
export function stop(out: Output, useBrake = false) {
let b = mkCmd(out, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, useBrake ? 1 : 0)
writePWM(b)
}
//% whenUsed fixedInstance block="motor B"
export const motorB = new Motor(Output.B);
/**
* Turn motor on.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_start block="turn motor %out|on"
//% weight=95 group="Motors"
//% deprecated=1
export function start(out: Output) {
if (currentSpeed[out] == -1) setSpeed(out, 50)
let b = mkCmd(out, DAL.opOutputStart, 0)
writePWM(b)
}
//% whenUsed fixedInstance block="motor C"
export const motorC = new Motor(Output.C);
export function reset(out: Output) {
//% whenUsed fixedInstance block="motor A"
export const motorA = new Motor(Output.A);
//% whenUsed fixedInstance block="motor D"
export const motorD = new Motor(Output.D);
function reset(out: Output) {
let b = mkCmd(out, DAL.opOutputReset, 0)
writePWM(b)
}
export function clearCount(out: Output) {
function clearCount(out: Output) {
let b = mkCmd(out, DAL.opOutputClearCount, 0)
writePWM(b)
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
@ -147,14 +181,14 @@ namespace output {
return 0
}
export interface MotorData {
interface MotorData {
actualSpeed: number; // -100..+100
tachoCount: number;
count: number;
}
// only a single output at a time
export function getMotorData(out: Output): MotorData {
function getMotorData(out: Output): MotorData {
let buf = motorMM.slice(outOffset(out), MotorDataOff.Size)
return {
actualSpeed: buf.getNumber(NumberFormat.Int8LE, MotorDataOff.Speed),
@ -163,52 +197,13 @@ namespace output {
}
}
/**
* Get motor speed.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_getCurrentSpeed block="motor %out|speed"
//% weight=70 group="Motors"
export function getCurrentSpeed(out: Output) {
return getMotorData(out).actualSpeed;
}
/**
* Set motor speed.
* @param out the output connection that the motor is connected to
* @param speed the desired speed to use. eg: 100
*/
//% blockId=output_setSpeed block="set motor %out| speed to %speed"
//% weight=81 group="Motors"
//% speed.min=-100 speed.max=100
export function setSpeed(out: Output, speed: number) {
currentSpeed[out] = speed;
let b = mkCmd(out, DAL.opOutputSpeed, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, speed))
writePWM(b)
}
/**
* Set motor power.
* @param out the output connection that the motor is connected to
* @param power the desired power to use. eg: 100
*/
//% blockId=output_setPower block="set motor %out| power to %power"
//% weight=80 group="Motors"
//% power.min=-100 power.max=100
export function setPower(out: Output, power: number) {
let b = mkCmd(out, DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power))
writePWM(b)
}
export function setPolarity(out: Output, polarity: number) {
function setPolarity(out: Output, polarity: number) {
let b = mkCmd(out, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-1, 1, polarity))
writePWM(b)
}
export interface StepOptions {
interface StepOptions {
power?: number;
speed?: number; // either speed or power has to be present
step1: number;
@ -218,7 +213,7 @@ namespace output {
useBrake?: boolean;
}
export function step(out: Output, opts: StepOptions) {
function step(out: Output, opts: StepOptions) {
let op = opts.useSteps ? DAL.opOutputStepSpeed : DAL.opOutputTimeSpeed
let speed = opts.speed
if (speed == null) {

View File

@ -78,13 +78,21 @@ namespace screen {
}
}
export function setPixel(x: number, y: number, mode = Draw.Normal) {
/**
* Sets a pixel on or off
* @param on a value indicating if the pixel should be on or off
* @param x the starting position's x coordinate, eg: 0
* @param y the starting position's x coordinate, eg: 0
*/
//% blockId=screen_setpixel block="set pixel %on| at x: %x| y: %y"
//% weight=98 group="Brick" blockNamespace=output
//% x.min=0 x.max=178 y.min=0 y.max=128 on.fieldEditor=toggleonoff
export function setPixel(on: boolean, x: number, y: number) {
x |= 0
y |= 0
if (0 <= x && x < DAL.LCD_WIDTH && 0 <= y && y < DAL.LCD_HEIGHT)
_setPixel(x, y, mode)
_setPixel(x, y, on ? Draw.Normal : Draw.Clear)
}
/**
* Show text on the screen.

View File

@ -31,17 +31,17 @@ input.buttonUp.onEvent(ButtonEvent.Click, () => {
let num = 0
input.touchSensor1.onEvent(ButtonEvent.Click, () => {
input.touchSensor1.onEvent(TouchSensorEvent.Bumped, () => {
screen.print("Click! " + num, 10, 60)
num++
})
input.remoteTopLeft.onEvent(ButtonEvent.Click, () => {
input.remoteButtonTopLeft.onEvent(ButtonEvent.Click, () => {
screen.print("TOPLEFT " + num, 10, 60)
num++
})
input.remoteTopRight.onEvent(ButtonEvent.Down, () => {
input.remoteButtonTopRight.onEvent(ButtonEvent.Down, () => {
screen.print("TOPRIGH " + num, 10, 60)
num++
})

View File

@ -4,8 +4,8 @@
* Touch sensor interactions
*/
const enum TouchSensorEvent {
//% block="touched"
Touched = 4,
//% block="pressed"
Pressed = 4,
//% block="bumped"
Bumped = 1,
//% block="released"
@ -28,7 +28,7 @@ namespace input {
}
_update(prev: number, curr: number) {
this.button.update(curr > 0)
this.button._update(curr > 0)
}
_deviceType() {

View File

@ -1,15 +1,58 @@
const enum PromixityEvent {
//% block="object near"
ObjectNear = 1,
//% block="object detected"
ObjectDetected = 2
}
namespace input {
//% fixedInstances
export class UltraSonicSensor extends internal.UartSensor {
private promixityThreshold: number;
constructor(port: number) {
super(port)
this.promixityThreshold = 10;
}
_deviceType() {
return DAL.DEVICE_TYPE_ULTRASONIC
}
_query(): number {
const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
return d < this.promixityThreshold ? PromixityEvent.ObjectNear
: d > this.promixityThreshold + 5 ? PromixityEvent.ObjectDetected
: 0;
}
_update(prev: number, curr: number) {
if (curr)
control.raiseEvent(this._id, curr);
}
/**
* 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
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Ultrasonic Sensor"
onObjectNear(distance: number, handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.distance() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.promixityThreshold = Math.max(1, Math.min(250, distance));
}
/**
* Gets the distance from the sonar in millimeters
* @param sensor the ultrasonic sensor port
@ -24,7 +67,7 @@ namespace input {
distance() {
// it supposedly also has an inch mode, but we stick to mm
this._setMode(0)
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
}
}

View File

@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "0.0.21",
"version": "0.0.25",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true,
"keywords": [

View File

@ -89,10 +89,6 @@
"name": "About",
"path": "/about"
},
{
"name": "Examples",
"path": "#projects:Examples"
},
{
"name": "Blocks",
"path": "/blocks"
@ -110,12 +106,12 @@
"path": "https://www.lego.com/en-us/mindstorms/products/mindstorms-ev3-31313"
}
],
"useStartPage": true,
"showHomeScreen": true,
"homeScreenHero": "./static/hero.png",
"invertedMenu": false,
"invertedMonaco": false,
"monacoToolbox": true,
"invertedToolbox": true,
"exampleGallery": "examples",
"hasAudio": true,
"usbHelp": [],
"extendEditor": true,