Compare commits

...

6 Commits

Author SHA1 Message Date
ed653e8a37 0.1.7 2018-03-28 09:05:10 -07:00
31f91d4e24 upgrading to latest common packages (#383) 2018-03-28 09:04:49 -07:00
8536126e23 removing tacho (#382) 2018-03-28 09:04:28 -07:00
f1ea113fc0 0.1.6 2018-03-28 08:50:34 -07:00
550528c695 bringing back show ports (#377)
* bringing back show ports

* added firmware links in docs

* updated color rendering

* better rendering of touch/ultra/ir

* better data per sensor
2018-03-28 08:50:14 -07:00
89e1819399 Applying home screen UI changes (#378) 2018-03-27 16:30:43 -07:00
21 changed files with 155 additions and 121 deletions

View File

@ -27,6 +27,12 @@ so it appears as a mounted drive (named **EV3**).
Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary
program to a **.uf2** file, which you then copy to the **EV3** drive, which flashes the device with the new program. program to a **.uf2** file, which you then copy to the **EV3** drive, which flashes the device with the new program.
### ~ hint
Not seeing the **EV3** drive? Make sure to upgrade your firmware at https://ev3manager.education.lego.com/.
### ~
## Simulator: Test Your Code ## Simulator: Test Your Code
You can run your code using the micro:bit simulator, all within the confines of a web browser. You can run your code using the micro:bit simulator, all within the confines of a web browser.

View File

@ -19,6 +19,5 @@ motors.stopAll()
```cards ```cards
motors.largeA.speed() motors.largeA.speed()
motors.largeA.angle() motors.largeA.angle()
motors.largeA.tacho()
motors.largeA.clearCounts() motors.largeA.clearCounts()
``` ```

View File

@ -17,11 +17,11 @@ let tachoCount = 0;
motors.largeA.reset() motors.largeA.reset()
motors.largeA.run(50) motors.largeA.run(50)
pause(10000) pause(10000)
tachoCount = motors.largeA.tacho() tachoCount = motors.largeA.angle()
motors.largeA.clearCounts() motors.largeA.clearCounts()
motors.largeA.run(50) motors.largeA.run(50)
pause(10000) pause(10000)
if (tachoCount == motors.largeA.tacho()) { if (tachoCount == motors.largeA.angle()) {
brick.showString("Motor turns equal.", 1) brick.showString("Motor turns equal.", 1)
} else { } else {
brick.showString("Motor turns NOT equal.", 1) brick.showString("Motor turns NOT equal.", 1)

View File

@ -1,48 +0,0 @@
# tacho
Get the current number of degress of rotation.
```sig
motors.largeA.tacho()
```
The motors that come with your @boardname@ have a way to detect their own turning motion. They count the amount of motor rotation in degrees. The motor will count each degree of angle rotation up to 360 degrees for a full rotation. As the motor continues to turn, the _tacho_ count keeps adding up the degrees even past one full rotation. So, if the motor makes 3 complete rotations, the count will be 1080.
The name _tacho_ comes from the first part of the word [tachometer](https://en.wikipedia.org/wiki/Tachometer) which is a device to measure how fast something is turning. The motor controller in the brick uses the tacho count to regulate the motor's speed.
## ~hint
**Measure RPM**
A standard way to know how fast a motor is turning is by measuring its _revolutions per minute_ (rpm). One revolution is the same thing as a rotation, or one turn. How do you measure rpm? Well, here's a simple way:
1. Record the current tacho count
2. Run the motor for 60 seconds
3. Get the tacho count again
4. Subtract the first tacho count from the second one
5. Divide that number by `360`
## ~
## Returns
* a [number](/types/number) which is the total count of degrees of rotation that the motor has turned since it was first started or reset.
## Example
Run the motor connected to port **A** at half speed for 5 seconds. Display the number of full rotations on the screen.
```blocks
motors.largeA.run(50)
pause(5000)
motors.largeA.stop()
brick.showString("Motor rotations:", 1)
brick.showNumber(motors.largeA.tacho() / 360, 3)
motors.largeA.run(50)
```
## See also
[angle](/reference/motors/motor/tacho), [speed](/reference/motors/motor/speed),
[set regulated](/reference/motors/motor/set-regulated),
[reset](/reference/motors/motor/reset), [clear counts](/reference/motors/motor/clear-counts)

View File

@ -16,6 +16,7 @@
"ns.ts", "ns.ts",
"control.cpp", "control.cpp",
"control.ts", "control.ts",
"eventcontext.ts",
"serial.cpp", "serial.cpp",
"serial.ts", "serial.ts",
"fieldeditors.ts" "fieldeditors.ts"

10
libs/base/shims.d.ts vendored
View File

@ -102,14 +102,10 @@ declare namespace control {
function millis(): int32; function millis(): int32;
/** /**
* Run code when a registered event happens. * Used internally
* @param id the event compoent id
* @param value the event value to match
*/ */
//% weight=20 blockGap=8 blockId="control_on_event" block="on event|from %src|with value %value" //% flags.defl=16 shim=control::internalOnEvent
//% blockExternalInputs=1 function internalOnEvent(src: int32, value: int32, handler: () => void, flags?: int32): void;
//% help="control/on-event" flags.defl=16 shim=control::onEvent
function onEvent(src: int32, value: int32, handler: () => void, flags?: int32): void;
/** /**
* Reset the device. * Reset the device.

View File

@ -96,6 +96,22 @@ namespace sensors {
return 0 return 0
} }
_info(): string {
switch (this.mode) {
case ColorSensorMode.Color:
return ["none",
"black",
"blue",
"green",
"yellow",
"red",
"white",
"brown"][this._query()];
default:
return this._query().toString();
}
}
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
if (this.calibrating) return; // simply ignore data updates while calibrating if (this.calibrating) return; // simply ignore data updates while calibrating
if (this.mode == ColorSensorMode.Color) if (this.mode == ColorSensorMode.Color)

View File

@ -177,6 +177,10 @@ namespace sensors.internal {
return 0 return 0
} }
_info(): string {
return this._query().toString();
}
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
} }

View File

@ -378,21 +378,6 @@ namespace motors {
return getMotorData(this._port).count; return getMotorData(this._port).count;
} }
/**
* Gets motor tachometer count.
* @param motor the port which connects to the motor
*/
//% blockId=motorTachoCount block="%motor|tacho"
//% weight=69
//% blockGap=8
//% group="Counters"
//% help=motors/motor/tacho
tacho(): number {
this.init();
return getMotorData(this._port).tachoCount;
}
/** /**
* Clears the motor count * Clears the motor count
*/ */

View File

@ -56,7 +56,7 @@ namespace sensors {
const __remoteButtons: RemoteInfraredBeaconButton[] = []; const __remoteButtons: RemoteInfraredBeaconButton[] = [];
function __irButton(id: InfraredRemoteButton): RemoteInfraredBeaconButton { function __irButton(id: InfraredRemoteButton): RemoteInfraredBeaconButton {
for(let i = 0; i < __remoteButtons.length; ++i) { for (let i = 0; i < __remoteButtons.length; ++i) {
if (__remoteButtons[i].position == id) if (__remoteButtons[i].position == id)
return __remoteButtons[i]; return __remoteButtons[i];
} }
@ -161,6 +161,14 @@ namespace sensors {
return 0 return 0
} }
_info(): string {
if (this.mode == InfraredSensorMode.RemoteControl)
return "remote";
else if (this.mode == InfraredSensorMode.Proximity)
return `${this._query()}%`;
return "";
}
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
if (this.mode == InfraredSensorMode.RemoteControl) { if (this.mode == InfraredSensorMode.RemoteControl) {
for (let i = 0; i < __remoteButtons.length; ++i) { for (let i = 0; i < __remoteButtons.length; ++i) {

View File

@ -23,14 +23,14 @@ declare interface Image {
/** /**
* Set pixel color * Set pixel color
*/ */
//% shim=ImageMethods::set //% shim=ImageMethods::setPixel
set(x: int32, y: int32, c: int32): void; setPixel(x: int32, y: int32, c: int32): void;
/** /**
* Get a pixel color * Get a pixel color
*/ */
//% shim=ImageMethods::get //% shim=ImageMethods::getPixel
get(x: int32, y: int32): int32; getPixel(x: int32, y: int32): int32;
/** /**
* Fill entire image with a given color * Fill entire image with a given color

View File

@ -5,18 +5,17 @@
//% groups=["0.,","1#*"] //% groups=["0.,","1#*"]
function img(lits: any, ...args: any[]): Image { return null } function img(lits: any, ...args: any[]): Image { return null }
let screen = image.create(DAL.LCD_WIDTH, DAL.LCD_HEIGHT) const screen = image.create(DAL.LCD_WIDTH, DAL.LCD_HEIGHT)
namespace _screen_internal { namespace _screen_internal {
//% shim=pxt::updateScreen //% shim=pxt::updateScreen
function updateScreen(img: Image): void {} function updateScreen(img: Image): void { }
//% shim=pxt::updateStats //% shim=pxt::updateStats
function updateStats(msg: string): void {} function updateStats(msg: string): void { }
control.setupScreenRefresh(() => updateScreen(screen)) control.__screen.setupUpdate(() => updateScreen(screen))
control.EventContext.onStats = function(msg: string) {
export function _stats(msg: string) { updateStats(msg);
updateStats(msg)
} }
} }
@ -78,6 +77,43 @@ namespace brick {
screen.drawImage(image, 0, 0) screen.drawImage(image, 0, 0)
} }
/**
* Display the sensor and motor states attached to ports
*/
//% blockId=brickShowPorts block="show ports"
//% help=brick/show-ports blockGap=8
//% weight=10 group="Screen"
export function showPorts() {
const col = 44;
clearScreen();
function scale(x: number) {
if (Math.abs(x) > 1000) return Math.round(x / 100) / 10 + "k";
return ("" + (x >> 0));
}
// motors
const datas = motors.getAllMotorData();
for (let i = 0; i < datas.length; ++i) {
const data = datas[i];
if (!data.actualSpeed && !data.count) continue;
const x = i * col;
screen.print("ABCD"[i], x, brick.LINE_HEIGHT)
screen.print(`${scale(data.actualSpeed)}%`, x, 2* brick.LINE_HEIGHT)
screen.print(`${scale(data.count)}>`, x, 3 * brick.LINE_HEIGHT)
}
// sensors
const sis = sensors.internal.getActiveSensors();
for (let i = 0; i < sis.length; ++i) {
const si = sis[i];
const x = (si.port() - 1) * col;
const inf = si._info();
screen.print(si.port() + "", x, 8 * brick.LINE_HEIGHT)
screen.print(inf, x, 9 * brick.LINE_HEIGHT)
}
}
/** /**
* An image * An image
* @param image the image * @param image the image
@ -96,7 +132,7 @@ namespace brick {
*/ */
//% blockId=screen_clear_screen block="clear screen" //% blockId=screen_clear_screen block="clear screen"
//% weight=90 group="Screen" //% weight=90 group="Screen"
//% help=brick/clear-screen //% help=brick/clear-screen weight=1
export function clearScreen() { export function clearScreen() {
screen.fill(0) screen.fill(0)
} }

View File

@ -15,6 +15,10 @@ namespace sensors {
return this._readPin6() > 2500 ? 1 : 0 return this._readPin6() > 2500 ? 1 : 0
} }
_info(): string {
return this._query() ? "pres" : "rel";
}
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
this.button._update(curr > 0) this.button._update(curr > 0)
} }

View File

@ -18,6 +18,7 @@ namespace sensors {
super(port) super(port)
this.promixityThreshold = new sensors.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm this.promixityThreshold = new sensors.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm
this.movementThreshold = 1; this.movementThreshold = 1;
this._setMode(0);
} }
_deviceType() { _deviceType() {
@ -28,6 +29,10 @@ namespace sensors {
return ((this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff) / 10) >> 0; // range is 0..2550, in 0.1 cm increments. return ((this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff) / 10) >> 0; // range is 0..2550, in 0.1 cm increments.
} }
_info(): string {
return `${this.distance()}cm`
}
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
// is there an object near? // is there an object near?
this.promixityThreshold.setLevel(curr); this.promixityThreshold.setLevel(curr);
@ -38,7 +43,7 @@ namespace sensors {
} }
/** /**
* Registers code to run when the given color is close * Registers code to run when an object is close or far
* @param handler the code to run when detected * @param handler the code to run when detected
*/ */
//% help=sensors/ultrasonic/on-event //% help=sensors/ultrasonic/on-event

56
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.1.5", "version": "0.1.7",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -3274,19 +3274,19 @@
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
}, },
"pxt-common-packages": { "pxt-common-packages": {
"version": "0.19.4", "version": "0.20.14",
"resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-0.19.4.tgz", "resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-0.20.14.tgz",
"integrity": "sha512-sAccQrTh+LNuuDuQlkeuGaRu99+7iORfiREJV7eemqzr5yuspgA9aLif0FYFIPas37RD8Uoz+n36RxgsKZoLJg==", "integrity": "sha512-DlZIDfDSH5jGq5K4k+9QtALzcedT+lYBNnxUWrbAK/GOxkqXZxhwGGvi1O2p6eFOfCWBuH0kjBlui3dzxeF0LA==",
"requires": { "requires": {
"autoprefixer": "6.7.7", "autoprefixer": "6.7.7",
"pxt-core": "3.4.3", "pxt-core": "3.5.11",
"rtlcss": "2.2.1" "rtlcss": "2.2.1"
} }
}, },
"pxt-core": { "pxt-core": {
"version": "3.4.3", "version": "3.5.11",
"resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-3.4.3.tgz", "resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-3.5.11.tgz",
"integrity": "sha512-zsBf5/pf9B5vS4THqTQLOFodi+o0GtX2npvT3efF6Cql29dXtzVYKUAxSclzGCtNljI34dC++CLaaPfYfzMOnQ==", "integrity": "sha512-niFvx2PbvWqNPikB0uyR22Pnsc7ipOfWsB656KvnenK4lRNUMEFcxUg4B+65+NZZQypEHk5OxsD3nbE62749EA==",
"requires": { "requires": {
"bluebird": "3.5.1", "bluebird": "3.5.1",
"browserify": "13.3.0", "browserify": "13.3.0",
@ -3298,7 +3298,7 @@
"lzma": "2.3.2", "lzma": "2.3.2",
"marked": "0.3.12", "marked": "0.3.12",
"node-hid": "0.5.7", "node-hid": "0.5.7",
"postcss": "6.0.17", "postcss": "6.0.21",
"request": "2.83.0", "request": "2.83.0",
"rimraf": "2.5.4", "rimraf": "2.5.4",
"rtlcss": "2.2.1", "rtlcss": "2.2.1",
@ -3307,21 +3307,21 @@
}, },
"dependencies": { "dependencies": {
"ansi-styles": { "ansi-styles": {
"version": "3.2.0", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": { "requires": {
"color-convert": "1.9.1" "color-convert": "1.9.1"
} }
}, },
"chalk": { "chalk": {
"version": "2.3.1", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
"integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
"requires": { "requires": {
"ansi-styles": "3.2.0", "ansi-styles": "3.2.1",
"escape-string-regexp": "1.0.5", "escape-string-regexp": "1.0.5",
"supports-color": "5.2.0" "supports-color": "5.3.0"
} }
}, },
"has-flag": { "has-flag": {
@ -3330,13 +3330,13 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
}, },
"postcss": { "postcss": {
"version": "6.0.17", "version": "6.0.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.17.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz",
"integrity": "sha512-Bl1nybsSzWYbP8O4gAVD8JIjZIul9hLNOPTGBIlVmZNUnNAGL+W0cpYWzVwfImZOwumct4c1SDvSbncVWKtXUw==", "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==",
"requires": { "requires": {
"chalk": "2.3.1", "chalk": "2.3.2",
"source-map": "0.6.1", "source-map": "0.6.1",
"supports-color": "5.2.0" "supports-color": "5.3.0"
} }
}, },
"source-map": { "source-map": {
@ -3345,9 +3345,9 @@
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}, },
"supports-color": { "supports-color": {
"version": "5.2.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
"integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
"requires": { "requires": {
"has-flag": "3.0.0" "has-flag": "3.0.0"
} }
@ -3710,9 +3710,9 @@
"integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk="
}, },
"semantic-ui-less": { "semantic-ui-less": {
"version": "2.2.12", "version": "2.2.14",
"resolved": "https://registry.npmjs.org/semantic-ui-less/-/semantic-ui-less-2.2.12.tgz", "resolved": "https://registry.npmjs.org/semantic-ui-less/-/semantic-ui-less-2.2.14.tgz",
"integrity": "sha1-0ChpjwgOgc2wv4DlXl5jf8mUNdQ=", "integrity": "sha512-JLkTqjOtct+OwM/JRv0SH76gCC0eE98xp5G4D29e9VbJ66QjWD3nB3waB7drpaMUFXo/YbKcyNOJBgMamcJI0Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"jquery": "3.2.1" "jquery": "3.2.1"

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.1.5", "version": "0.1.7",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -45,7 +45,7 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.20.14", "pxt-common-packages": "0.20.28",
"pxt-core": "3.5.11" "pxt-core": "3.5.11"
}, },
"scripts": { "scripts": {

View File

@ -100,10 +100,18 @@
"selectLanguage": true, "selectLanguage": true,
"highContrast": true, "highContrast": true,
"docMenu": [ "docMenu": [
{
"name": "Support",
"path": "https://service.lego.com"
},
{ {
"name": "About", "name": "About",
"path": "/about" "path": "/about"
}, },
{
"name": "Upgrade Firmware",
"path": "https://ev3manager.education.lego.com/"
},
{ {
"name": "Blocks", "name": "Blocks",
"path": "/blocks" "path": "/blocks"

View File

@ -7,7 +7,7 @@
text-transform: uppercase; text-transform: uppercase;
} }
#mainmenu { #mainmenu, #homemenu {
background: @legoGreyLight; background: @legoGreyLight;
border-bottom: 5px solid #00a5c8; border-bottom: 5px solid #00a5c8;
} }

View File

@ -27,7 +27,7 @@
@orange: #fa7f2a; @orange: #fa7f2a;
@green: @brightYellowishGreen; @green: @brightYellowishGreen;
@legoGreyLight: #F4F1F4; @legoGreyLight: #F2F2F2;
@legoGreyDark: #f4f7f9; @legoGreyDark: #f4f7f9;
@grey: @legoGreyLight; @grey: @legoGreyLight;
@ -131,7 +131,7 @@
@editorToolsBackground: @legoGreyLight; /* #fff;*/ /* #fcfbfa; */ @editorToolsBackground: @legoGreyLight; /* #fff;*/ /* #fcfbfa; */
@blocklySvgColor: #f9f9f9; /*#f2f6f8;*/ /*ecf6fe;*/ @blocklySvgColor: #f9f9f9; /*#f2f6f8;*/ /*ecf6fe;*/
@homeScreenBackground: #EAEEEF; @homeScreenBackground: #F2F2F2;
/*------------------- /*-------------------
Full screen Full screen

View File

@ -7,6 +7,7 @@
@import 'themes/default/collections/menu.variables'; @import 'themes/default/collections/menu.variables';
@import 'fieldeditors'; @import 'fieldeditors';
@import 'target-home';
/* Reference import */ /* Reference import */
@import (reference) "semantic.less"; @import (reference) "semantic.less";

13
theme/target-home.less Normal file
View File

@ -0,0 +1,13 @@
@import (reference) "home.less";
#homemenu {
.left.menu {
margin-left: @carouselArrowSize;
}
.right.menu {
margin-right: @carouselArrowSize;
}
}