Compare commits

...

185 Commits

Author SHA1 Message Date
8fd0bf92fa move electron to v1.1.22 2019-10-07 14:23:34 -07:00
a33bff0520 offline template 2019-10-07 14:22:05 -07:00
7549f865d6 move master to 1.2.22 2019-10-02 13:59:58 -07:00
a5de9d88bb adding latest video 2019-10-02 13:53:22 -07:00
0437df10de 1.2.22 2019-10-02 13:27:53 -07:00
2079173dfa lock execution thread before exiting (#935) 2019-10-02 12:40:45 -07:00
018a1e7528 added proportional line follower 2019-10-02 12:26:51 -07:00
757f95d984 move master to v1.2.21 2019-10-02 10:59:50 -07:00
8bc3fdc8ba 1.2.21 2019-10-01 15:56:22 -07:00
e8a1e73cf5 1.2.20 2019-10-01 14:54:42 -07:00
e9b2b239ad More gyro lessons (#933)
* updated pauseuntil

* updated youtube link

* updated docs
2019-10-01 14:54:17 -07:00
5ad2288a9f updated docs 2019-10-01 13:38:33 -07:00
92d13ef343 updated bluetooth info 2019-10-01 13:36:53 -07:00
471ca5d915 1.2.19 2019-10-01 13:28:01 -07:00
f745079728 Don't reset threashold when resetting color mode (#932)
* don't reset threshold when changing modes

* updated docs
2019-10-01 13:27:37 -07:00
d179f18ef3 added gyro movies 2019-10-01 11:05:44 -07:00
805fc6c787 1.2.18 2019-10-01 10:12:21 -07:00
374bbb8304 Drift-compensated angle in gyro (#931)
* compute angle based on undrifted rate

* add is calibrating function

* fix integrator

* added example

* docs

* poll faster
2019-10-01 10:11:58 -07:00
25452efc92 1.2.17 2019-09-30 22:44:09 -07:00
80b9c715b2 Gyro tutorials (#930)
* gyro tutorials

* tutorials

* fix gyro simulator

* images

* updated image

* fix svg errors
2019-09-30 22:43:50 -07:00
cb816c91ad updated drift 2019-09-30 14:33:57 -07:00
3012068986 1.2.16 2019-09-30 13:44:27 -07:00
4c9c7d6a69 add delay to fix mac deployment (#929) 2019-09-30 13:43:12 -07:00
ad3652c290 bump master to 1.2.15 2019-09-30 13:03:48 -07:00
d8971829e3 1.2.15 2019-09-30 11:13:45 -07:00
8ca4558fc2 web serial cleanup (#928)
* updated ticks

* fix enable and compile

* add debug mode

* don't try to change UI while downloading

* cleanup

* don't double open

* use cu

* add delay before reconnecting

* support for 200 ragne in field turn ratio

* updated docs

* fix docs
2019-09-30 11:13:28 -07:00
d85b5c5129 updated info for macs (#925) 2019-09-30 10:30:21 -07:00
95b1c6a50f 1.2.14 2019-09-29 23:09:07 -07:00
4dc2872286 Better bt download flow (#927)
* round the drif

* restart compile automatically

* add settle
2019-09-29 23:08:46 -07:00
6c9ff804c8 1.2.13 2019-09-29 09:49:35 -07:00
7581b5af9e Drift support (#926)
* upgrading drift support

* updated showports

* typos
2019-09-29 09:49:13 -07:00
07504027f9 1.2.12 2019-09-27 16:46:20 -07:00
a0e133864a background show ports (#924)
* background show ports

* render once at least

* better rendering

* bumped up scale
2019-09-27 16:45:57 -07:00
0285711954 added automation package 2019-09-27 16:08:54 -07:00
91be998d7e 1.2.11 2019-09-27 15:49:43 -07:00
e862869327 Snap backwards (#923)
* snap to multiple of 5

* normalize negative values
2019-09-27 15:49:21 -07:00
8047cb2612 beta notation 2019-09-27 11:45:25 -07:00
8e2ffefd2c adding walkthrough video 2019-09-27 11:43:04 -07:00
092e7b0522 1.2.10 2019-09-27 11:15:29 -07:00
42454ecd57 graceful handling of bluetooth connectivity issues (#922)
* more cleanup

* cleanup life cycle

* more error checking
2019-09-27 11:15:10 -07:00
2563fd6031 move image 2019-09-27 09:36:25 -07:00
e0c1f2dca0 added other issue 2019-09-27 09:25:46 -07:00
c80574ed3f 1.2.9 2019-09-27 09:16:45 -07:00
b28b5cb6b7 better flow + handle unclosed connection (#921)
* better flow + handle unclosed connection

* more checks
2019-09-27 09:16:27 -07:00
d1f11059db updated text 2019-09-27 08:46:50 -07:00
6de5c6afdf added beta note 2019-09-27 06:56:03 -07:00
b72c7c0c4f 1.2.8 2019-09-27 06:54:03 -07:00
352c1ca5ec Experiment BT support using Chrome web serial (#920)
* plumbing

* plumbing

* logging

* more notes

* fixing typing

* more plumbing

* more plumbing

* different baud rate

* talking to the brick

* first over the air drop

* fix buffer

* tweak paraetmers

* formatting fixing double upload

* reduce console.log

* cleanup

* add BLE button to download dialog

* changed label

* recover from broken COM port

* fix function call

* reduce log level

* adding ticks

* some help

* updated support matrix

* more docs

* updated browser help

* more docs

* add link

* add device

* added image
2019-09-27 06:53:26 -07:00
6d940a9ec7 other color snesor tutorial (#919) 2019-09-25 22:35:10 -07:00
c070173346 adding moods 2019-09-25 21:12:45 -07:00
6fcf68f174 fix tutorial 2019-09-25 21:08:44 -07:00
02f2a85d28 added images 2019-09-25 15:16:36 -07:00
f63196908e updated robot 1 2019-09-25 13:20:20 -07:00
ad48ee12ca 1.2.7 2019-09-24 21:45:20 -07:00
83aeb24a98 broadcast project (#918)
* broadcast project

* revert chaanges
2019-09-24 21:44:59 -07:00
fc5ecd9f10 added pause-on-start uttorial 2019-09-24 20:47:29 -07:00
0b3b840ac1 1.2.6 2019-09-17 15:14:32 -07:00
60c09809e7 Stall (#897)
* stall detection

* arrange blocks

* updated blocks

* tested on hw
2019-09-17 15:14:14 -07:00
148067a143 1.2.5 2019-09-17 14:30:20 -07:00
6f34887c94 Safepolling (#915)
* headstart on safe polling

* poke in sensors

* more poking

* typo
2019-09-17 14:30:02 -07:00
64a9930c2e 1.2.4 2019-09-17 12:36:35 -07:00
5815e16647 update pxt reference (#914) 2019-09-17 12:36:11 -07:00
c4f5e425c2 1.2.3 2019-09-17 11:26:52 -07:00
361ae7a2d2 adding a few pause to allow motors to settle 2019-09-17 11:23:40 -07:00
3769402ade 1.2.2 2019-09-17 10:52:14 -07:00
5c3c83eb52 add a run to avoid tight loop hogging (#913) 2019-09-17 10:52:00 -07:00
0f07a89981 updated docs on offline-app 2019-09-11 19:37:26 -07:00
11d887a213 Releaseing offline app version 1.1.20 (#912) 2019-09-11 18:24:47 -07:00
8150b2dbb0 fix turtle link 2019-09-11 13:23:09 -07:00
89f41f23da 1.2.1 2019-09-10 07:13:42 -07:00
6b78e08053 Edits for 'citys shaper' robot tutorials (#911) 2019-09-09 16:59:12 -07:00
186c86d2b1 rev minor version 2019-09-09 09:09:27 -07:00
181c71d2dd 1.1.22 2019-09-09 09:08:50 -07:00
be05da3232 enabled green screen 2019-09-09 09:08:38 -07:00
5958157a76 1.1.21 2019-09-09 09:04:28 -07:00
f72b825377 reenable permanent storage (#909) 2019-09-09 09:04:12 -07:00
d76af5e5af moving turtle 2019-09-08 21:36:04 -07:00
23f48db20b added turtle program 2019-09-08 21:29:27 -07:00
2975bf2b55 Console to dmesg (#910)
* always pip console.log to dmesg

* trim new line

* restore storage

* restore new line

* remove unused variable
2019-09-07 18:22:39 -07:00
5314515619 Crane mission (#907)
* dummy page

* robot 1 lesson

* added lesson 2

* added mission 2

* added link
2019-09-06 16:10:33 -07:00
75b2db9f67 releasing to 1.1.20 (#908) 2019-09-06 14:24:19 -07:00
cf2e39f1b2 renamed tutorial 2019-09-06 08:47:56 -07:00
6d15d69aa1 updated fll page 2019-09-06 08:33:25 -07:00
72a0940235 1.1.20 2019-09-06 06:22:43 -07:00
b08dd8a7d2 Merge branch 'master' of https://github.com/microsoft/pxt-ev3 2019-09-06 06:22:36 -07:00
def648a98b Block updates follow blog post (#905)
* fix battery block comment

* update run phase blocks

* some more docs
2019-09-06 06:22:12 -07:00
32a92789b3 fix battery block comment 2019-09-06 05:23:48 -07:00
9956bb06fb adding wall follower 2019-09-04 21:42:08 -07:00
83b9aecd7a 1.1.19 2019-09-04 14:52:02 -07:00
17ab24eaa9 Ramp (#904)
* updated ramp block

* updated example
2019-09-04 14:51:45 -07:00
9c5d5f9a86 updated block 2019-09-04 13:50:13 -07:00
43a13e0877 added example 2019-09-04 13:42:29 -07:00
fe0915484d 1.1.18 2019-09-04 12:57:17 -07:00
87a65aa38f battery properties (#903)
* Battery params

* move category

* cleanup

* use property

* fix level

* fix battery computation

* fix level comp

* docs
2019-09-04 12:56:45 -07:00
1317da8904 Remove old instructions 2019-09-03 17:34:34 -07:00
62b2881e2a Embed file deleter in PDF file so we can serve it 2019-09-03 16:29:31 -07:00
bf482a2ac9 Do ZIP not UF2 for file manager 2019-09-03 16:11:02 -07:00
243600ad8f Adding file manager program 2019-09-03 16:08:56 -07:00
349caa4aed 1.1.17 2019-09-02 20:58:29 -07:00
56bbcde299 Support for smooth acceleration/deceleration in run (#900)
* removed logging

* removing more logging

* always use step for single/multiple motors

* refactored schedule

* account for accel ramp up and down

* added default acc/decel

* rounding speed/angle

* remove hack

* use acceleration time in run too

* handle missing case

* adding notes on motors

* adding sample

* fixed ramp simulation

* clear defaults

* some docs, more later

* adding basic examples

* remove debug msg

* clean json

* added move schedule

* docs

* basic docs
2019-09-02 20:57:23 -07:00
7e9cc791ec Some edits for the new sensor/motor examples (#901)
* Some edits for the new sensor/motor examples

* article typo

* dark and bright

* fix block styling

* I like 'on'

* more block styling
2019-09-02 04:20:42 -07:00
d5194b8d28 More samples (#896)
* coast or brake

* fix title

* added lesson
2019-08-31 06:05:36 -07:00
12b1eb349b 1.1.16 2019-08-30 16:53:03 -07:00
68dc195ea4 motor tutorials (#895)
* updated pivots

* redirect support to forum

* adding top level FLL link

* updated wording
2019-08-30 16:52:37 -07:00
0251b914f2 color sensor examples (#894)
* tank zigzag

* reflected light measure

* adding links

* added reflected light calibration

* updated summary
2019-08-30 15:03:09 -07:00
1fc818767c added vscode workspace 2019-08-30 13:57:27 -07:00
9aeaec477f updated FLL page 2019-08-30 12:03:43 -07:00
7fc796d2cb 1.1.15 2019-08-30 11:55:49 -07:00
cb1cd2a4b4 Tutorial category breakout (#437)
* Tutorial category breakout

* Put galleries in config

* restore default tutorial

* updated links

* update tutorials pages

* add infrared
2019-08-30 11:54:30 -07:00
39bd7aa0eb 1.1.14 2019-08-30 10:59:15 -07:00
140ba64462 Gyrofix (#893)
* disable drift correction by default

* disable drift correction

* better calibration sequence

* add comments

* updated comment about beta
2019-08-30 10:58:49 -07:00
42fe96aa5a fix link 2019-08-30 09:40:41 -07:00
1a5b42026d adding redirects for missing links 2019-08-30 09:39:28 -07:00
9fe649aa3c fixed extensions.md 2019-08-30 05:48:41 -07:00
a97dfb17b2 1.1.13 2019-08-30 05:41:11 -07:00
277c9903bb Tank fixes (#892)
* fixing turnration computation

* updated tank computation

* fix rendering glitch

* restore tank computation

* rounding errors
2019-08-30 05:40:51 -07:00
0de8a84de2 1.1.12 2019-08-29 13:11:34 -07:00
a302bbfc2b Single tank (#891)
* add note about dual blocks

* fix simulator to match hardware

* updated wording
2019-08-29 13:11:01 -07:00
bcb682b602 1.1.11 2019-08-28 23:00:03 -07:00
e4a7531541 add rgbraw (#890) 2019-08-28 22:59:41 -07:00
348964c888 1.1.10 2019-08-28 22:43:42 -07:00
8b3461bebd Add exitThread() polling the exit button (#888)
* Add exitThread() polling the exit button

* Add missing includes

* Remove redundant code
2019-08-28 22:43:21 -07:00
e511630c2e Update README.md 2019-08-28 16:27:03 -07:00
db156d5df0 Update README.md 2019-08-28 16:24:55 -07:00
93c6975400 1.1.9 2019-08-28 16:21:41 -07:00
abc93dd7da Multi sensor fix (#887)
* more logging

* set uart mode all at once

* updated logging

* pr feedback
2019-08-28 16:21:06 -07:00
85cfc86bf8 1.1.8 2019-08-28 13:36:50 -07:00
b66d4f2d64 enable storage extension (#886)
* enable storage extension

* fix -beta
2019-08-28 13:36:23 -07:00
5843deab11 1.1.7 2019-08-28 11:39:18 -07:00
8d5edc38bb bump common version (#885) 2019-08-28 11:30:59 -07:00
0309e50058 1.1.6 2019-08-28 08:52:24 -07:00
aa40e7b169 Endprogram (#884)
* moving end program logic to c++

* typo

* always stop on reset
2019-08-28 08:52:01 -07:00
75cf8da396 1.1.5 2019-08-27 17:57:44 -07:00
Max
db9b6a995b IIC added (#870)
* IIC added

* Fixed bug with not detecting device
2019-08-27 17:57:21 -07:00
fb255edafe 1.1.4 2019-08-27 17:28:57 -07:00
f4c39f74e8 1.1.3 2019-08-27 17:05:49 -07:00
3e56e2c3e2 Rgb raw tuning of blocs (#883)
* refactor blocks

* make non-private
2019-08-27 17:05:16 -07:00
79b5f8cc88 Add rgb and reflection raw mods for color sensor (#876)
* Add reflection raw value

Add reflection raw value for color sensor

* update

* Combined rgbraw and refraw
2019-08-27 16:45:12 -07:00
312729142f 1.1.2 2019-08-27 16:42:36 -07:00
Max
5bd4aed0e1 Multiple sensors 2 (#877)
* Fixed -1 mode in libs

* Deleted todo
2019-08-27 16:34:55 -07:00
cfaa4ae3ef migrate build to travis 2019-08-27 16:29:18 -07:00
faa839d59f 1.1.1 2019-08-27 16:26:37 -07:00
630687bfce bump to 1.1 2019-08-27 16:26:19 -07:00
2b300a4094 Maximmasterr set settle (#882)
* Added set settle time

* updated blocks
2019-08-27 14:57:28 -07:00
5fb8c0de6e delete package-lock.json 2019-08-27 14:45:25 -07:00
1f65cd59a8 Fixes to "Line Following in Loop" Sample Solutions (#871)
Sample Solutions were wrong for both Methods of Line Following in a Loop
2019-08-27 14:27:20 -07:00
fd75bb61d6 Fix typos in sample programme description (#872)
1500 milliseconds is not one quarter of a second - fixed the text to reflect.
2019-08-06 14:50:19 -07:00
Max
4d2f72575b Fixed multiple sensor bug (#868) 2019-07-15 15:26:25 -07:00
1fe3d3e01a plug in offline page (#836) 2019-03-07 19:40:21 -08:00
0c6e65d828 Updateing Trademark in readme (#834)
* Updateing Trademark in readme

* Removed chat reference
2019-03-04 16:39:23 -08:00
ae9c0603f2 Releasing electron 1.0.11 (#832) 2018-12-06 10:16:17 -08:00
06aeca228a Updating offline-app.html to right version (#833) 2018-12-06 10:15:40 -08:00
31fd4799a5 Hot fix release (v1.0.11) (#831)
* Hot fix release (v1.0.10)
2018-12-04 13:24:06 -08:00
7d8e6891ee 1.0.11 2018-12-04 13:03:59 -08:00
462234b1c0 Re-enable trace from simulator configuration (#830) 2018-12-04 13:03:34 -08:00
dad1bd0cd4 1.0.10 2018-12-03 16:38:08 -08:00
b71bfef418 Call setOutputType with the right arguments (#828)
* Call setOutputType with the right arguments
2018-12-03 16:37:53 -08:00
2e0a34c99b Calibration states (#820)
* color calibration
2018-12-03 16:37:40 -08:00
4133828a10 Update the join up link to the FLL Slack channel (#824) 2018-11-19 19:49:46 -08:00
f0c19bc976 Add LEGO video links to FLL page (#822) 2018-11-12 12:20:37 -08:00
a09b4a083f FLL page changes/add-ons (#821) 2018-11-12 12:02:19 -08:00
15dff9af08 Update fll.md 2018-11-12 07:49:04 -08:00
6fa5c1b688 Update fll.md 2018-11-12 07:47:31 -08:00
d76cea1477 1.0.9 2018-11-06 09:08:51 -08:00
ca09a0a833 Add file delete workaround to 'FLL' page (#816) 2018-11-06 09:08:14 -08:00
fcc864823e Use single sentence 'getting-started' card (#817) 2018-11-05 18:04:42 -08:00
166dc27b93 Add FLL page to SUMMARY (#815) 2018-11-01 17:38:21 -07:00
66e50473c4 FLL info page (#814) 2018-11-01 07:46:43 -07:00
58452e1ca3 Fix for missing CAPS in certain parts of EULA 2018-10-26 09:13:03 -07:00
2b7498ea2d Updating new EULA from legal (#813) 2018-10-26 09:09:11 -07:00
5ab2b97663 Remove titles from videos in homescreen (#812) 2018-10-23 08:44:02 -07:00
ffe0f0fb32 Enable tracing from simulator to appTheme (#810) 2018-10-17 11:33:18 -07:00
f27d13f88e Updating offline docs to new release 1.0.8 (#808) 2018-09-26 16:26:35 -07:00
31067dcef8 enable light toc 2018-09-26 16:13:15 -07:00
123f6c84b2 Release electron for auto update (#807)
This will enable auto update of the packages
2018-09-26 16:11:42 -07:00
c5f07ca67c removing light toc 2018-09-26 15:43:20 -07:00
22fc7dee18 added lighttoc 2018-09-26 15:42:28 -07:00
1f58b649c5 Release of 1.0.8 to live (#806)
Beta->release
2018-09-26 15:41:03 -07:00
fc75fe8e16 fixed video title 2018-09-26 11:31:24 -07:00
b399c37527 adding videos page to home 2018-09-26 11:28:32 -07:00
a054fdd3d3 1.0.8 2018-09-25 16:58:51 -07:00
a239589913 Move back to 4.0.9 2018-09-25 16:58:40 -07:00
98a046237c bump pxt-core to 4.1.1, 2018-09-25 16:56:45 -07:00
eb385ec532 1.0.7 2018-09-25 10:28:59 -07:00
2fdce16685 Update field motors editor to support localized languages (#803)
* Use the value for options, and hardcode localized versions of first dropdown
2018-09-25 10:28:34 -07:00
141 changed files with 4265 additions and 5769 deletions

9
.travis.yml Normal file
View File

@ -0,0 +1,9 @@
language: node_js
node_js:
- "8.9.0"
script:
- "node node_modules/pxt-core/built/pxt.js travis"
sudo: false
cache:
directories:
- node_modules

View File

@ -1,13 +1,8 @@
# LEGO® MINDSTORMS® Education EV3 for Microsoft MakeCode
[![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/)
# LEGO® MINDSTORMS® Education EV3 for Microsoft MakeCode [![Build Status](https://travis-ci.org/microsoft/pxt-ev3.svg?branch=master)](https://travis-ci.org/microsoft/pxt-ev3)
This repo contains the editor target hosted at https://makecode.mindstorms.com
LEGO Auth: https://src.education.lego.com/groups/ev3-makecode (use Google Authenticator)
LEGO Chat: https://chat.internal.education.lego.com/make-code/channels/town-square
## Local Dev setup
## Local setup
These instructions assume familiarity with dev tools and languages.
@ -15,10 +10,6 @@ These instructions assume familiarity with dev tools and languages.
* install Docker; make sure `docker` command is in your `PATH`
* (optional) install [Visual Studio Code](https://code.visualstudio.com/)
In a common folder,
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
* clone https://github.com/Microsoft/pxt-ev3 to ``pxt-ev3`` folder
* go to ``pxt`` and run
@ -26,6 +17,18 @@ In a common folder,
npm install
```
* to run the local server,
```
pxt serve --cloud
```
## Local Dev setup
In the common folder,
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
* go to ``pxt-common-packages`` and run
```
@ -57,12 +60,12 @@ cd libs/core
pxt deploy
```
### Jenkins build
https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/
## License
MIT
## Trademarks
MICROSOFT, the Microsoft Logo, and MAKECODE are registered trademarks of Microsoft Corporation. They can only be used for the purposes described in and in accordance with Microsofts Trademark and Brand guidelines published at https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general.aspx. If the use is not covered in Microsofts published guidelines or you are not sure, please consult your legal counsel or the MakeCode team (makecode@microsoft.com).
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

View File

@ -6,13 +6,13 @@
<a class="item" href="https://makecode.com/privacy" target="_blank" rel="noopener">Privacy &amp; Cookies</a>
<a class="item" href="https://makecode.com/termsofuse" target="_blank" rel="noopener"> Terms Of Use</a>
<a class="item" href="https://makecode.com/trademarks" target="_blank" rel="noopener">Trademarks</a>
<div class="item">© 2018 Microsoft</div>
<div class="item">©2019 Microsoft</div>
</div>
<div class="ui container horizontal small divided link list">
<a class="ui centered item" href="https://makecode.com/" title="Microsoft MakeCode" target="_blank" rel="noopener">Powered by Microsoft MakeCode</a>
</div>
<div class="ui centered container small list">
<p class="item">LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.</p>
<p class="item">@copyrightText@</p>
</div>
</div>
</footer>

View File

@ -4,7 +4,10 @@
* [Troubleshoot](/troubleshoot)
* [EV3 Manager](https://ev3manager.education.lego.com/)
* [Bluetooth](/bluetooth)
* [Forum](https://forum.makecode.com)
* [LEGO Support](https://www.lego.com/service/)
* [FIRST LEGO League](/fll)
## Projects #projects
@ -18,11 +21,14 @@
* [What Animal Am I?](/tutorials/what-animal-am-i)
* [Music Brick](/tutorials/music-brick)
* [Run Motors](/tutorials/run-motors)
* [Tank ZigZag](/tutorials/tank-zigzag)
* [Touch to Run](/tutorials/touch-to-run)
* [Touch Sensor Values](/tutorials/touch-sensor-values)
* [What Color?](/tutorials/what-color)
* [Line Following](/tutorials/line-following)
* [Red Light, Green Light](/tutorials/redlight-greenlight)
* [Reflected Light Measure](/tutorials/reflected-light-measure)
* [Reflected Light Calibration](/tutorials/reflected-light-calibration)
* [Object Near?](/tutorials/object-near)
* [Security Alert](/tutorials/security-alert)

View File

@ -28,7 +28,7 @@ program to a **.uf2** file, which you then copy to the **@drivename@** drive. Th
### ~ hint
Not seeing the **@drivename@** drive? Make sure to upgrade your firmware at https://ev3manager.education.lego.com/. Try these [troubleshooting](/troubleshoot) tips if you still have trouble getting the drive to appear.
**Experimental support** for Bluetooth download is now available. Please read the [Bluetooth](/bluetooth) page for more information.
### ~

62
docs/bluetooth.md Normal file
View File

@ -0,0 +1,62 @@
# Bluetooth
This page describes the procedure to download MakeCode program to the EV3 brick
over Bluetooth.
## ~ hint
### WARNING: EXPERIMENTAL FEATURES AHEAD!
Support for Bluetooth download relies on [Web Serial](https://wicg.github.io/serial/),
an experimental browser feature. Web Serial is a work [in progress](https://www.chromestatus.com/feature/6577673212002304);
it may change or be removed in future versions without notice.
By enabling these experimental browser features, you could lose browser data or compromise your device security
or privacy.
## ~
https://youtu.be/VIq8-6Egtqs
## Supported browsers
* Chrome desktop, version 77 and higher, Windows 10 or Mac OS.
* [Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
To make sure your browser is up to date, go to the '...' menu, click "Help" then "About".
Next you need to enable the experimental features (this may change in the future)
* go to **chrome://flags/#enable-experimental-web-platform-features** and **enable**
**Experimental Web Platform features**
![A screenshot of the flags page in chrome](/static/bluetooth/experimental.png)
## Machine Setup
* pair your EV3 brick with your computer over Bluetooth. This is the usual pairing procedure.
## Download over Bluetooth
* go to https://makecode.mindstorms.com/
* click on **Download** to start a file download as usual
* on the download dialog, you should see a **Bluetooth** button. Click on the
**Bluetooth** button to enable the mode.
* **make sure the EV3 brick is not running a program**
* click on **Download** again to download over bluetooth.
## Choosing the correct serial port
Unfortunately, the browser dialog does not make it easy to select which serial port is the brick.
* On Windows, choose ``Standard Serial over Bluetooth``. There might be multiple of those but only one works. Try your luck! Once you know the COM port number, remember it for the next time around.
* On Mac OS, choose ``cu.BRICKNAME-SerialPort``
## Known issues
* We do not detect properly that the program is running on the brick. Make sure to stop the program before starting the download procedure.
* The list of programs on the brick screen is not updated when uploading via bluetooth.
## Feedback
Please send us your feedback through https://forum.makecode.com.

View File

@ -190,12 +190,10 @@ if (true) {
```blocks
forever(function () {
while (true) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Black)
while (sensors.color3.color() == ColorSensorColor.Black) {
motors.largeBC.steer(-30, 50)
}
while (true) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.White)
while (sensors.color3.color() == ColorSensorColor.White) {
motors.largeBC.steer(30, 50)
}
})
@ -209,11 +207,9 @@ Else the Color Sensor detects the color white, start motors ``B`` and ``C`` (dri
```blocks
forever(function () {
if (true) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Black)
if (sensors.color3.color() == ColorSensorColor.Black) {
motors.largeBC.steer(-30, 50)
} else {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.White)
motors.largeBC.steer(30, 50)
}
})

View File

@ -101,9 +101,9 @@ The blocks inside the ``||loops:forever||`` loop have these actions:
1. Turn on the ``green`` EV3 Brick Status Light.
2. Wait for Ultrasonic Sensor to detect an object.
3. Turn on Motors ``A`` and ``D`` in opposite directions.
4. Wait for one quarter of a second (``1500`` milli seconds).
4. Wait for one and a half seconds (``1500`` milli seconds).
5. Reverse the direction of Motors ``A`` and ``D``.
6. Wait for one quarter of a second.
6. Wait for one and a half seconds.
7. Stop all motors.
8. Make an insect chirping sound.
9. Loop continuously so that the insect wanders around when the Ultrasonic Sensor is detects something.

View File

@ -212,6 +212,12 @@ Here are some fun programs for your @boardname@!
"description": "Keep your brick entertained and happy",
"url":"/examples/happy-unhappy",
"cardType": "example"
}, {
{
"name": "Turtle",
"description": "Encode moves and run them on a driving base",
"url":"/examples/turtle",
"cardType": "example"
}, {
"name": "Distance Measurer",
"description": "Use a motor to measure angle and distance",

18
docs/extensions.md Normal file
View File

@ -0,0 +1,18 @@
# Extensions
## #gallery
## Using Extensions
In the web editor, click on ``Settings`` then ``Extensions`` to search and add extensions to the project.
The Blocks and JavaScript definitions will be automatically loaded in the editor.
## Custom extensions
The [Build Your Own Extension](https://makecode.com/extensions/getting-started) manual is for advanced users who want to publish their own extension.
## ~ hint
**Extensions** were previously called **Packages** in MakeCode.
## ~

BIN
docs/file-manager.pdf Normal file

Binary file not shown.

116
docs/fll.md Normal file
View File

@ -0,0 +1,116 @@
# MakeCode for _FIRST_ LEGO League
![FIRST LEGO League logo](/static/fll/fll-logo.png)
**For teams participating in City Shaper challenge**, you can use MakeCode for your challenge (see [City Shaper Challenge, page 7 bottom](https://firstinspiresst01.blob.core.windows.net/fll/2020/city-shaper-game-guide-pdf.pdf)!
Weve compiled a list of resources and information that we hope will be helpful for you.
* **Got a question? Post it on the forums** at https://forum.makecode.com/
## FAQ
### I found a bug what do I do?
If you found a bug, please try if it hasn't been fixed yet! Go to https://makecode.mindstorms.com/beta and try if the bug is corrected. Otherwise, please tell us at https://forum.makecode.com/.
### How do I use MakeCode with my EV3?
* You will need to install the latest EV3 firmware on your brick. Instructions on how to do that are located here: https://makecode.mindstorms.com/troubleshoot.
* You will need a computer with a USB port to connect to the EV3 in order to download your programs.
* You will need internet access and a browser on your computer to get to https://makecode.mindstorms.com.
* You can [install the app](/offline-app) to use the editor offline.
### I know LabView, how is MakeCode different?
We have compiled a guide for EV3 LabView users at https://makecode.mindstorms.com/labview.
### Whats the best way to get started with MakeCode?
Go to https://makecode.mindstorms.com. The home screen is filled with videos, tutorials and examples that might be relevant for your missions.
On the home page, scroll down to the **FLL / City Shaper** section for specific lessons related to Mission 2.
### Can I load both LEGO MINDSTORMS EV3 Software and MakeCode programs onto my EV3?
Yes.
### Does it work without internet?
No, the editor is cached in your browser cache. However, you can also download the [offline app](/offline-app) in case you need to install it on a computer.
### How do I figure out what a block does?
You can right-click on any block and select “Help” in the context menu to open the documentation page describing what that block does.
![Select help in context menu for block](/static/fll/context-help.jpg)
### How do I program in JavaScript?
Click the **JavaScript** button at the top of the page to get to the JavaScript editor. Students can drag and drop code snippets from the Toolbox on the left, or type directly in the editor. You can switch back and forth between **Blocks** and **JavaScript** as you program.
![Coding in JavaScript](/static/fll/code-js.gif)
Also, watch the [Text-based Coding](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=3513a83b87fe536b2dc512237465fd1b&source=embed&photo%5fid=35719471) video for more about coding using the JavaScript editor.
### How do I use the Simulator?
The Simulator will show the physical representation of your code blocks. For example, based on this code snippet, the Simulator will show the touch sensor on Port 1, and a large motor on Port D.
```blocks
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
motors.largeD.run(50)
})
```
![Simulator demonstration](/static/fll/simulator.gif)
Note that the Simulator is also interactive, so you can simulate inputs with any of the sensors.
See the video [Block-based Coding and Simulation](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=629730c938e452f0fd7653fbc4708166&source=embed&photo%5fid=35719470) for more about using the simulator.
### How do I save my programs?
MakeCode will automatically save your recent projects in the browser. However, you can also save a copy of your project as a file on your computer:
* From the **Settings** menu, select **Save Project**
* This will download your program from the browser as a _lego-myproject.uf2_ file
![Save project menu selection](/static/fll/save-project.jpg)
* You can import your saved projects by clicking the Import button on the Home Page
![Import button on home screen](/static/fll/import-button.jpg)
### How do I share my programs?
You can share your projects by clicking on the **share** button in the top left of the screen. This will create a URL which you can send others to open and view your project.
![Share button in editor](/static/fll/share-button.jpg)
![Share button and dialogs demo](/static/fll/share-program.gif)
Sharing programs is also shown in the [Tips and Tricks](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5c594c2373367f7870196f519f3bfc7a&source=embed&photo%5fid=35719472) video.
### Can I use Bluetooth to transfer my program?
The official answer is currently no. That being said, we have **Experimental support** for Bluetooth download. Please read the [Bluetooth](/bluetooth) page for more information.
https://youtu.be/VIq8-6Egtqs
### Why can't I delete my program (*.uf2) files from the Brick?
There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet.
We have prepared a special program that lets you delete UF2 files from the brick.
Download [these PDF instructions](/file-manager.pdf) and drop the PDF on the brick drive.
This will present you with an menu for deleting files.
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.
## Workarounds
1. Deleting Programs from the EV3 brick
>* Description: Unable to delete program files from the EV3 brick after downloading them
>* Status: LEGO Education team is working on a fix, no estimated date yet

View File

@ -7,7 +7,7 @@
{
"name": "Prepare",
"imageUrl": "/static/lessons/firmware.png",
"description": "To use Microsoft MakeCode with your EV3 Brick, you will need to install the latest LEGO® MINDSTORMS® Education EV3 firmware. Follow these steps to make sure you're up to date and install the latest firmware if you need to.",
"description": "To use Microsoft MakeCode with your EV3 Brick, you will need to install the latest LEGO® MINDSTORMS® Education EV3 firmware.",
"label": "New? Start Here!",
"labelClass": "red ribbon large",
"url": "https://makecode.mindstorms.com/troubleshoot"
@ -25,6 +25,12 @@
"description": "Build a robot and drive into the world of robotics!",
"url": "/getting-started/use",
"cardType": "side"
},
{
"name": "First LEGO League",
"imageUrl": "/static/fll/fll-big.png",
"description": "Information about using MakeCode in FLL competitions",
"url": "/fll"
}
]
```

View File

@ -1,3 +1,3 @@
{
"appref": "v0.4.2"
"appref": "v1.2.22"
}

View File

@ -61,6 +61,12 @@ motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations);
motors.largeBC.stop();
```
### ~ hint
The **turn ratio range is -200, 200** unlike LabView who used -100,100.
### ~
## Tank
The **tank** blocks control the speed of two motors. These are commonly used for a differential drive robot. The blocks can also specify the duration, angle, or number of rotations.

View File

@ -3,11 +3,20 @@
<head>
<meta charset="UTF-8">
<title>LEGO® MINDSTORMS® Education EV3 Offline App</title>
<meta name="Description" content="A MakeCode for LEGO® MINDSTORMS® Education EV3 offline app" />
<title>@name@ Offline App</title>
<meta name="Description" content="A MakeCode for @name@ offline app" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- @include indexhead.html -->
<link rel="stylesheet" data-rtl="/blb/rtlsemantic.css" href="/doccdn/semantic.css" />
<link rel="stylesheet" href="/docfiles/style.css" />
<link rel="stylesheet" href="/docfiles/target.css" />
<script src="/doccdn/jquery.js" type="text/javascript"></script>
<script src="/doccdn/semantic.js" type="text/javascript"></script>
<script src="/docfiles/target.js" type="text/javascript"></script>
<style>
@targetstyle@
</style>
<style>
p.item {
color: rgba(0, 0, 0, 0.4);
@ -55,6 +64,10 @@
background-color: rgb(250, 250, 250);
}
#legal-segment {
background:white;
}
@media only screen and (max-width: 800px) {
.grid .column .image {
display: none;
@ -368,34 +381,61 @@
</style>
<script>
$(document).ready(function () {
tickEvent = function (id, data) {
if (!pxt.aiTrackEvent) return;
if (!data) pxt.aiTrackEvent(id);
else {
var props = {};
var measures = {};
for (var k in data)
if (typeof data[k] == "string") props[k] = data[k];
else measures[k] = data[k];
pxt.aiTrackEvent(id, props, measures);
}
var electronLatestVersion = "";
function tickEvent(id, data) {
if (!pxt.aiTrackEvent) return;
if (!data) pxt.aiTrackEvent(id);
else {
var props = {};
var measures = {};
for (var k in data)
if (typeof data[k] == "string") props[k] = data[k];
else measures[k] = data[k];
pxt.aiTrackEvent(id, props, measures);
}
});
}
function agreeCheckboxChanged() {
var downloadSegment = document.getElementById("download-segment");
downloadSegment.classList.toggle("hidden");
showDownloads();
}
function showAgree() {
$("#agree-segment").removeClass("hidden");
$("#read-segment").removeClass("hidden");
$("#legal-segment").removeClass("hidden");
}
function showNoDownloads() {
$("#no-download-segment").removeClass("hidden");
$("#read-segment").addClass("hidden");
$("#legal-segment").addClass("hidden");
}
function showDownloads() {
$("#download-win64").attr("href", "https://makecode.com/api/release/@targetid@/" + electronLatestVersion + "/win64");
$("#download-mac64").attr("href", "https://makecode.com/api/release/@targetid@/" + electronLatestVersion + "/mac64");
$("#download-segment").removeClass("hidden");
}
function downloadWin64() {
// TODO: Keep this link up-to-date with the desired release version
window.open("https://makecode.com/api/release/ev3/v0.4.2/win64");
tickEvent("offlineapp.download", { "target": "ev3", "platform": "win64" });
tickEvent("offlineapp.download", { "target": "@targetid@", "platform": "win64" });
}
function downloadMac64() {
// TODO: Keep this link up-to-date with the desired release version
window.open("https://makecode.com/api/release/ev3/v0.4.2/mac64");
tickEvent("offlineapp.download", { "target": "ev3", "platform": "mac64" });
tickEvent("offlineapp.download", { "target": "@targetid@", "platform": "mac64" });
}
$(function () {
$.getJSON("https://makecode.com/api/config/@targetid@/targetconfig")
.then(function (data) {
if (data && data.electronManifest && data.electronManifest.latest) {
electronLatestVersion = data.electronManifest.latest;
showAgree();
} else {
showNoDownloads();
}
})
.catch(function () {
showNoDownloads();
})
});
</script>
</head>
@ -406,35 +446,39 @@
<div class="ui grid topbar">
<div class="three wide column">
<img class="ui small image left" src="/static//lego_education_logo_white.png" />
<img class="ui small image left" src="@cardLogo@" />
</div>
<div class="ten wide column">
<h1 class="ui inverted welcomeheader">MakeCode Offline App</h1>
<h1 class="ui inverted welcomeheader">@name@ Offline App</h1>
</div>
<div class="three wide column">
<img class="ui small image right" src="/static//Microsoft-logo_rgb_c-white.png" />
<img class="ui small image right" src="/static/Microsoft-logo_rgb_c-white.png" />
</div>
</div>
<div class="ui compact segments terms-container">
<div class="ui secondary center aligned segment">
<div id="segments" class="ui compact segments terms-container">
<div id="read-segment" class="ui secondary center aligned segment hidden">
Please read and accept the following terms to download the app.
</div>
<div class="ui left aligned segment terms">
<div id="legal-segment" class="ui left aligned segment terms hidden">
<div id="loader" class="ui active loader"></div>
<div class="c17">
<p class="c11">
<span class="c4 c1">MICROSOFT PRE-RELEASE SOFTWARE LICENSE TERMS</span>
</p>
<p class="c11">
<span class="c4 c1">MICROSOFT MAKECODE FOR LEGO MINDSTORMS EDUCATION EV3</span>
<span class="c4 c1">MICROSOFT MAKECODE SOFTWARE FOR @name@</span>
</p>
<p class="c7">
<span class="c4 c1"></span>
</p>
<p class="c11">
<span class="c3 c1">These license terms are an agreement between Microsoft Corporation (or based on where you live, one
of its affiliates) and you. They apply to the software named above. The terms also apply to any
Microsoft services or updates for the software, except to the extent those have additional terms.</span>
<span class="c3 c1">These license terms are an agreement between Microsoft Corporation (or based
on where you live, one
of its affiliates) and you. They apply to the software named above. The terms also apply to
any
Microsoft services or updates for the software, except to the extent those have additional
terms.</span>
</p>
<p class="c7">
<span class="c3 c1"></span>
@ -446,43 +490,47 @@
<span class="c5 c1">1.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">INSTALLATION AND USE RIGHTS. </span>
<span class="c3 c1">You may install and use any number of copies of the software to evaluate it as you develop and test
your software applications for use with Lego Mindstorms Education EV3 hardware.</span>
<span class="c3 c1">You may install and use any number of copies of the software to evaluate it
as you develop and test
your software applications for use with @name@ hardware.</span>
</p>
<p class="c2">
<span class="c5 c1">2.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">PRE-RELEASE SOFTWARE. </span>
<span class="c3 c1">The software is a pre-release version. It may not work the way a final version of the software will.
Microsoft may change it for the final, commercial version. We also may not release a commercial
version. Microsoft is not obligated to provide maintenance, technical support or updates to you
<span class="c3 c1">The software is a pre-release version. It may not work the way a final
version of the software will.
Microsoft may change it for the final, commercial version. We also may not release a
commercial
version. Microsoft is not obligated to provide maintenance, technical support or updates to
you
for the software.</span>
</p>
<p class="c2">
<span class="c5 c1">3.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">Associated Online Services.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some features of the software may provide access
to, or rely on, Azure online services, including an associated Azure online service to the software
currently in development (the &ldquo;corresponding service&rdquo;). The use of those services
(but not the software) is governed by the separate terms and privacy policies in the agreement
under which you obtained the Azure services at</span>
<span class="c1">
<a class="c9" href="https://www.google.com/url?q=https://go.microsoft.com/fwLink/p/?LinkID%3D233178&amp;sa=D&amp;ust=1529596153826000">&nbsp;</a>
<span class="c5 c1">ASSOCIATED ONLINE SERVICES.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Some features of the software
provide access
to, or rely on, online services to provide you information about updates to the software or
extensions,
or to enable you to retrieve content, collaborate with others, or otherwise supplement your
development
experience. As used throughout these license terms, the term <q>software</q> includes these
online
services and features. By using these online services and features you consent to the to the
transmission of information as described in Section 5, DATA.
</span>
<span class="c1 c18">
<a class="c9" href="https://www.google.com/url?q=https://go.microsoft.com/fwLink/p/?LinkID%3D233178&amp;sa=D&amp;ust=1529596153826000">https://go.microsoft.com/fwLink/p/?LinkID=233178</a>
</span>
<span class="c3 c1">&nbsp;(and, with respect to the corresponding service, the additional terms below). Please read them.
The services may not be available in all regions.</span>
</p>
<p class="c2">
<span class="c5 c1">4.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">Licenses for other components.</span>
<span class="c3 c1">&nbsp;The software may include third party components with separate legal notices or governed by
<span class="c5 c1">LICENSES FOR OTHER COMPONENTS.</span>
<span class="c3 c1">&nbsp;The software may include third party components with separate legal
notices or governed by
other agreements, as described in the ThirdPartyNotices file accompanying the software. Even
if such components are governed by other agreements, the disclaimers and the limitations on and
if such components are governed by other agreements, the disclaimers and the limitations on
and
exclusions of damages below also apply.</span>
</p>
<p class="c2">
@ -494,26 +542,35 @@
<span class="c5 c1">a.</span>
<span class="c1">&nbsp; &nbsp;</span>
<span class="c1 c5">Data Collection. </span>
<span class="c1">The software may collect information about you and your use of the software, and send that to Microsoft.
Microsoft may use this information to provide services and improve our products and services.
You may opt out of many of these scenarios, but not all, as described in the product documentation.
In using the software, you must comply with applicable law. You can learn more about data collection
<span class="c1">The software may collect information about you and your use of the software,
and send that to Microsoft.
Microsoft may use this information to provide services and improve our products and
services.
You may opt out of many of these scenarios, but not all, as described in the product
documentation.
In using the software, you must comply with applicable law. You can learn more about data
collection
and use in the help documentation and the privacy statement at </span>
<span class="c14 c1">
<a class="c9" href="https://www.google.com/url?q=http://go.microsoft.com/fwlink/?LinkId%3D398505&amp;sa=D&amp;ust=1529596153827000">http://go.microsoft.com/fwlink/?LinkId=398505</a>
<a class="c9"
href="http://go.microsoft.com/fwlink/?LinkId=398505">http://go.microsoft.com/fwlink/?LinkId=398505</a>
</span>
<span class="c1">.</span>
<span class="c3 c1">&nbsp;Your use of the software operates as your consent to these practices.</span>
<span class="c3 c1">&nbsp;Your use of the software operates as your consent to these
practices.</span>
</p>
<p class="c8">
<span class="c5 c1">b.</span>
<span class="c1">&nbsp; &nbsp;</span>
<span class="c5 c1">Processing of Personal Data. </span>
<span class="c1">To the extent Microsoft is a processor or subprocessor of personal data in connection with the software,
Microsoft makes the commitments in the European Union General Data Protection Regulation Terms
<span class="c1">To the extent Microsoft is a processor or subprocessor of personal data in
connection with the software,
Microsoft makes the commitments in the European Union General Data Protection Regulation
Terms
of the Online Services Terms to all customers effective May 25, 2018, at </span>
<span class="c1 c14">
<a class="c9" href="https://www.google.com/url?q=http://go.microsoft.com/?linkid%3D9840733&amp;sa=D&amp;ust=1529596153828000">http://go.microsoft.com/?linkid=9840733</a>
<a class="c9"
href="http://go.microsoft.com/?linkid=9840733">http://go.microsoft.com/?linkid=9840733</a>
</span>
<span class="c3 c1">.</span>
</p>
@ -521,48 +578,62 @@
<span class="c5 c1">6.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">FEEDBACK. </span>
<span class="c3 c1">If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the
<span class="c3 c1">If you give feedback about the software to Microsoft, you give to Microsoft,
without charge, the
right to use, share and commercialize your feedback in any way and for any purpose. You will
not give feedback that is subject to a license that requires Microsoft to license its software
or documentation to third parties because we include your feedback in them. These rights survive
not give feedback that is subject to a license that requires Microsoft to license its
software
or documentation to third parties because we include your feedback in them. These rights
survive
this agreement.</span>
</p>
<p class="c2">
<span class="c5 c1">7.</span>
<span class="c1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">SCOPE OF LICENSE.</span>
<span class="c3 c1">&nbsp;The software is licensed, not sold. This agreement only gives you some rights to use the software.
Microsoft reserves all other rights. Unless applicable law gives you more rights despite this
<span class="c3 c1">&nbsp;The software is licensed, not sold. This agreement only gives you some
rights to use the software.
Microsoft reserves all other rights. Unless applicable law gives you more rights despite
this
limitation, you may use the software only as expressly permitted in this agreement. &nbsp;In
doing so, you must comply with any technical limitations in the software that only allow you
to use it in certain ways. You may not:</span>
</p>
<p class="c8">
<span class="c3 c1">- &nbsp; &nbsp; work around any technical limitations in the software;</span>
<span class="c3 c1">- &nbsp; &nbsp; work around any technical limitations in the
software;</span>
</p>
<p class="c8">
<span class="c3 c1">- &nbsp; &nbsp; reverse engineer, decompile or disassemble the software, or attempt to do so, except
<span class="c3 c1">- &nbsp; &nbsp; reverse engineer, decompile or disassemble the software, or
attempt to do so, except
and only to the extent required by third party licensing terms governing use of certain open
source components that may be included with the software;</span>
</p>
<p class="c8">
<span class="c3 c1">- &nbsp; &nbsp; remove, minimize, block or modify any notices of Microsoft or its suppliers in the
<span class="c3 c1">- &nbsp; &nbsp; remove, minimize, block or modify any notices of Microsoft
or its suppliers in the
software;
</span>
</p>
<p class="c8">
<span class="c3 c1">- &nbsp; &nbsp; use the software in any way that is against the law; or</span>
<span class="c3 c1">- &nbsp; &nbsp; use the software in any way that is against the law;
or</span>
</p>
<p class="c8">
<span class="c3 c1">- &nbsp; &nbsp; share, publish, rent or lease the software, or provide the software as a stand-alone
<span class="c3 c1">- &nbsp; &nbsp; share, publish, rent or lease the software, or provide the
software as a stand-alone
offering for others to use.</span>
</p>
<p class="c2">
<span class="c5 c1">8. &nbsp; UPDATES. </span>
<span class="c3 c1">The software may periodically check for updates and download and install them for you. You may obtain
updates only from Microsoft or authorized sources. Microsoft may need to update your system to
provide you with updates. You agree to receive these automatic updates without any additional
notice. Updates may not include or support all existing software features, services, or peripheral
<span class="c3 c1">The software may periodically check for updates and download and install
them for you. You may obtain
updates only from Microsoft or authorized sources. Microsoft may need to update your system
to
provide you with updates. You agree to receive these automatic updates without any
additional
notice. Updates may not include or support all existing software features, services, or
peripheral
devices.
</span>
</p>
@ -570,57 +641,74 @@
<span class="c5 c1">9.</span>
<span class="c1">&nbsp; &nbsp;</span>
<span class="c5 c1">EXPORT RESTRICTIONS.</span>
<span class="c3 c1">&nbsp;You must comply with all domestic and international export laws and regulations that apply
to the software, which include restrictions on destinations, end users and end use. For further
<span class="c3 c1">&nbsp;You must comply with all domestic and international export laws and
regulations that apply
to the software, which include restrictions on destinations, end users and end use. For
further
information on export restrictions, visit (aka.ms/exporting).</span>
</p>
<p class="c2">
<span class="c5 c1">10.</span>
<span class="c1">&nbsp;</span>
<span class="c5 c1">SUPPORT SERVICES. </span>
<span class="c3 c1">Because the software is &ldquo;as is,&rdquo; we may not provide support services for it.</span>
<span class="c3 c1">Because the software is &ldquo;as is,&rdquo; we may not provide support
services for it.</span>
</p>
<p class="c2">
<span class="c5 c1">11.</span>
<span class="c1">&nbsp;</span>
<span class="c5 c1">ENTIRE AGREEMENT.</span>
<span class="c3 c1">&nbsp;This agreement, and the terms for supplements, updates, Internet-based services and support
services that you use, are the entire agreement for the software and support services.</span>
<span class="c3 c1">&nbsp;This agreement, and the terms for supplements, updates, Internet-based
services and support
services that you use, are the entire agreement for the software and support
services.</span>
</p>
<p class="c2">
<span class="c5 c1">12.</span>
<span class="c1">&nbsp;</span>
<span class="c5 c1">APPLICABLE LAW. </span>
<span class="c3 c1">If you acquired the software in the United States, Washington State law applies to interpretation
of and claims for breach of this agreement, and the laws of the state where you live apply to
<span class="c3 c1">If you acquired the software in the United States, Washington State law
applies to interpretation
of and claims for breach of this agreement, and the laws of the state where you live apply
to
all other claims. If you acquired the software in any other country, its laws apply.</span>
</p>
<p class="c2">
<span class="c5 c1">13.</span>
<span class="c1">&nbsp;</span>
<span class="c5 c1">CONSUMER RIGHTS; REGIONAL VARIATIONS. </span>
<span class="c3 c1">This agreement describes certain legal rights. You may have other rights, including consumer rights,
under the laws of your state or country. Separate and apart from your relationship with Microsoft,
you may also have rights with respect to the party from which you acquired the software. This
agreement does not change those other rights if the laws of your state or country do not permit
it to do so. For example, if you acquired the software in one of the below regions, or mandatory
<span class="c3 c1">This agreement describes certain legal rights. You may have other rights,
including consumer rights,
under the laws of your state or country. Separate and apart from your relationship with
Microsoft,
you may also have rights with respect to the party from which you acquired the software.
This
agreement does not change those other rights if the laws of your state or country do not
permit
it to do so. For example, if you acquired the software in one of the below regions, or
mandatory
country law applies, then the following provisions apply to you:</span>
</p>
<p class="c8">
<span class="c5 c1">a.</span>
<span class="c1">&nbsp; &nbsp;</span>
<span class="c5 c1">Australia. </span>
<span class="c3 c1">You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is
<span class="c3 c1">You have statutory guarantees under the Australian Consumer Law and nothing
in this agreement is
intended to affect those rights.</span>
</p>
<p class="c8">
<span class="c5 c1">b.</span>
<span class="c1">&nbsp; &nbsp;</span>
<span class="c5 c1">Canada. </span>
<span class="c3 c1">If you acquired the software in Canada, you may stop receiving updates by turning off the automatic
update feature, disconnecting your device from the Internet (if and when you re-connect to the
Internet, however, the software will resume checking for and installing updates), or uninstalling
the software. The product documentation, if any, may also specify how to turn off updates for
<span class="c3 c1">If you acquired the software in Canada, you may stop receiving updates by
turning off the automatic
update feature, disconnecting your device from the Internet (if and when you re-connect to
the
Internet, however, the software will resume checking for and installing updates), or
uninstalling
the software. The product documentation, if any, may also specify how to turn off updates
for
your specific device or software.</span>
</p>
<p class="c8">
@ -633,8 +721,10 @@
<span class="c5 c1">(i)</span>
<span class="c1">&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">Warranty</span>
<span class="c3 c1">. The properly licensed software will perform substantially as described in any Microsoft materials
that accompany the software. However, Microsoft gives no contractual guarantee in relation to
<span class="c3 c1">. The properly licensed software will perform substantially as described in
any Microsoft materials
that accompany the software. However, Microsoft gives no contractual guarantee in relation
to
the licensed software.</span>
</p>
<p class="c6">
@ -644,74 +734,103 @@
<span class="c5 c1">(ii)</span>
<span class="c1">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span class="c5 c1">Limitation of Liability</span>
<span class="c3 c1">. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as
well as, in case of death or personal or physical injury, Microsoft is liable according to the
<span class="c3 c1">. In case of intentional conduct, gross negligence, claims based on the
Product Liability Act, as
well as, in case of death or personal or physical injury, Microsoft is liable according to
the
statutory law.</span>
</p>
<p class="c10">
<span class="c3 c1">Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft
is in breach of such material contractual obligations, the fulfillment of which facilitate the
due performance of this agreement, the breach of which would endanger the purpose of this agreement
and the compliance with which a party may constantly trust in (so-called &quot;cardinal obligations&quot;).
In other cases of slight negligence, Microsoft will not be liable for slight negligence.</span>
<span class="c3 c1">Subject to the foregoing clause (ii), Microsoft will only be liable for
slight negligence if Microsoft
is in breach of such material contractual obligations, the fulfillment of which facilitate
the
due performance of this agreement, the breach of which would endanger the purpose of this
agreement
and the compliance with which a party may constantly trust in (so-called &quot;cardinal
obligations&quot;).
In other cases of slight negligence, Microsoft will not be liable for slight
negligence.</span>
</p>
<p class="c2">
<span class="c5 c1">14.</span>
<span class="c1">&nbsp;</span>
<span class="c5 c1">LEGAL EFFECT.</span>
<span class="c3 c1">&nbsp;This agreement describes certain legal rights. You may have other rights under the laws of
your country. You may also have rights with respect to the party from whom you acquired the software.
This agreement does not change your rights under the laws of your country if the laws of your
<span class="c3 c1">&nbsp;This agreement describes certain legal rights. You may have other
rights under the laws of
your country. You may also have rights with respect to the party from whom you acquired the
software.
This agreement does not change your rights under the laws of your country if the laws of
your
country do not permit it to do so.</span>
</p>
<p class="c2">
<span class="c5 c1">15.</span>
<span class="c1">&nbsp;</span>
<span class="c4 c1">DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED &ldquo;AS-IS.&rdquo; &nbsp;YOU BEAR THE RISK OF
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED
<span class="c4 c1">DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED &ldquo;AS-IS.&rdquo;
&nbsp;YOU BEAR THE RISK OF
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT
PERMITTED
UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.</span>
</p>
<p class="c2">
<span class="c5 c1">16.</span>
<span class="c1">&nbsp;</span>
<span class="c4 c1">LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT
DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST
<span class="c4 c1">LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND
ITS SUPPLIERS ONLY DIRECT
DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL,
LOST
PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.</span>
</p>
<p class="c0">
<span class="c3 c1">This limitation applies to (a) anything related to the software, services, content (including code)
on third party Internet sites, or third party programs; and (b) claims for breach of contract,
breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the
<span class="c3 c1">This limitation applies to (a) anything related to the software, services,
content (including code)
on third party Internet sites, or third party programs; and (b) claims for breach of
contract,
breach of warranty, guarantee or condition, strict liability, negligence, or other tort to
the
extent permitted by applicable law.</span>
</p>
<p class="c0">
<span class="c3 c1">It also applies even if Microsoft knew or should have known about the possibility of the damages.
The above limitation or exclusion may not apply to you because your country may not allow the
<span class="c3 c1">It also applies even if Microsoft knew or should have known about the
possibility of the damages.
The above limitation or exclusion may not apply to you because your country may not allow
the
exclusion or limitation of incidental, consequential or other damages.</span>
</p>
<p class="c12">
<span class="c4 c1">Please note: As the software is distributed in Quebec, Canada, some of the clauses in this agreement
<span class="c4 c1">Please note: As the software is distributed in Quebec, Canada, some of the
clauses in this agreement
are provided below in French.</span>
</p>
<p class="c12">
<span class="c4 c1">Remarque : Ce logiciel &eacute;tant distribu&eacute; au Qu&eacute;bec, Canada, certaines des clauses
<span class="c4 c1">Remarque : Ce logiciel &eacute;tant distribu&eacute; au Qu&eacute;bec,
Canada, certaines des clauses
dans ce contrat sont fournies ci-dessous en fran&ccedil;ais.</span>
</p>
<p class="c11">
<span class="c5 c1">EXON&Eacute;RATION DE GARANTIE.</span>
<span class="c1 c3">&nbsp;Le logiciel vis&eacute; par une licence est offert &laquo; tel quel &raquo;. Toute utilisation
de ce logiciel est &agrave; votre seule risque et p&eacute;ril. Microsoft n&rsquo;accorde aucune
autre garantie expresse. Vous pouvez b&eacute;n&eacute;ficier de droits additionnels en vertu
du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles
sont permises par le droit locale, les garanties implicites de qualit&eacute; marchande, d&rsquo;ad&eacute;quation
<span class="c1 c3">&nbsp;Le logiciel vis&eacute; par une licence est offert &laquo; tel quel
&raquo;. Toute utilisation
de ce logiciel est &agrave; votre seule risque et p&eacute;ril. Microsoft n&rsquo;accorde
aucune
autre garantie expresse. Vous pouvez b&eacute;n&eacute;ficier de droits additionnels en
vertu
du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou
elles
sont permises par le droit locale, les garanties implicites de qualit&eacute; marchande,
d&rsquo;ad&eacute;quation
&agrave; un usage particulier et d&rsquo;absence de contrefa&ccedil;on sont exclues.
</span>
</p>
<p class="c11">
<span class="c5 c1">LIMITATION DES DOMMAGES-INT&Eacute;R&Ecirc;TS ET EXCLUSION DE RESPONSABILIT&Eacute; POUR LES DOMMAGES.</span>
<span class="c3 c1">&nbsp;Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages
directs uniquement &agrave; hauteur de 5,00 $ US. Vous ne pouvez pr&eacute;tendre &agrave; aucune
<span class="c5 c1">LIMITATION DES DOMMAGES-INT&Eacute;R&Ecirc;TS ET EXCLUSION DE
RESPONSABILIT&Eacute; POUR LES DOMMAGES.</span>
<span class="c3 c1">&nbsp;Vous pouvez obtenir de Microsoft et de ses fournisseurs une
indemnisation en cas de dommages
directs uniquement &agrave; hauteur de 5,00 $ US. Vous ne pouvez pr&eacute;tendre &agrave;
aucune
indemnisation pour les autres dommages, y compris les dommages sp&eacute;ciaux, indirects ou
accessoires et pertes de b&eacute;n&eacute;fices.</span>
</p>
@ -719,26 +838,36 @@
<span class="c3 c1">Cette limitation concerne :</span>
</p>
<p class="c2">
<span class="c3 c1">- &nbsp; &nbsp; &nbsp; &nbsp; tout ce qui est reli&eacute; au logiciel, aux services ou au contenu
(y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et</span>
<span class="c3 c1">- &nbsp; &nbsp; &nbsp; &nbsp; tout ce qui est reli&eacute; au logiciel, aux
services ou au contenu
(y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ;
et</span>
</p>
<p class="c2">
<span class="c3 c1">- &nbsp; &nbsp; &nbsp; &nbsp; les r&eacute;clamations au titre de violation de contrat ou de garantie,
ou au titre de responsabilit&eacute; stricte, de n&eacute;gligence ou d&rsquo;une autre faute
<span class="c3 c1">- &nbsp; &nbsp; &nbsp; &nbsp; les r&eacute;clamations au titre de violation
de contrat ou de garantie,
ou au titre de responsabilit&eacute; stricte, de n&eacute;gligence ou d&rsquo;une autre
faute
dans la limite autoris&eacute;e par la loi en vigueur.</span>
</p>
<p class="c12">
<span class="c3 c1">Elle s&rsquo;applique &eacute;galement, m&ecirc;me si Microsoft connaissait ou devrait conna&icirc;tre
<span class="c3 c1">Elle s&rsquo;applique &eacute;galement, m&ecirc;me si Microsoft connaissait
ou devrait conna&icirc;tre
l&rsquo;&eacute;ventualit&eacute; d&rsquo;un tel dommage. Si votre pays n&rsquo;autorise pas
l&rsquo;exclusion ou la limitation de responsabilit&eacute; pour les dommages indirects, accessoires
ou de quelque nature que ce soit, il se peut que la limitation ou l&rsquo;exclusion ci-dessus
l&rsquo;exclusion ou la limitation de responsabilit&eacute; pour les dommages indirects,
accessoires
ou de quelque nature que ce soit, il se peut que la limitation ou l&rsquo;exclusion
ci-dessus
ne s&rsquo;appliquera pas &agrave; votre &eacute;gard.</span>
</p>
<p class="c16">
<span class="c5 c1">EFFET JURIDIQUE.</span>
<span class="c3 c1">&nbsp;Le pr&eacute;sent contrat d&eacute;crit certains droits juridiques. Vous pourriez avoir d&rsquo;autres
droits pr&eacute;vus par les lois de votre pays. Le pr&eacute;sent contrat ne modifie pas les
droits que vous conf&egrave;rent les lois de votre pays si celles-ci ne le permettent pas.</span>
<span class="c3 c1">&nbsp;Le pr&eacute;sent contrat d&eacute;crit certains droits juridiques.
Vous pourriez avoir d&rsquo;autres
droits pr&eacute;vus par les lois de votre pays. Le pr&eacute;sent contrat ne modifie pas
les
droits que vous conf&egrave;rent les lois de votre pays si celles-ci ne le permettent
pas.</span>
</p>
<p class="c15">
<span class="c3 c1"></span>
@ -746,9 +875,9 @@
<p class="c16">
<span class="c3 c1">&nbsp;</span>
</p>
<p class="c11">
<span class="c3 c1">LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of
the LEGO Group. &copy;2018 The LEGO Group. All rights reserved.</span>
<span class="c3 c1">@copyrightText@</span>
</p>
<p class="c11">
<span class="c3 c1">&nbsp;</span>
@ -761,27 +890,30 @@
</p>
</div>
</div>
<div class="ui center aligned segment">
<div id="agree-segment" class="ui center aligned segment hidden">
<input id="agree-checkbox" type="checkbox" autocomplete="off" onchange="agreeCheckboxChanged(this)">
<label for="agree-checkbox">I agree to these Microsoft Software License Terms and to the
<a href="https://privacy.microsoft.com/en-us/privacystatement">Microsoft Privacy Statement.</a>
</label>
</div>
<div id="no-download-segment" class="ui center aligned segment hidden">
<p>Sorry, there is no Offline App available for this editor.</p>
</div>
<div id="download-segment" class="ui center aligned segment hidden">
<div class="ui grid">
<div class="eight wide column">
<h3 class="ui">Windows</h3>
<button class="ui icon button" onclick="downloadWin64()">
<a id="download-win64" class="ui icon button" onclick="downloadWin64()">
<i class="download icon"></i>
makecode-ev3-setup-win64.exe
</button>
makecode-@targetid@-setup-win64.exe
</a>
</div>
<div class="eight wide column">
<h3 class="ui">Mac OS</h3>
<button class="ui icon button" onclick="downloadMac64()">
<a id="download-mac64" class="ui icon button" onclick="downloadMac64()">
<i class="download icon"></i>
makecode-ev3-mac64.zip
</button>
makecode-@targetid@-mac64.zip
</a>
</div>
</div>
</div>

5
docs/offline.md Normal file
View File

@ -0,0 +1,5 @@
# @extends
## Offline app #target-app
The MakeCode editor is available as app which you can install on a computer with Windows or Mac OS. Once installed, the **[MakeCode Offline App](/offline-app)** lets you create, run, and download your projects to the @boardname@. It works the same as the Web application does in your browser but it's a stand-alone application that will work when a connection to the internet is restricted or not available.

3
docs/packages-ref.json Normal file
View File

@ -0,0 +1,3 @@
{
"redirect": "/extensions"
}

View File

@ -0,0 +1,3 @@
{
"redirect": "https://makecode.com/extensions/approval"
}

View File

@ -0,0 +1,3 @@
{
"redirect": "https://makecode.com/extensions/getting-started"
}

View File

@ -0,0 +1,3 @@
{
"redirect": "https://makecode.com/extensions/versioning"
}

View File

@ -0,0 +1,47 @@
# battery Property
Return the information about the battery
```sig
brick.batteryInfo(BatteryProperty.Level)
```
## Parameters
* property: the kind of information
## Returns
* a [number](/types/number) which represents the value of the property requested.
## Example
Show the battery level percentage on the screen. Also, show a green light if the battery level is above 15%. If the battery level is below 15% but above 5%, show a orange light. But, if the battery level is below 5%, show a pulsing red light.
```blocks
let battery = 0;
forever(function() {
brick.showString("Battery level:", 1)
brick.showNumber(battery, 2)
battery = brick.batteryInfo(BatteryProperty.Level);
if (battery > 15)
{
brick.setStatusLight(StatusLight.Green);
} else if (battery > 5) {
brick.setStatusLight(StatusLight.Orange);
} else {
brick.setStatusLight(StatusLight.RedPulse)
}
pause(30000)
})
```
Or see all the values
```blocks
forever(function () {
brick.showValue("bat V", brick.batteryInfo(BatteryProperty.Voltage), 1)
brick.showValue("bat %", brick.batteryInfo(BatteryProperty.Level), 2)
brick.showValue("bat I", brick.batteryInfo(BatteryProperty.Current), 3)
})
```

View File

@ -10,12 +10,12 @@ You can find out what's connected to the ports on the brick and show its status.
## Example
Show the status of the ports on the brick when the ``enter`` button is pressed.
Show the status of the ports on the brick. Resets all motors when ENTER is pressed.
```blocks
brick.showString("Press ENTER for port status", 1)
brick.showPorts()
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showPorts()
motors.resetAll()
})
```

View File

@ -0,0 +1,59 @@
# Ramp
Schedules an acceleration, constant and deceleration phase at a given speed.
```sig
motors.largeA.ramp(50, 100, 500, 100)
```
The speed setting is a percentage of the motor's full speed. Full speed is the speed that the motor runs when the brick supplies maximum output voltage to the port.
## Parameters
* **speed**: a [number](/types/number) that is the percentage of full speed. A negative value runs the motor in the reverse direction.
* **acceleration**: the [number](/types/number) of movement units to rotate for while accelerating.
* **value**: the [number](/types/number) of movement units to rotate for.
* **deceleration**: the [number](/types/number) of movement units to rotate for while decelerating.
* **unit**: the movement unit of rotation. This can be `milliseconds`, `seconds`, `degrees`, or `rotations`. If the number for **value** is `0`, this parameter isn't used.
## Example
This is an interactive program that lets you change the values of
the acceleration and deceleration and see the effects.
```blocks
let steady = 0
let dec = 0
let acc = 0
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
acc += -100
})
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
motors.largeB.ramp(50, steady, MoveUnit.MilliSeconds, acc, dec)
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
acc += 100
})
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
dec += 100
})
brick.buttonDown.onEvent(ButtonEvent.Pressed, function () {
dec += -100
})
acc = 500
steady = 1000
acc = 500
forever(function () {
brick.showValue("acc", acc, 1)
brick.showValue("steady", steady, 2)
brick.showValue("dec", dec, 3)
brick.showString("acc: left/right", 5)
brick.showString("dec: up/down", 6)
brick.showString("run large B: enter", 7)
})
```
## See also
[tank](/reference/motors/synced/tank), [steer](/reference/motors/synced/steer), [stop](/reference/motors/motor/stop)

View File

@ -6,9 +6,9 @@ Set the rotation speed of the motor as a percentage of maximum speed.
motors.largeA.run(50)
```
The speed setting is a pecentage of the motor's full speed. Full speed is the speed that the motor runs when the brick supplies maximum output voltage to the port.
The speed setting is a percentage of the motor's full speed. Full speed is the speed that the motor runs when the brick supplies maximum output voltage to the port.
If you use just the **speed** number, the motor runs continously and won't stop unless you tell it to. You can also give a value for a certain amount of distance you want the motor to rotate for. The **value** can be an amount of time, a turn angle in degrees, or a number of full rotations.
If you use just the **speed** number, the motor runs continuously and won't stop unless you tell it to. You can also give a value for a certain amount of distance you want the motor to rotate for. The **value** can be an amount of time, a turn angle in degrees, or a number of full rotations.
If you decide to use a **value** of rotation distance, you need to choose a type of movement **unit**.
@ -30,8 +30,8 @@ Here is how you use each different movement unit to run the motor for a fixed ro
// Run motor for 700 Milliseconds.
motors.largeA.run(25, 700, MoveUnit.MilliSeconds);
// Run motor for 700 Milliseconds again but no units specified.
motors.largeA.run(25, 700);
// Run motors B and C for 700 Milliseconds again but no units specified.
motors.largeBC.run(25, 700);
// Run the motor for 45 seconds
motors.largeA.run(50, 45, MoveUnit.Seconds);
@ -61,6 +61,14 @@ motors.largeB.run(-25)
## ~
## Multiple motors
When using **run** with multiple motors, there is no guarantee that their speed will stay in sync. Use [tank](/reference/motors/tank) or [steer](/reference/motors/steer) for synchronized motor operations.
```blocks
motors.largeBC.run(50)
```
## Examples
### Drive the motor for 20 seconds

View File

@ -0,0 +1,30 @@
# set Brake Settle Time
Set the time to wait after a motor stopped to allow it settle
when brake is enabled. Default is 10ms.
```sig
motors.largeA.setBrakeSettleTime(200)
```
When a the motor is stopped and brake is applied, it can still wiggle for a little while. You can use the settle time to automatically way after stopping and let the robot settle.
## Parameters
* **time**: a [number](/types/number) value which represents the number of milliseconds to wait after braking.
## Example
Set the brake mode and the settle time to 500ms. Run the motor connected to port **A** for 2 seconds at a speed of `30` and stop after 2s.
```blocks
motors.largeA.setBrake(true)
motors.largeA.setBrakeSettleTime(500)
motors.largeA.run(30)
pause(2000)
motors.largeA.stop()
```
## See also
[stop](/reference/motors/motor/stop)

View File

@ -1,28 +1,28 @@
# set Brake
Set the brake on the motor so it won't turn when it has no power.
Set the brake on the motor so it will brake when it finishes a brake command.
```sig
motors.largeA.setBrake(false)
```
When a the motor is stopped, it can still rotate if an external force is applied to it. This can happen, for example, if your're tanking your brick on a inclined surface and stop the motors. Gravity will push down on the brick and might cause it to start rolling again. You can prevent this movement by setting the brake.
When a the motor is stopped, it can still rotate if an external force is applied to it. This can happen, for example, if you're tanking your brick on a inclined surface and stop the motors. Gravity will push down on the brick and might cause it to start rolling again. You can prevent this movement by setting the brake.
Also, you can use the brake to do simple skid steering for your brick.
## Paramters
## Parameters
* **brake**: a [boolean](/types/boolean) value which is either `true` to set the brake on or `false` to set the brake off.
## Example
Run the motor connected to port **A** for 2 seconds at a speed of `30`. Stop and set the brake.
Run the motor connected to port **A** for 2 seconds at a speed of `30` and stop after 2s.
```blocks
motors.largeA.setBrake(true)
motors.largeA.run(30)
pause(2000)
motors.largeA.stop()
motors.largeA.setBrake(true)
```
## See also

View File

@ -0,0 +1,26 @@
# Set Run Phase
Allows to specify an acceleration or deceleration phases for run commands.
```sig
motors.largeD.setRunPhase(MovePhase.Acceleration, 1, MoveUnit.Seconds)
```
Once the run phase is specified on a motor (or pair of motors),
it will be automatically applied to [run](/reference/motors/run) commands.
## Time vs Rotation
The phases specified for time units (seconds, milliseconds) only apply to run with time
moves. Similarly, the phases specified for rotation units (# rotation, degrees) only
apply to run with rotation units.
## Examples
```blocks
motors.largeB.setRunPhase(MovePhase.Acceleration, 0.5, MoveUnit.Seconds)
motors.largeB.setRunPhase(MovePhase.Deceleration, 0.2, MoveUnit.Seconds)
forever(function () {
motors.largeB.run(50, 1, MoveUnit.Seconds)
})
```

View File

@ -0,0 +1,25 @@
# reset All Motors
Reset all motors currently running on the brick.
```sig
motors.resetAll();
```
The motors counters are resetted.
## Example
Tank the EV3 Brick forward at half speed for 5 seconds and then stop.
```blocks
motors.largeAB.tank(50, 50);
pause(5000);
motors.stopAll();
motors.resetAll();
```
## See also
[stop all](/reference/motors/motor/stop-all),
[reset](/reference/motors/motor/reset)

View File

@ -22,4 +22,5 @@ motors.stopAll();
[stop](/reference/motors/motor/stop),
[reset](/reference/motors/motor/reset),
[reset-all](/reference/motors/motor/reset-all),
[set brake](/reference/motors/motor/set-brake)

View File

@ -22,7 +22,7 @@ If you decide to use a **value** of rotation distance, you need to choose a type
## Parameters
* **turnRatio**: a [number](/types/number) that is the percentage of speed of the drive motor. The follower motor runs at this speed. A negative number steers to the left and a positive number steers to the right. This is a number between `-100` and `100`.
* **turnRatio**: a [number](/types/number) that is the percentage of speed of the drive motor. The follower motor runs at this speed. A negative number steers to the left and a positive number steers to the right. This is a number between `-200` and `200`.
* **speed**: a [number](/types/number) that is the percentage of full speed. A negative value runs the motors in the reverse direction. This is the speed that the drive motor runs at.
* **value**: the [number](/types/number) of movement units to rotate for. A value of `0` means run the motor continuously.
* **unit**: the movement unit of rotation. This can be `milliseconds`, `seconds`, `degrees`, or `rotations`. If the number for **value** is `0`, this parameter isn't used.
@ -39,6 +39,13 @@ motors.largeBC.steer(-15, -75)
## ~
## ~ hint
Only one set of synchronized motors will run at the same time. Once you launch tank/steer, it will cancel any existing synchronized speed command.
## ~
## Examples
### Make a slight right
@ -79,6 +86,51 @@ for (let i = 0; i < 4; i++) {
motors.stopAll()
```
### Steer tester
This program lets you change the values of speed and turn ratio with the buttons.
```typescript
let speed = 0;
let turnRatio = 0;
brick.showString(`steer tester`, 1)
brick.showString(`connect motors BC`, 7)
brick.showString(`up/down for speed`, 8)
brick.showString(`left/right for turn ratio`, 9)
forever(function () {
brick.showString(`motor B speed ${motors.largeB.speed()}%`, 4)
brick.showString(`motor C speed ${motors.largeC.speed()}%`, 5)
pause(100)
})
function updateSteer() {
motors.largeBC.steer(turnRatio, speed);
brick.showString(`speed ${speed}%`, 2)
brick.showString(`turnRatio ${turnRatio}`, 3)
}
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
speed += 10
updateSteer()
})
brick.buttonDown.onEvent(ButtonEvent.Pressed, function () {
speed -= 10
updateSteer()
})
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
turnRatio -= 10
updateSteer()
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
turnRatio += 10
updateSteer()
})
updateSteer()
```
## See also
[tank](/reference/motors/synced/tank), [run](/reference/motors/motor/run)

View File

@ -35,6 +35,12 @@ motors.largeBC.tank(-75, -75)
## ~
## ~ hint
Only one set of synchronized motors will run at the same time. Once you launch tank/steer, it will cancel any existing synchronized speed command.
## ~
## Examples
### Tank forward and backward
@ -76,6 +82,51 @@ pause(5000)
motors.stopAll()
```
### Tank tester
This program lets you change the tank values using the brick buttons.
```typescript
let tankB = 0;
let tankC = 0;
brick.showString(`tank tester`, 1)
brick.showString(`connect motors BC`, 7)
brick.showString(`up/down for tank B`, 8)
brick.showString(`left/right for tank C`, 9)
forever(function () {
brick.showString(`motor B speed ${motors.largeB.speed()}%`, 4)
brick.showString(`motor C speed ${motors.largeC.speed()}%`, 5)
pause(100)
})
function updateTank() {
brick.showString(`tank A: ${tankB}%`, 2)
brick.showString(`tank B: ${tankC}%`, 3)
motors.largeBC.tank(tankB, tankC);
}
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
tankB += 10
updateTank();
})
brick.buttonDown.onEvent(ButtonEvent.Pressed, function () {
tankB -= 10
updateTank();
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
tankC += 10
updateTank();
})
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
tankC -= 10
updateTank();
})
updateTank();
```
## See also
[steer](/reference/motors/synced/steer), [run](/reference/motors/motor/run)

BIN
docs/static/bluetooth/experimental.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/static/fll/code-js.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

BIN
docs/static/fll/context-help.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
docs/static/fll/fll-big.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
docs/static/fll/fll-logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/static/fll/import-button.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/static/fll/save-project.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/static/fll/share-button.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/static/fll/share-program.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
docs/static/fll/share-program.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/static/fll/simulator.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
docs/static/tutorials/calibrate-gyro.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/static/tutorials/coast-or-brake.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/static/tutorials/drifter.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/static/tutorials/move-to-color.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/static/tutorials/pause-on-start.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/static/tutorials/pivot-turn.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/static/tutorials/smooth-turn.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/static/tutorials/spin-turn.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/static/tutorials/tank-zigzag.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/static/tutorials/turn-with-gyro.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/static/tutorials/wall-follower.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -2,113 +2,51 @@
Step by step guides to coding your @boardname@.
## Brick
## Tutorials
```codecard
[{
"name": "Wake Up!",
"description": "Show different moods on the screen. Is it tired, sleepy, or awake?",
"cardType": "tutorial",
"url":"/tutorials/wake-up",
"name": "Brick",
"description": "Learn how to use the screen and the buttons",
"url":"/tutorials/brick",
"imageUrl":"/static/tutorials/wake-up.png"
}, {
"name": "Make an Animation",
"description": "Create a custom animation on your EV3 Brick Display.",
"cardType": "tutorial",
"url":"/tutorials/make-an-animation",
"imageUrl":"/static/tutorials/make-an-animation.png"
}, {
"name": "What Animal Am I?",
"description": "Create different animal effects and have someone guess what the animal is.",
"cardType": "tutorial",
"url":"/tutorials/what-animal-am-i",
"imageUrl":"/static/tutorials/what-animal-am-i.png"
}, {
"name": "Music Brick",
"description": "Transform the brick into a musical instrument!",
"cardType": "tutorial",
"url":"/tutorials/music-brick",
"imageUrl":"/static/tutorials/music-brick.png"
}]
```
## Motors
```codecard
[{
"name": "Run Motors",
"description": "Use the EV3 Brick buttons to start and stop the Large Motor and Medium Motor.",
"cardType": "tutorial",
"url":"/tutorials/run-motors",
"name": "Motors",
"description": "User motors to move the brick.",
"url":"/tutorials/motors",
"imageUrl":"/static/tutorials/run-motors.png"
}]
```
## Touch Sensor
```codecard
[{
"name": "Touch to Run",
"description": "Press the Touch Sensor and run a motor.",
"cardType": "tutorial",
"url":"/tutorials/touch-to-run",
}, {
"name": "Touch Sensor",
"description": "Use touch sensors in your robot.",
"url":"/tutorials/touch-sensor",
"imageUrl":"/static/tutorials/touch-to-run.png"
}, {
"name": "Touch Sensor Values",
"description": "Check the value of a Touch Sensor and stop a motor if pressed.",
"cardType": "tutorial",
"url":"/tutorials/touch-sensor-values",
"imageUrl":"/static/tutorials/touch-sensor-values.png"
}]
```
## Color Sensor
```codecard
[{
"name": "What Color?",
"description": "Use the Color Sensor to detect different colors.",
"cardType": "tutorial",
"url":"/tutorials/what-color",
"name": "Color Sensor",
"description": "Use the color sensor to follow line or detect colors",
"url":"/tutorials/color-sensor",
"imageUrl":"/static/tutorials/what-color.png"
}, {
"name": "Line Following",
"description": "Use the Color Sensor to make a robot follow a line.",
"cardType": "tutorial",
"url":"/tutorials/line-following",
"imageUrl":"/static/tutorials/line-following.png"
"name": "Gyro",
"description": "Drive straight or turn more precisely with the gyro",
"url":"/tutorials/gyro",
"imageUrl":"/static/tutorials/calibrate-gyro.png"
}, {
"name": "Red Light, Green Light",
"description": "Play Red Light, Green Light using the Color Sensor and the robot.",
"cardType": "tutorial",
"url":"/tutorials/redlight-greenlight",
"imageUrl":"/static/tutorials/redlight-greenlight.png"
}]
```
## Infrared Sensor
```codecard
[{
"name": "Security Alert",
"description": "Build an security alert using the Infrared Sensor.",
"cardType": "tutorial",
"url":"/tutorials/security-alert",
"name": "Ultrasonic Sensor",
"description": "Use the ultrasonic sensor to detect obstacles",
"url":"/tutorials/ultrasonic-sensor",
"imageUrl":"/static/tutorials/object-near.png"
}, {
"name": "Infrared Sensor",
"description": "Use the infrared sensor to detect objects",
"url":"/tutorials/infrared-sensor",
"imageUrl":"/static/tutorials/security-alert.png"
}]
```
## See Also
[Wake Up!](/tutorials/wake-up),
[Make An Animation](/tutorials/make-an-animation),
[What Animal Am I?](/tutorials/what-animal-am-i),
[Music Brick](/tutorials/music-brick),
[Run Motors](/tutorials/run-motors),
[Touch to Run](/tutorials/touch-to-run),
[Touch Sensor Values](/tutorials/touch-sensor-values),
[What Color?](/tutorials/what-color),
[Line Following](/tutorials/line-following),
[Red Light, Green Light](/tutorials/redlight-greenlight),
[Object Near?](/tutorials/object-near),
[Security Alert](/tutorials/security-alert)
[Brick tutorials](/tutorials/brick),
[Motors tutorials](/tutorials/motors),
[Touch sensor tutorials](/tutorials/touch-sensor),
[Color sensor tutorials](/tutorials/color-sensor),
[Infrared sensor tutorials](/tutorials/infrared-sensor)

44
docs/tutorials/brick.md Normal file
View File

@ -0,0 +1,44 @@
# Brick Tutorials
## Tutorials
```codecard
[{
"name": "Wake Up!",
"description": "Show different moods on the screen. Is it tired, sleepy, or awake?",
"cardType": "tutorial",
"url":"/tutorials/wake-up",
"imageUrl":"/static/tutorials/wake-up.png"
}, {
"name": "Make an Animation",
"description": "Create a custom animation on your EV3 Brick Display.",
"cardType": "tutorial",
"url":"/tutorials/make-an-animation",
"imageUrl":"/static/tutorials/make-an-animation.png"
}, {
"name": "What Animal Am I?",
"description": "Create different animal effects and have someone guess what the animal is.",
"cardType": "tutorial",
"url":"/tutorials/what-animal-am-i",
"imageUrl":"/static/tutorials/what-animal-am-i.png"
}, {
"name": "Music Brick",
"description": "Transform the brick into a musical instrument!",
"cardType": "tutorial",
"url":"/tutorials/music-brick",
"imageUrl":"/static/tutorials/music-brick.png"
}, {
"name": "Pause On Start",
"description": "Don't start running immediately!",
"cardType": "tutorial",
"url":"/tutorials/pause-on-start",
"imageUrl":"/static/tutorials/pause-on-start.png"
}]
```
## See Also
[Wake Up!](/tutorials/wake-up),
[Make An Animation](/tutorials/make-an-animation),
[What Animal Am I?](/tutorials/what-animal-am-i),
[Music Brick](/tutorials/music-brick),

View File

@ -0,0 +1,37 @@
# Calibrate Gyro
## Introduction @fullscreen
The gyroscope is a very useful sensor in the EV3 system. It detects the rotation rate
which can be very useful to correct the trajectory of the robot and do precise turns.
However, the sensor can be imprecise and subject to drifting. It is recommend to
calibrate your sensor at least once after starting your brick. You don't have to
recalibrate on every run.
* [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
* [EV3 Driving Base with Gyro](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-gyro-sensor-driving-base-a521f8ebe355c281c006418395309e15.pdf)
## Step 1 Show ports
Add the ``||brick:show ports||`` to see the status of the gyroscope.
```blocks
brick.showPorts()
```
## Step 2 Calibration
Add a ``||sensors:calibrate gyro||`` block to calibrate the gyro. The block
detects if the sensor is present and does a full reset of the sensor if necessary.
```blocks
brick.showPorts()
sensors.gyro2.calibrate()
```
## Step 3 Download and run @fullscreen
Download this program to your brick and press the ENTER button.

View File

@ -0,0 +1,54 @@
# City Shaper
## Tutorials
```codecard
[
{
"name": "Crane Mission / Robot 1",
"description": "Learn the basics and build your first robot driving base.",
"cardType": "tutorial",
"url":"/tutorials/city-shaper/robot-1",
"imageUrl": "/static/tutorials/city-shaper/robot1.jpg"
}, {
"name": "Crane Mission / Robot 2",
"description": "Program your robot to move in different ways.",
"cardType": "tutorial",
"url":"/tutorials/city-shaper/robot-2",
"imageUrl": "/static/tutorials/city-shaper/robot2.jpg"
}, {
"name": "Crane Mission / Video 1",
"description": "A video of the Robot 1 tutorial",
"youTubeId": "IqL0Pyeu5Ng"
}, {
"name": "Bluetooth download (beta)",
"description": "EXPERIMENTAL! Learn how to download code via Bluetooth.",
"youTubeId": "VIq8-6Egtqs"
}, {
"name": "Turn with Gyro",
"description": "Use the gyro for precise turns.",
"youTubeId": "I7ncuXAfBwk"
}, {
"name": "Moving with Gyro",
"description": "Use the gyro for correct the robot trajectory.",
"youTubeId": "ufiOPvW37xc"
}, {
"name": "Line following with 1 color sensor",
"description": "Simple line following using the color sensor.",
"youTubeId": "_LeduyKQVjg"
}, {
"name": "Proportional line following with 1 color sensor",
"description": "Proportional line following using the color sensor.",
"youTubeId": "-AirqwC9DL4"
}, {
"name": "Proportional line following with 2 color sensors",
"description": "Proportional line following using two color sensor.",
"youTubeId": "QWOflBuu9Oo"
}]
```
## See Also
[Robot 1](/tutorials/city-shaper/robot-1),
[Robot 2](/tutorials/city-shaper/robot-2)

View File

@ -0,0 +1,27 @@
# Crane Mission Lessons
The [Crane Mission Lessons](https://firstinspiresst01.blob.core.windows.net/fll/2020/fll-ev3-overview.pdf) adapted for MakeCode.
## Lessons
```codecard
[
{
"name": "Crane Mission / Robot 1",
"description": "Learn the basics and build your first robot driving base.",
"cardType": "tutorial",
"url":"/tutorials/city-shaper/robot-1"
}, {
"name": "Crane Mission / Robot 2",
"description": "Program your robot to move in different ways.",
"cardType": "tutorial",
"url":"/tutorials/city-shaper/robot-2"
}
]
```
## See Also
[Robot 1](/tutorials/city-shaper/robot-1),
[Robot 2](/tutorials/city-shaper/robot-2)

View File

@ -0,0 +1,20 @@
# Mission 2 Lesson
Use the program below to tell your robot how to solve the Crane Mission (Mission 2).
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
motors.largeBC.steer(0, 25, 2.25, MoveUnit.Rotations)
control.timer1.reset()
while (control.timer1.seconds() < 1.5) {
motors.largeBC.steer(sensors.color1.light(LightIntensityMode.Reflected) - 40, 50)
}
motors.largeBC.stop()
motors.largeBC.steer(0, 15, 0.25, MoveUnit.Rotations)
motors.mediumA.run(25, 60, MoveUnit.Degrees)
pause(2000)
motors.mediumA.run(-25, 1, MoveUnit.Seconds)
motors.largeBC.steer(0, -100, 4, MoveUnit.Rotations)
})
motors.largeBC.setBrake(true)
```

View File

@ -0,0 +1,53 @@
# Robot 1 Lesson
## Step 1 - Build Your Driving Base Robot @unplugged
Build the medium motor robot driving base:
* [Driving base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
* [Medium motor driving base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-medium-motor-driving-base-e66e2fc0d917485ef1aa023e8358e7a7.pdf)
If clicking on the image above doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
## Step 2 - Show an image @fullscreen
At first, it's nice to know that your program is running. Plug in a ``||brick:show mood||`` from the **BRICK** toolbox drawer
into the ``||loops:on start||`` block. Change the image to something else if you want!
```blocks
brick.showMood(moods.sleeping)
```
## Step 3 - Try your code @fullscreen
Look at the simulator and check that your image is showing on the screen. When you are ready, press the **DOWNLOAD** button
and follow the instructions to transfer your code on the brick.
## Step 4 - Pause on Start @fullscreen
As you may have noticed, the code starts running immediately once you download it to the brick. To prevent the robot
from rolling away, add a ``||brick:pause until enter pressed||`` button to wait for the user to press enter.
```blocks
brick.showMood(moods.sleeping)
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
```
## Step 5 - Steer motors @fullscreen
Drag a ``||motors:steer motors||`` block from the **MOTORS** toolbox drawer and snap it in under ``||brick:show mood||``.
Click on the **(+)** symbol and make sure to tell your motors to turn **1** rotation.
```blocks
brick.showMood(moods.sleeping)
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
brick.showMood(moods.neutral)
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
```
## Step 6 - Try your code @fullscreen
Whenever you make a code change, the simulator will restart so you can see what your latest change will do.
When you are ready, click **DOWNLOAD** and follow the instructions to transfer the code into your brick.
**Remember**: Take the driving base apart at the end of the session so that another group can build their robot too.

View File

@ -0,0 +1,100 @@
# Robot 2 Lesson
## Step 1 - Build Your Driving Base Robot @unplugged
Build the robot driving base:
[![EV3 Driving Base](/static/lessons/common/ev3-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
If clicking on the image above doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
## Step 2 - Show an image and move @fullscreen
Add blocks to the ``||loops:on start||`` block to show an image and move the motors **B+C** for ``1`` rotation.
```blocks
brick.showMood(moods.neutral)
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
```
## Step 3 - Brick button @fullscreen
Let's change the code so that your robot moves when the **UP** button is pressed.
Add an ``||brick:on button up||`` block and move ``||motors:steer motors||`` inside of it.
After downloading your code, press **UP** to move the robot.
```blocks
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.awake)
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
})
brick.showMood(moods.neutral)
```
## Step 4 - Braking @fullscreen
When the motors are done turning, the robot keeps on moving for a short distance.
Turn on the **brakes** so that your robot stops immediately.
Drag a ``||motors:set brake||`` block into the ``||loops:on start||`` and set it to **ON** for the the **BC** motors.
```blocks
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.awake)
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
})
brick.showMood(moods.neutral)
motors.largeBC.setBrake(true)
```
## Step 5 - Left and Right turn @fullscreen
Let's make the robot turn to the left when the **LEFT** button is pressed on the brick.
Find an ``||brick:on button||`` block and put a ``||motors:steer motors||`` in it. Make the turn ratio drive the motor to left.
Get another ``||brick:on button||`` and set it to run when the **RIGHT** is pressed.
Put a ``||motors:steer motors||`` in for that button and set the turn ratio to drive to the right.
```blocks
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.middleLeft)
motors.largeBC.steer(-50, 50, 1, MoveUnit.Rotations)
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.middleRight)
motors.largeBC.steer(50, 50, 1, MoveUnit.Rotations)
})
```
## Step 6 - Backwards @fullscreen
Let's make the robot go backwards when the **DOWN** button is pressed on the brick.
Add a ``||motors:steer motors||`` to an ``||brick:on button||`` block and change the speed to be negative. This will make the motor go backwards.
```blocks
brick.buttonDown.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.knockedOut)
motors.largeBC.steer(0, -50, 1, MoveUnit.Rotations)
})
```
## Step 7 - Add an Ultrasonic sensor @fullscreen
Add an Ultrasonic sensor to your driving base.
[![EV3 Driving Base with Ultrasonic Sensor](/static/lessons/common/ev3-ultrasonic-sensor-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-ultrasonic-sensor-driving-base-61ffdfa461aee2470b8ddbeab16e2070.pdf)
If clicking on the image above doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
## Step 8 - Stopping distance @fullscreen
Create a program that moves the Driving Base and makes it stop 6 cm from the Cuboid.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showMood(moods.dizzy)
motors.largeBC.steer(0, 50)
pauseUntil(() => sensors.ultrasonic4.distance() < 6)
motors.largeBC.stop()
})
```
Try sending your robot towards a wall!

View File

@ -0,0 +1,16 @@
# Coast or Brake
This code example will set the brake when button **A** is pressed or let the motor coast (turn freely when not running) when button **B** is pressed. The motor is turned by one rotation to cause motion.
```blocks
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
// tell motor to brake once the run command is done
motors.largeB.setBrake(true)
motors.largeB.run(100, 1, MoveUnit.Rotations)
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
// tell motor to coast once the run command is done
motors.largeB.setBrake(false)
motors.largeB.run(100, 1, MoveUnit.Rotations)
})
```

View File

@ -0,0 +1,49 @@
# Color Sensor
## Tutorials
```codecard
[{
"name": "What Color?",
"description": "Use the Color Sensor to detect different colors.",
"cardType": "tutorial",
"url":"/tutorials/what-color",
"imageUrl":"/static/tutorials/what-color.png"
}, {
"name": "Line Following",
"description": "Use the Color Sensor to make a robot follow a line.",
"cardType": "tutorial",
"url":"/tutorials/line-following",
"imageUrl":"/static/tutorials/line-following.png"
}, {
"name": "Red Light, Green Light",
"description": "Play Red Light, Green Light using the Color Sensor and the robot.",
"cardType": "tutorial",
"url":"/tutorials/redlight-greenlight",
"imageUrl":"/static/tutorials/redlight-greenlight.png"
}, {
"name": "Move To Color",
"description": "Move straight until a color is detected.",
"cardType": "tutorial",
"url":"/tutorials/move-to-color",
"imageUrl":"/static/tutorials/move-to-color.png"
}, {
"name": "Reflected Light Measure",
"description": "Teach the sensor what light or dark is.",
"cardType": "example",
"url":"/tutorials/reflected-light-measure",
"imageUrl":"/static/tutorials/reflected-light-measure.png"
}, {
"name": "Reflected Light Calibration",
"description": "Use the auto-calibration feature to setup the dark and bright values.",
"cardType": "example",
"url":"/tutorials/reflected-light-calibration",
"imageUrl":"/static/tutorials/reflected-light-calibration.png"
}]
```
## See Also
[What Color?](/tutorials/what-color),
[Line Following](/tutorials/line-following),
[Red Light, Green Light](/tutorials/redlight-greenlight),

34
docs/tutorials/drifter.md Normal file
View File

@ -0,0 +1,34 @@
# Drifter
Use this program to try out the gyro sensor and the effect of drifting.
```typescript
// this loop shows the rate, angle and drift of the robot
forever(() => {
brick.showValue("rate", sensors.gyro2.rate(), 1)
brick.showValue("angle", sensors.gyro2.angle(), 2)
brick.showValue("drift", sensors.gyro2.drift(), 3)
})
// this loop shows wheter the sensor is calibrating
forever(() => {
brick.showString(sensors.gyro2.isCalibrating() ? "calibrating..." : "", 4)
})
// instructions on how to use the buttons
brick.showString("ENTER: calibrate", 7)
brick.showString(" (reset+drift)", 8)
brick.showString("LEFT: reset", 9)
brick.showString("RIGHT: compute drift", 10)
// enter -> calibrate
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
sensors.gyro2.calibrate()
})
// right -> compute drift
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
sensors.gyro2.computeDrift()
})
// left -> reset
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
sensors.gyro2.reset()
})
```

31
docs/tutorials/gyro.md Normal file
View File

@ -0,0 +1,31 @@
# Gyro tutorials
## Tutorials
```codecard
[{
"name": "Calibrate",
"description": "Make sure you gyro sensor is ready to use",
"cardType": "tutorial",
"url":"/tutorials/calibrate-gyro",
"imageUrl":"/static/tutorials/calibrate-gyro.png"
}, {
"name": "Turn",
"description": "Use the gyro to turn precisely",
"cardType": "tutorial",
"url":"/tutorials/turn-with-gyro",
"imageUrl":"/static/tutorials/turn-with-gyro.png"
}, {
"name": "Move Straight",
"description": "Use the gyro to correct the trajectory of the robot",
"cardType": "tutorial",
"url":"/tutorials/move-straight-with-gyro",
"imageUrl":"/static/tutorials/move-straight-with-gyro.png"
}, {
"name": "Drifter",
"description": "Explore how the gyro is drifting",
"cardType": "example",
"url":"/tutorials/drifter",
"imageUrl":"/static/tutorials/drifter.png"
}]
```

View File

@ -0,0 +1,17 @@
# Infrared sensor
## Tutorials
```codecard
[{
"name": "Security Alert",
"description": "Build an security alert using the Infrared Sensor.",
"cardType": "tutorial",
"url":"/tutorials/security-alert",
"imageUrl":"/static/tutorials/security-alert.png"
}]
```
## See Also
[Security Alert](/tutorials/security-alert)

58
docs/tutorials/motors.md Normal file
View File

@ -0,0 +1,58 @@
# Motors
## Tutorials
```codecard
[{
"name": "Run Motors",
"description": "Use the EV3 Brick buttons to start and stop the Large Motor and Medium Motor.",
"cardType": "tutorial",
"url":"/tutorials/run-motors",
"imageUrl":"/static/tutorials/run-motors.png"
}, {
"name": "Spin Turn",
"description": "Turn the driving base around its center.",
"cardType": "example",
"url":"/tutorials/spin-turn",
"imageUrl":"/static/tutorials/spin-turn.png"
}, {
"name": "Pivot Turn",
"description": "Turn the driving base around a wheel.",
"cardType": "example",
"url":"/tutorials/pivot-turn",
"imageUrl":"/static/tutorials/pivot-turn.png"
}, {
"name": "Smooth Turn",
"description": "Turn the driving base in a smooth, steering motion.",
"cardType": "example",
"url":"/tutorials/smooth-turn",
"imageUrl":"/static/tutorials/smooth-turn.png"
}, {
"name": "Tank ZigZag",
"description": "Use the tank block to keep motors in sync.",
"cardType": "example",
"url":"/tutorials/tank-zigzag",
"imageUrl":"/static/tutorials/tank-zigzag.png"
}, {
"name": "Coast Or Brake",
"description": "Tell motors to coast or brake once the run command is done.",
"cardType": "example",
"url":"/tutorials/coast-or-brake",
"imageUrl":"/static/tutorials/coast-or-brake.png"
}, {
"name": "Turtle",
"description": "Encode moves and run them on a driving base",
"url":"/tutorials/turtle",
"cardType": "example"
}]
```
## See Also
[Run Motors](/tutorials/run-motors),
[Spin Turn](/tutorials/spin-turn),
[Pivot Turn](/tutorials/pivot-turn),
[Smooth Turn](/tutorials/smooth-turn),
[Tank ZigZag](/tutorials/tank-zigzag),
[Coast Or Brake](/tutorials/coast-or-brake),
[Turtle](/tutorials/turtle)

View File

@ -0,0 +1,61 @@
# Move Straight With Gyro
## Introduction @fullscreen
Rotating using a wheel is not precise. The wheel can slip or the motors
can be slightly different.
With the help of the gyro you can detect and correct deviations in your trajectory.
* [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
* [EV3 Driving Base with Gyro](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-gyro-sensor-driving-base-a521f8ebe355c281c006418395309e15.pdf)
## Step 1 Calibration
Add a ``||sensors:calibrate gyro||`` block in a ``||brick:on button enter pressed||`` block so that you can manually start a calibration process. Run the calibration
at least once after connecting the gyro.
```blocks
brick.showPorts()
sensors.gyro2.calibrate()
```
## Step 2 Compute the error
Make a new **error** variable and drag the ``||sensors:gyro rate||``
and multiply it by -1. Since the rate shows the rotation rate, we will
counter it by negating it.
```blocks
let error = 0
brick.showPorts()
sensors.gyro2.calibrate()
while (true) {
error = sensors.gyro2.rate() * -1
}
```
## Step 3 Steer with feedback
Drag a ``||motors:steer motors||`` block under the variable and pass
the **error** variable into the turn ratio section.
If the robot is turning right, the gyro will report a positive rotation rate
and the turn ratio will be negative which will the turn the robot left!
```blocks
let error = 0
brick.showPorts()
sensors.gyro2.calibrate()
while (true) {
error = sensors.gyro2.rate() * -1
motors.largeBC.steer(error, 50)
}
```
## Step 4 Run it!
Download to your brick and test out if the robot is going straight.
This kind of technique is called a proportional controller;
it corrects the inputs (motor speed) with a feedback proportional to the output (rotation rate).

View File

@ -0,0 +1,65 @@
# Move To Color
## Introduction @fullscreen
This tutorial shows how to move the EV3 driving base until the color sensor detects a color.
Here are the building instructions for the robot:
* [EV3 driving base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
* [Color sensor down](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-color-sensor-down-driving-base-d30ed30610c3d6647d56e17bc64cf6e2.pdf)
## Step 1 Run code on button pressed
Drag ``||brick:on button pressed||`` block so that your code starts when the enter button is pressed (and not at the start). We are also using the ``||brick:show string||``
message easily diagnose if the program does not work.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showString("started", 1)
})
```
## Step 2 Turn on the motors
Drag a ``||motors:steer motors B+C||`` block under the button pressed event. This will turn on both motors.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showString("started", 1)
motors.largeBC.steer(0, 50)
})
```
## Step 3 Pause until color
Drag a ``||sensors:pause until color detected||`` block after the steer and select the color you want to detect. This block will stop the program until the color is detected.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showString("started", 1)
motors.largeBC.steer(0, 50)
brick.showString("looking for red", 1)
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
})
```
### Step 4 Stop the motors!
Once the color is detected, the program will continue to run blocks. Drag a ``||motors:stop B+C motor||`` so that both motors stop.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
brick.showString("started", 1)
motors.largeBC.steer(0, 50)
brick.showString("looking for red", 1)
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
brick.showString("stop", 1)
motors.largeBC.stop()
})
```
## Step 5
Download your program to your brick and try it out!

View File

@ -0,0 +1,33 @@
# Pause On Start
## Introduction @unplugged
Sometimes you don't want your program to run right away... you can use a button to wait before moving the motors.
## Step 1
Let's start by showing an image on the screen so the user knows that the robot is ready and waiting.
```blocks
brick.showImage(images.informationStop1)
```
## Step 2
Drag the ``||brick:pause until enter pressed||`` button to wait for the user to press the Enter button.
```blocks
brick.showImage(images.informationStop1)
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
```
## Step 3
Add all the motor and sensor code you want after those blocks!
```blocks
brick.showImage(images.informationStop1)
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
brick.showImage(images.expressionsBigSmile)
motors.largeBC.tank(50, 50, 1, MoveUnit.Seconds)
```

View File

@ -0,0 +1,9 @@
# Pause Until Pressed
This is a code example to detect contact or collision with another object. It uses a touch sensor to detect hitting a wall or other obstacle. The motors are run and then stopped when the sensor is pressed.
```blocks
motors.largeBC.tank(50, 50)
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
motors.largeBC.stop()
```

View File

@ -0,0 +1,12 @@
# Pivot Turn
A **pivot turn** happens when a [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf) turns around the wheel on the inside of the turn by spinning just the single wheel at the outside of the turn.
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
```blocks
forever(function() {
motors.largeBC.tank(50, 0, 2, MoveUnit.Rotations)
motors.largeBC.tank(0, 50, 2, MoveUnit.Rotations)
})
```

View File

@ -0,0 +1,24 @@
# Reflected light calibration
The ``||sensors:calibrateLight||`` blocks allows you to calibrate the reflected light of the color sensor in one block. At the time you run the block, move the sensor over a dark surface and a bright surface; then stop moving it.
```blocks
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
brick.showString("dark", 2)
})
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Bright, function () {
brick.showString("bright", 2)
})
console.sendToScreen()
console.log("move color sensor")
console.log("over DARK and BRIGHT color")
console.log("and stop moving when done")
console.log("press ENTER when ready")
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
sensors.color3.calibrateLight(LightIntensityMode.Reflected)
brick.showValue("dark", sensors.color3.threshold(Light.Dark), 4)
brick.showValue("bright", sensors.color3.threshold(Light.Bright), 5)
forever(function () {
brick.showValue("reflected light", sensors.color3.light(LightIntensityMode.Reflected), 1)
})
```

View File

@ -0,0 +1,29 @@
# Reflected light measure
This example uses a color sensor to measure the reflected light from a dark and light surface
and sets the light/dark thresholds.
```blocks
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
brick.showString("dark", 2)
})
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Bright, function () {
brick.showString("bright", 2)
})
console.sendToScreen()
console.log("move color sensor")
console.log("over DARK color")
console.log("press ENTER when ready")
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
sensors.color3.setThreshold(Light.Dark, sensors.color3.light(LightIntensityMode.Reflected) + 5)
console.logValue("dark", sensors.color3.threshold(Light.Dark))
console.log("move color sensor")
console.log("over BRIGHT color")
console.log("press ENTER when ready")
brick.buttonEnter.pauseUntil(ButtonEvent.Pressed)
sensors.color3.setThreshold(Light.Bright, sensors.color3.light(LightIntensityMode.Reflected) - 5)
console.logValue("bright", sensors.color3.threshold(Light.Bright))
forever(function () {
brick.showValue("reflected light", sensors.color3.light(LightIntensityMode.Reflected), 1)
})
```

View File

@ -0,0 +1,12 @@
# Smooth Turn
A **smooth turn** happens when a [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf) makes a turn by spinning both both wheels but with each running at a different speed.
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
```blocks
forever(function() {
motors.largeBC.tank(50, 20, 2, MoveUnit.Rotations)
motors.largeBC.tank(20, 50, 2, MoveUnit.Rotations)
})
```

View File

@ -0,0 +1,12 @@
# Spin Turn
A **spin turn** happens when a [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf) turns, or rotates, on a single spot by spinning both wheels, but with each turning in opposite directions.
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
```blocks
forever(function() {
motors.largeBC.tank(50, -50, 2, MoveUnit.Rotations)
motors.largeBC.tank(-50, 50, 2, MoveUnit.Rotations)
})
```

View File

@ -0,0 +1,9 @@
# Stop At Object
This is a code example to detect contact or collision with another object. It uses a touch sensor to detect hitting a wall or other obstacle. The motors are run and then stopped when the sensor is pressed.
```blocks
motors.largeBC.tank(50, 50)
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
motors.largeBC.stop()
```

View File

@ -0,0 +1,17 @@
# Tank ZigZag
This example shows how to use the [tank](/reference/motors/tank) block to keep the speed of 2 large motors synchronized. The [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
) will move in a zig zag pattern.
```blocks
/**
* Use the tank block to keep large motors synched.
Use this code with a EV3 driving base.
*/
forever(function () {
brick.showImage(images.eyesMiddleRight)
motors.largeBC.tank(50, 10, 2, MoveUnit.Rotations)
brick.showImage(images.eyesMiddleLeft)
motors.largeBC.tank(10, 50, 2, MoveUnit.Rotations)
})
```

View File

@ -0,0 +1,31 @@
# Touch Sensor
## Tutorials
```codecard
[{
"name": "Touch to Run",
"description": "Press the Touch Sensor and run a motor.",
"cardType": "tutorial",
"url":"/tutorials/touch-to-run",
"imageUrl":"/static/tutorials/touch-to-run.png"
}, {
"name": "Sensor Values",
"description": "Check the value of a Touch Sensor and stop a motor if pressed.",
"cardType": "tutorial",
"url":"/tutorials/touch-sensor-values",
"imageUrl":"/static/tutorials/touch-sensor-values.png"
}, {
"name": "Stop At Object",
"description": "Waits for the sensor to be pressed before continuing the program",
"cardType": "tutorial",
"url":"/tutorials/stop-at-object",
"imageUrl":"/static/tutorials/pause-until-pressed.png"
}]
```
## See Also
[Touch to Run](/tutorials/touch-to-run),
[Touch Sensor Values](/tutorials/touch-sensor-values),
[Stop At Object](/tutorials/stop-at-object)

View File

@ -0,0 +1,43 @@
# Turn With Gyro
## Introduction @fullscreen
Use the gyro to measure how much the robot is turning, regardless if your wheels are slipping.
## Step 1 Calibrate
Add the ``||sensors:calibrate gyro||`` block to make sure your gyro is ready to use.
```blocks
sensors.gyro2.calibrate()
```
## Step 2 Turn
Use motor blocks to make the robot turn. Don't go too fast!
```blocks
sensors.gyro2.calibrate()
motors.largeBC.steer(200, 20)
```
## Step 3 Pause for turn
Use the ``||sensors:pause until rotated||`` block to wait until the desired amount of rotation has occured.
```blocks
sensors.gyro2.calibrate()
motors.largeBC.steer(200, 20)
sensors.gyro2.pauseUntilRotated(90)
```
## Step 4 Stop
Stop the motors!
```blocks
sensors.gyro2.calibrate()
motors.largeBC.steer(200, 20)
sensors.gyro2.pauseUntilRotated(90)
motors.stopAll()
```

52
docs/tutorials/turtle.md Normal file
View File

@ -0,0 +1,52 @@
# Turtle
A fun interactive program where the user enters a sequence of moves using the buttons and the robot executes it.
```blocks
/**
* Run this program with a driving base.
**/
let indent = ""
let command = ""
let c = ""
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
command = command + "L"
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
command = command + "R"
})
brick.buttonUp.onEvent(ButtonEvent.Pressed, function () {
command = command + "F"
})
brick.buttonDown.onEvent(ButtonEvent.Pressed, function () {
command = command + "B"
})
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
indent = ""
for (let index = 0; index <= command.length; index++) {
c = command[index]
brick.showString("" + indent + c, 4)
indent = "" + indent + " "
if (c == "L") {
motors.largeBC.steer(-100, 50, 378, MoveUnit.Degrees)
} else if (c == "R") {
motors.largeBC.steer(100, 50, 378, MoveUnit.Degrees)
} else if (c == "F") {
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
} else if (c == "B") {
motors.largeBC.steer(0, -50, 1, MoveUnit.Rotations)
}
}
command = ""
brick.showString("", 2)
})
motors.largeBC.setBrake(true)
forever(function () {
brick.showString("TURTLE", 1)
brick.showString(command, 3)
brick.showString("up/down: forward/backward", 8)
brick.showString("left/right: turn", 9)
brick.showString("enter: play commands", 10)
})
```

View File

@ -0,0 +1,24 @@
# Infrared sensor
## Tutorials
```codecard
[{
"name": "Object Near",
"description": "Detect if objects are near.",
"cardType": "tutorial",
"url":"/tutorials/object-near",
"imageUrl":"/static/tutorials/object-near.png"
}, {
"name": "Wall Follower",
"description": "Follow a wall at a distance using the ultrasonic sensor and a proportional controller.",
"cardType": "tutorial",
"url":"/tutorials/wall-follower",
"imageUrl":"/static/tutorials/wall-follower.png"
}]
```
## See Also
[Object Near?](/tutorials/object-near),
[Wall Follower](/tutorials/wall-follower)

View File

@ -0,0 +1,191 @@
# Wall Follower
## Introduction @unplugged
This tutorial shows you how to use the ultrasonic sensor to
move a [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
along a wall.
Your ultrasonic sensor should be placed horizontally, near the driving wheel, facing the wall.
## Step 1 Measure distance
Declare a new variable ``distance`` and store the distance from
the ultrasonic sensor on port 4.
```blocks
let distance = 0
forever(function () {
distance = sensors.ultrasonic4.distance()
})
```
## Step 2 Show distance
Use a ``||brick:show value||`` block to display the distance value on the screen.
This is **very** helpful when you are debugging your code on the robot.
Once your code is ready, download it to your robot and check that the measured distance looks ok.
```blocks
let distance = 0
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
})
```
## Step 3 Goal
Declare a new variable ``goal`` and assign it to ``10`` in ``on start``.
The value should be the distance in centimeters between your robot and the wall.
```blocks
let goal = 0
goal = 10
```
## Step 4 Compute Error
Declare a new variable ``error`` and assign a difference between ``distance`` and ``goal``.
We will use this value to determine how much the robot needs to correct its trajectory.
```blocks
let distance = 0
let goal = 0
let error = 0
goal = 10
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
error = distance - goal
brick.showValue("error", error, 2)
})
```
## Step 5 Show Error
Just like ``distance``, use ``||brick:show value||`` to display the value of the error (line 2).
This will allow you to debug your code while it is running on the robot.
Download your program to the robot and check that the error goes to ``0`` when
the robot is around 10cm from the wall.
```blocks
let distance = 0
let goal = 0
let error = 0
goal = 10
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
error = distance - goal
brick.showValue("error", error, 2)
})
```
## Step 6 Kp
Declare a new variable ``kp`` and assign it to ``1``.
This number determines how to convert the error into a ``turn ratio`` for the steer block.
For starter, set it to 1 and we will go through the steps to tune its value later on.
As usual, also use ``||brick:show value||`` to display the value of ``kp`` on the screen (line 3).
```blocks
let distance = 0
let goal = 0
let error = 0
let kp = 0
goal = 10
kp = 1
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
error = distance - goal
brick.showValue("error", error, 2)
brick.showValue("kp", kp, 3)
})
```
## Step 7 Turn ratio
Declare a new variable ``turnratio`` and store the product of ``error`` and ``kp`` in it.
Also use ``||brick:show value||`` to display its value on screen.
Download the program on the robot and try moving the robot around the wall. You should see
the value of ``turnratio`` change similarly to ``error``.
```blocks
let distance = 0
let goal = 0
let error = 0
let kp = 0
let turnratio = 0
goal = 10
kp = 1
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
error = distance - goal
brick.showValue("error", error, 2)
brick.showValue("kp", kp, 3)
turnratio = error * kp
brick.showValue("turn", turnratio, 4)
})
```
## Step 8 Steering
Add a ``||motors:steer motors||`` block for ``large B+C`` at 35% and place the ``turnratio``
variable for the turn value.
Download the code to your robot and try it out. Does it follow the wall?...
Not really, this is because we need to tune the ``kp`` variable.
```blocks
let distance = 0
let goal = 0
let error = 0
let kp = 0
let turnratio = 0
goal = 10
kp = 1
forever(function () {
distance = sensors.ultrasonic4.distance()
brick.showValue("distance", distance, 1)
error = distance - goal
brick.showValue("error", error, 2)
brick.showValue("kp", kp, 3)
turnratio = error * kp
brick.showValue("turn", turnratio, 4)
motors.largeBC.steer(turnratio, 35)
})
```
## Step 9 Tuning kp
As mentioned in a previous step, we need to find the right value for kp so that the robot
follows the wall properly. This tuning can be tedious so we are going to the brick buttons
to speed up the process.
Add ``||brick:on button||`` blocks to handle the left and right button pressed. When left is pressed, change ``kp`` by ``-1``. When right is pressed, change ``kp`` by 1.
Download your code to the robot and change the values of ``kp`` until the robot follows the wall. (Tip try something around -5 / -10).
```blocks
let kp = 0
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
kp += -1
})
brick.buttonRight.onEvent(ButtonEvent.Pressed, function () {
kp += 1
})
```
## Step 10 @unplugged
Well done! Your robot is using the ultrasonic distance
to correct is trajectory using a proportional controller!
The robot will be more precise if it goes slow... Try using a variable
and the brick up and down events to control the speed as well.

33
docs/videos.md Normal file
View File

@ -0,0 +1,33 @@
# Videos
## Tutorials
```codecard
[
{
"name": "",
"url": "https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5d009e5f93fbf479c2e5ed2bf87a7990&source=embed&photo%5fid=35719444",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288170/35719444/5d009e5f93fbf479c2e5ed2bf87a7990/thumbnail.png"
},
{
"name": "",
"url": "https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=2008a566f1fb034d58d5ebe19ba8621f&source=embed&photo%5fid=35719467",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288175/35719467/2008a566f1fb034d58d5ebe19ba8621f/thumbnail.png"
},
{
"name": "",
"url": "https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=629730c938e452f0fd7653fbc4708166&source=embed&photo%5fid=35719470",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288172/35719470/629730c938e452f0fd7653fbc4708166/thumbnail.png"
},
{
"name": "",
"url": "https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=3513a83b87fe536b2dc512237465fd1b&source=embed&photo%5fid=35719471",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288172/35719471/3513a83b87fe536b2dc512237465fd1b/thumbnail.png"
},
{
"name": "",
"url": "https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5c594c2373367f7870196f519f3bfc7a&source=embed&photo%5fid=35719472",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288175/35719472/5c594c2373367f7870196f519f3bfc7a/thumbnail.png"
}
]
```

View File

@ -2,72 +2,236 @@
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
import UF2 = pxtc.UF2;
import { Ev3Wrapper } from "./wrap";
export let ev3: pxt.editor.Ev3Wrapper
export let ev3: Ev3Wrapper;
let confirmAsync: (options: any) => Promise<number>;
export function setConfirmAsync(cf: (options: any) => Promise<number>) {
confirmAsync = cf;
}
export function debug() {
return initAsync()
return initHidAsync()
.then(w => w.downloadFileAsync("/tmp/dmesg.txt", v => console.log(pxt.Util.uint8ArrayToString(v))))
}
function hf2Async() {
return pxt.HF2.mkPacketIOAsync()
.then(h => {
let w = new pxt.editor.Ev3Wrapper(h)
ev3 = w
return w.reconnectAsync(true)
.then(() => w)
})
// Web Serial API https://wicg.github.io/serial/
// chromium bug https://bugs.chromium.org/p/chromium/issues/detail?id=884928
// Under experimental features in Chrome Desktop 77+
enum ParityType {
"none",
"even",
"odd",
"mark",
"space"
}
declare interface SerialOptions {
baudrate?: number;
databits?: number;
stopbits?: number;
parity?: ParityType;
buffersize?: number;
rtscts?: boolean;
xon?: boolean;
xoff?: boolean;
xany?: boolean;
}
type SerialPortInfo = pxt.Map<string>;
type SerialPortRequestOptions = any;
declare class SerialPort {
open(options?: SerialOptions): Promise<void>;
close(): void;
readonly readable: any;
readonly writable: any;
//getInfo(): SerialPortInfo;
}
declare interface Serial extends EventTarget {
onconnect: any;
ondisconnect: any;
getPorts(): Promise<SerialPort[]>
requestPort(options: SerialPortRequestOptions): Promise<SerialPort>;
}
let noHID = false
class WebSerialPackageIO implements pxt.HF2.PacketIO {
onData: (v: Uint8Array) => void;
onError: (e: Error) => void;
onEvent: (v: Uint8Array) => void;
onSerial: (v: Uint8Array, isErr: boolean) => void;
sendSerialAsync: (buf: Uint8Array, useStdErr: boolean) => Promise<void>;
private _reader: any;
private _writer: any;
let initPromise: Promise<pxt.editor.Ev3Wrapper>
export function initAsync() {
if (initPromise)
return initPromise
constructor(private port: SerialPort, private options: SerialOptions) {
}
let canHID = false
async readSerialAsync() {
this._reader = this.port.readable.getReader();
let buffer: Uint8Array;
const reader = this._reader;
while (reader === this._reader) { // will change if we recycle the connection
const { done, value } = await this._reader.read()
if (!buffer) buffer = value;
else { // concat
let tmp = new Uint8Array(buffer.length + value.byteLength)
tmp.set(buffer, 0)
tmp.set(value, buffer.length)
buffer = tmp;
}
if (buffer && buffer.length >= 6) {
this.onData(new Uint8Array(buffer));
buffer = undefined;
}
}
}
static isSupported(): boolean {
return !!(<any>navigator).serial;
}
static async mkPacketIOAsync(): Promise<pxt.HF2.PacketIO> {
const serial = (<any>navigator).serial;
if (serial) {
try {
const requestOptions: SerialPortRequestOptions = {};
const port = await serial.requestPort(requestOptions);
const options: SerialOptions = {
baudrate: 460800,
buffersize: 4096
};
return new WebSerialPackageIO(port, options);
} catch (e) {
console.log(`connection error`, e)
}
}
throw new Error("could not open serial port");
}
error(msg: string): any {
console.error(msg);
throw new Error(lf("error on brick ({0})", msg))
}
private openAsync() {
console.log(`serial: opening port`)
if (!!this._reader) return Promise.resolve();
this._reader = undefined;
this._writer = undefined;
return this.port.open(this.options)
.then(() => {
this.readSerialAsync();
return Promise.resolve();
});
}
private closeAsync() {
console.log(`serial: closing port`);
this.port.close();
this._reader = undefined;
this._writer = undefined;
return Promise.delay(500);
}
reconnectAsync(): Promise<void> {
return this.openAsync();
}
disconnectAsync(): Promise<void> {
return this.closeAsync();
}
sendPacketAsync(pkt: Uint8Array): Promise<void> {
if (!this._writer)
this._writer = this.port.writable.getWriter();
return this._writer.write(pkt);
}
}
function hf2Async() {
const pktIOAsync: Promise<pxt.HF2.PacketIO> = useWebSerial
? WebSerialPackageIO.mkPacketIOAsync() : pxt.HF2.mkPacketIOAsync()
return pktIOAsync.then(h => {
let w = new Ev3Wrapper(h)
ev3 = w
return w.reconnectAsync(true)
.then(() => w)
})
}
let useHID = false;
let useWebSerial = false;
export function initAsync(): Promise<void> {
if (pxt.U.isNodeJS) {
// doesn't seem to work ATM
canHID = false
useHID = false
} else {
const forceHexDownload = /forceHexDownload/i.test(window.location.href);
if (pxt.Cloud.isLocalHost() && pxt.Cloud.localToken && !forceHexDownload)
canHID = true
const nodehid = /nodehid/i.test(window.location.href);
if (pxt.Cloud.isLocalHost() && pxt.Cloud.localToken && nodehid)
useHID = true;
}
if (noHID)
canHID = false
if (WebSerialPackageIO.isSupported())
pxt.tickEvent("webserial.supported");
if (canHID) {
initPromise = hf2Async()
return Promise.resolve();
}
export function canUseWebSerial() {
return WebSerialPackageIO.isSupported();
}
export function enableWebSerialAsync() {
initPromise = undefined;
useWebSerial = WebSerialPackageIO.isSupported();
useHID = useWebSerial;
if (useWebSerial)
return initHidAsync().then(() => { });
else return Promise.resolve();
}
function cleanupAsync() {
if (ev3) {
console.log('cleanup previous port')
return ev3.disconnectAsync()
.catch(e => { })
.finally(() => { ev3 = undefined; });
}
return Promise.resolve();
}
let initPromise: Promise<Ev3Wrapper>
function initHidAsync() { // needs to run within a click handler
if (initPromise)
return initPromise
if (useHID) {
initPromise = cleanupAsync()
.then(() => hf2Async())
.catch(err => {
console.error(err);
initPromise = null
noHID = true
return Promise.reject(err)
useHID = false;
useWebSerial = false;
return Promise.reject(err);
})
} else {
noHID = true
useHID = false
useWebSerial = false;
initPromise = Promise.reject(new Error("no HID"))
}
return initPromise
return initPromise;
}
// this comes from aux/pxt.lms
const fspath = "../prjs/BrkProg_SAVE/"
const rbfTemplate = `
4c45474f580000006d000100000000001c000000000000000e000000821b038405018130813e8053
74617274696e672e2e2e0084006080XX00448581644886488405018130813e80427965210084000a
`
export function deployCoreAsync(resp: pxtc.CompileResult) {
let w: pxt.editor.Ev3Wrapper
let filename = resp.downloadFileBaseName || "pxt"
filename = filename.replace(/^lego-/, "")
let fspath = "../prjs/BrkProg_SAVE/"
let elfPath = fspath + filename + ".elf"
let rbfPath = fspath + filename + ".rbf"
@ -107,27 +271,54 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
return Promise.resolve();
}
if (noHID) return saveUF2Async()
if (!useHID) return saveUF2Async()
return initAsync()
pxt.tickEvent("webserial.flash");
let w: Ev3Wrapper;
return initHidAsync()
.then(w_ => {
w = w_
if (w.isStreaming)
pxt.U.userError("please stop the program first")
return w.stopAsync()
return w.reconnectAsync(false)
.catch(e => {
// user easily forgets to stop robot
if (confirmAsync)
return confirmAsync({
header: lf("Bluetooth download failed..."),
htmlBody:
`<ul>
<li>${lf("Make sure to stop your program or exit portview on the EV3.")}</li>
<li>${lf("Check your battery level.")}</li>
<li>${lf("Close EV3 LabView or other MakeCode editor tabs.")}
</ul>`,
hasCloseIcon: true,
hideCancel: true,
hideAgree: false,
agreeLbl: lf("Try again"),
}).then(() => w.disconnectAsync())
.then(() => Promise.delay(1000))
.then(() => w.reconnectAsync());
// nothing we can do
return Promise.reject(e);
})
})
.then(() => w.stopAsync())
.then(() => w.rmAsync(elfPath))
.then(() => w.flashAsync(elfPath, UF2.readBytes(origElfUF2, 0, origElfUF2.length * 256)))
.then(() => w.flashAsync(rbfPath, rbfBIN))
.then(() => w.runAsync(rbfPath))
.then(() => Promise.delay(500))
.then(() => {
pxt.tickEvent("webserial.success");
return w.disconnectAsync()
//return Promise.delay(1000).then(() => w.dmesgAsync())
}).catch(e => {
// if we failed to initalize, retry
if (noHID)
return saveUF2Async()
else
return Promise.reject(e)
pxt.tickEvent("webserial.fail");
useHID = false;
useWebSerial = false;
// if we failed to initalize, tell the user to retry
return Promise.reject(e)
})
}

View File

@ -1,28 +1,28 @@
/// <reference path="../node_modules/pxt-core/built/pxteditor.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
import { deployCoreAsync, initAsync } from "./deploy";
import { deployCoreAsync, initAsync, canUseWebSerial, enableWebSerialAsync, setConfirmAsync } from "./deploy";
let bluetoothDialogShown = false;
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
const projectView = opts.projectView;
pxt.debug('loading pxt-ev3 target extensions...')
function enableWebSerialAndCompileAsync() {
return enableWebSerialAsync()
.then(() => Promise.delay(500))
.then(() => projectView.compile());
}
const res: pxt.editor.ExtensionResult = {
deployCoreAsync,
showUploadInstructionsAsync: (fn: string, url: string, confirmAsync: (options: any) => Promise<number>) => {
let resolve: (thenableOrResult?: void | PromiseLike<void>) => void;
let reject: (error: any) => void;
const deferred = new Promise<void>((res, rej) => {
resolve = res;
reject = rej;
});
const boardName = pxt.appTarget.appTheme.boardName || "???";
const boardDriveName = pxt.appTarget.appTheme.driveDisplayName || pxt.appTarget.compile.driveName || "???";
setConfirmAsync(confirmAsync);
// https://msdn.microsoft.com/en-us/library/cc848897.aspx
// "For security reasons, data URIs are restricted to downloaded resources.
// Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements"
const downloadAgain = !pxt.BrowserUtils.isIE() && !pxt.BrowserUtils.isEdge();
const docUrl = pxt.appTarget.appTheme.usbDocs;
const saveAs = pxt.BrowserUtils.hasSaveAs();
const htmlBody = `
<div class="ui grid stackable">
@ -84,7 +84,38 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
hideAgree: false,
agreeLbl: lf("I got it"),
className: 'downloaddialog',
buttons: [downloadAgain ? {
buttons: [canUseWebSerial() ? {
label: lf("Bluetooth"),
icon: "bluetooth",
className: "bluetooth focused",
onclick: () => {
pxt.tickEvent("bluetooth.enable");
if (bluetoothDialogShown) {
enableWebSerialAndCompileAsync().done();
} else {
bluetoothDialogShown = true;
confirmAsync({
header: lf("Bluetooth pairing"),
hasCloseIcon: true,
hideCancel: true,
buttons: [{
label: lf("Help"),
icon: "question circle",
className: "lightgrey",
url: "/bluetooth"
}],
htmlBody: `<p>
${lf("You will be prompted to select a serial port.")}
${pxt.BrowserUtils.isWindows()
? lf("Look for 'Standard Serial over Bluetooth link'.")
: lf("Loop for 'cu.EV3-SerialPort'.")}
${lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")}
</p>
`
}).then(() => enableWebSerialAndCompileAsync())
}
}
} : undefined, downloadAgain ? {
label: fn,
icon: "download",
className: "lightgrey focused",

View File

@ -1,285 +1,286 @@
namespace pxt.editor {
import HF2 = pxt.HF2
import U = pxt.U
/**
* See https://www.lego.com/cdn/cs/set/assets/blt6879b00ae6951482/LEGO_MINDSTORMS_EV3_Communication_Developer_Kit.pdf
* https://github.com/mindboards/ev3sources/blob/master/lms2012/lms2012/source/bytecodes.h#L146
*/
import HF2 = pxt.HF2
import U = pxt.U
function log(msg: string) {
pxt.log("EWRAP: " + msg)
function log(msg: string) {
pxt.log("serial: " + msg)
}
export interface DirEntry {
name: string;
md5?: string;
size?: number;
}
const runTemplate = "C00882010084XX0060640301606400"
const usbMagic = 0x3d3f
const DIRECT_COMMAND_NO_REPLY = 0x80
export class Ev3Wrapper {
msgs = new U.PromiseBuffer<Uint8Array>()
private cmdSeq = U.randomUint32() & 0xffff;
private lock = new U.PromiseQueue();
isStreaming = false;
dataDump = /talkdbg=1/.test(window.location.href);
constructor(public io: pxt.HF2.PacketIO) {
io.onData = buf => {
buf = buf.slice(0, HF2.read16(buf, 0) + 2)
if (HF2.read16(buf, 4) == usbMagic) {
let code = HF2.read16(buf, 6)
let payload = buf.slice(8)
if (code == 1) {
let str = U.uint8ArrayToString(payload)
if (U.isNodeJS)
pxt.debug("SERIAL: " + str.replace(/\n+$/, ""))
else
window.postMessage({
type: 'serial',
id: 'n/a', // TODO?
data: str
}, "*")
} else
pxt.debug("Magic: " + code + ": " + U.toHex(payload))
return
}
if (this.dataDump)
log("RECV: " + U.toHex(buf))
this.msgs.push(buf)
}
}
export interface DirEntry {
name: string;
md5?: string;
size?: number;
private allocCore(addSize: number, replyType: number) {
let len = 5 + addSize
let buf = new Uint8Array(len)
HF2.write16(buf, 0, len - 2) // pktLen
HF2.write16(buf, 2, this.cmdSeq++) // msgCount
buf[4] = replyType
return buf
}
const runTemplate = "C00882010084XX0060640301606400"
const usbMagic = 0x3d3f
private allocSystem(addSize: number, cmd: number, replyType = 1) {
let buf = this.allocCore(addSize + 1, replyType)
buf[5] = cmd
return buf
}
export class Ev3Wrapper {
msgs = new U.PromiseBuffer<Uint8Array>()
private cmdSeq = U.randomUint32() & 0xffff;
private lock = new U.PromiseQueue();
isStreaming = false;
dataDump = false;
private allocCustom(code: number, addSize = 0) {
let buf = this.allocCore(1 + 2 + addSize, 0)
HF2.write16(buf, 4, usbMagic)
HF2.write16(buf, 6, code)
return buf
}
constructor(public io: pxt.HF2.PacketIO) {
io.onData = buf => {
buf = buf.slice(0, HF2.read16(buf, 0) + 2)
if (HF2.read16(buf, 4) == usbMagic) {
let code = HF2.read16(buf, 6)
let payload = buf.slice(8)
if (code == 1) {
let str = U.uint8ArrayToString(payload)
if (Util.isNodeJS)
console.log("SERIAL: " + str.replace(/\n+$/, ""))
else
window.postMessage({
type: 'serial',
id: 'n/a', // TODO?
data: str
}, "*")
} else
console.log("Magic: " + code + ": " + U.toHex(payload))
return
}
if (this.dataDump)
log("RECV: " + U.toHex(buf))
this.msgs.push(buf)
}
}
private allocCore(addSize: number, replyType: number) {
let len = 5 + addSize
let buf = new Uint8Array(len)
HF2.write16(buf, 0, len - 2) // pktLen
HF2.write16(buf, 2, this.cmdSeq++) // msgCount
buf[4] = replyType
return buf
}
private allocSystem(addSize: number, cmd: number, replyType = 1) {
let buf = this.allocCore(addSize + 1, replyType)
buf[5] = cmd
return buf
}
private allocCustom(code: number, addSize = 0) {
let buf = this.allocCore(1 + 2 + addSize, 0)
HF2.write16(buf, 4, usbMagic)
HF2.write16(buf, 6, code)
return buf
}
stopAsync() {
return this.isVmAsync()
.then(vm => {
if (vm) return Promise.resolve();
log(`stopping PXT app`)
let buf = this.allocCustom(2)
return this.justSendAsync(buf)
.then(() => Promise.delay(500))
})
}
dmesgAsync() {
log(`asking for DMESG buffer over serial`)
let buf = this.allocCustom(3)
return this.justSendAsync(buf)
}
runAsync(path: string) {
let codeHex = runTemplate.replace("XX", U.toHex(U.stringToUint8Array(path)))
let code = U.fromHex(codeHex)
let pkt = this.allocCore(2 + code.length, 0)
HF2.write16(pkt, 5, 0x0800)
U.memcpy(pkt, 7, code)
log(`run ${path}`)
return this.justSendAsync(pkt)
}
justSendAsync(buf: Uint8Array) {
return this.lock.enqueue("talk", () => {
this.msgs.drain()
if (this.dataDump)
log("SEND: " + U.toHex(buf))
return this.io.sendPacketAsync(buf)
})
}
talkAsync(buf: Uint8Array, altResponse = 0) {
return this.lock.enqueue("talk", () => {
this.msgs.drain()
if (this.dataDump)
log("TALK: " + U.toHex(buf))
return this.io.sendPacketAsync(buf)
.then(() => this.msgs.shiftAsync(1000))
.then(resp => {
if (resp[2] != buf[2] || resp[3] != buf[3])
U.userError("msg count de-sync")
if (buf[4] == 1) {
if (altResponse != -1 && resp[5] != buf[5])
U.userError("cmd de-sync")
if (altResponse != -1 && resp[6] != 0 && resp[6] != altResponse)
U.userError("cmd error: " + resp[6])
}
return resp
})
})
}
flashAsync(path: string, file: Uint8Array) {
log(`write ${file.length} bytes to ${path}`)
let handle = -1
let loopAsync = (pos: number): Promise<void> => {
if (pos >= file.length) return Promise.resolve()
let size = file.length - pos
if (size > 1000) size = 1000
let upl = this.allocSystem(1 + size, 0x93, 0x1)
upl[6] = handle
U.memcpy(upl, 6 + 1, file, pos, size)
return this.talkAsync(upl, 8) // 8=EOF
.then(() => loopAsync(pos + size))
}
let begin = this.allocSystem(4 + path.length + 1, 0x92)
HF2.write32(begin, 6, file.length) // fileSize
U.memcpy(begin, 10, U.stringToUint8Array(path))
return this.lock.enqueue("file", () =>
this.talkAsync(begin)
.then(resp => {
handle = resp[7]
return loopAsync(0)
}))
}
lsAsync(path: string): Promise<DirEntry[]> {
let lsReq = this.allocSystem(2 + path.length + 1, 0x99)
HF2.write16(lsReq, 6, 1024) // maxRead
U.memcpy(lsReq, 8, U.stringToUint8Array(path))
return this.talkAsync(lsReq, 8)
.then(resp =>
U.uint8ArrayToString(resp.slice(12)).split(/\n/).map(s => {
if (!s) return null as DirEntry
let m = /^([A-F0-9]+) ([A-F0-9]+) ([^\/]*)$/.exec(s)
if (m)
return {
md5: m[1],
size: parseInt(m[2], 16),
name: m[3]
}
else
return {
name: s.replace(/\/$/, "")
}
}).filter(v => !!v))
}
rmAsync(path: string): Promise<void> {
log(`rm ${path}`)
let rmReq = this.allocSystem(path.length + 1, 0x9c)
U.memcpy(rmReq, 6, U.stringToUint8Array(path))
return this.talkAsync(rmReq, 5)
.then(resp => { })
}
isVmAsync(): Promise<boolean> {
let path = "/no/such/dir"
let mkdirReq = this.allocSystem(path.length + 1, 0x9b)
U.memcpy(mkdirReq, 6, U.stringToUint8Array(path))
return this.talkAsync(mkdirReq, -1)
.then(resp => {
let isVM = resp[6] == 0x05
log(`${isVM ? "PXT app" : "VM"} running`)
return isVM
})
}
private streamFileOnceAsync(path: string, cb: (d: Uint8Array) => void) {
let fileSize = 0
let filePtr = 0
let handle = -1
let resp = (buf: Uint8Array): Promise<void> => {
if (buf[6] == 2) {
// handle not ready - file is missing
this.isStreaming = false
return Promise.resolve()
}
if (buf[6] != 0 && buf[6] != 8)
U.userError("bad response when streaming file: " + buf[6] + " " + U.toHex(buf))
this.isStreaming = true
fileSize = HF2.read32(buf, 7)
if (handle == -1) {
handle = buf[11]
log(`stream on, handle=${handle}`)
}
let data = buf.slice(12)
filePtr += data.length
if (data.length > 0)
cb(data)
if (buf[6] == 8) {
// end of file
this.isStreaming = false
return this.rmAsync(path)
}
let contFileReq = this.allocSystem(1 + 2, 0x97)
HF2.write16(contFileReq, 7, 1000) // maxRead
contFileReq[6] = handle
return Promise.delay(data.length > 0 ? 0 : 500)
.then(() => this.talkAsync(contFileReq, -1))
.then(resp)
}
let getFileReq = this.allocSystem(2 + path.length + 1, 0x96)
HF2.write16(getFileReq, 6, 1000) // maxRead
U.memcpy(getFileReq, 8, U.stringToUint8Array(path))
return this.talkAsync(getFileReq, -1).then(resp)
}
streamFileAsync(path: string, cb: (d: Uint8Array) => void) {
let loop = (): Promise<void> =>
this.lock.enqueue("file", () =>
this.streamFileOnceAsync(path, cb))
stopAsync() {
return this.isVmAsync()
.then(vm => {
if (vm) return Promise.resolve();
log(`stopping PXT app`)
let buf = this.allocCustom(2)
return this.justSendAsync(buf)
.then(() => Promise.delay(500))
.then(loop)
return loop()
})
}
dmesgAsync() {
log(`asking for DMESG buffer over serial`)
let buf = this.allocCustom(3)
return this.justSendAsync(buf)
}
runAsync(path: string) {
let codeHex = runTemplate.replace("XX", U.toHex(U.stringToUint8Array(path)))
let code = U.fromHex(codeHex)
let pkt = this.allocCore(2 + code.length, DIRECT_COMMAND_NO_REPLY)
HF2.write16(pkt, 5, 0x0800)
U.memcpy(pkt, 7, code)
log(`run ${path}`)
return this.justSendAsync(pkt)
}
justSendAsync(buf: Uint8Array) {
return this.lock.enqueue("talk", () => {
this.msgs.drain()
if (this.dataDump)
log("SEND: " + U.toHex(buf))
return this.io.sendPacketAsync(buf)
})
}
talkAsync(buf: Uint8Array, altResponse = 0) {
return this.lock.enqueue("talk", () => {
this.msgs.drain()
if (this.dataDump)
log("TALK: " + U.toHex(buf))
return this.io.sendPacketAsync(buf)
.then(() => this.msgs.shiftAsync(1000))
.then(resp => {
if (resp[2] != buf[2] || resp[3] != buf[3])
U.userError("msg count de-sync")
if (buf[4] == 1) {
if (altResponse != -1 && resp[5] != buf[5])
U.userError("cmd de-sync")
if (altResponse != -1 && resp[6] != 0 && resp[6] != altResponse)
U.userError("cmd error: " + resp[6])
}
return resp
})
})
}
flashAsync(path: string, file: Uint8Array) {
log(`write ${file.length} bytes to ${path}`)
let handle = -1
let loopAsync = (pos: number): Promise<void> => {
if (pos >= file.length) return Promise.resolve()
let size = file.length - pos
if (size > 1000) size = 1000
let upl = this.allocSystem(1 + size, 0x93, 0x1)
upl[6] = handle
U.memcpy(upl, 6 + 1, file, pos, size)
return this.talkAsync(upl, 8) // 8=EOF
.then(() => loopAsync(pos + size))
}
let begin = this.allocSystem(4 + path.length + 1, 0x92)
HF2.write32(begin, 6, file.length) // fileSize
U.memcpy(begin, 10, U.stringToUint8Array(path))
return this.lock.enqueue("file", () =>
this.talkAsync(begin)
.then(resp => {
handle = resp[7]
return loopAsync(0)
}))
}
downloadFileAsync(path: string, cb: (d: Uint8Array) => void) {
return this.lock.enqueue("file", () =>
this.streamFileOnceAsync(path, cb))
}
lsAsync(path: string): Promise<DirEntry[]> {
let lsReq = this.allocSystem(2 + path.length + 1, 0x99)
HF2.write16(lsReq, 6, 1024) // maxRead
U.memcpy(lsReq, 8, U.stringToUint8Array(path))
private initAsync() {
return Promise.resolve()
return this.talkAsync(lsReq, 8)
.then(resp =>
U.uint8ArrayToString(resp.slice(12)).split(/\n/).map(s => {
if (!s) return null as DirEntry
let m = /^([A-F0-9]+) ([A-F0-9]+) ([^\/]*)$/.exec(s)
if (m)
return {
md5: m[1],
size: parseInt(m[2], 16),
name: m[3]
}
else
return {
name: s.replace(/\/$/, "")
}
}).filter(v => !!v))
}
rmAsync(path: string): Promise<void> {
log(`rm ${path}`)
let rmReq = this.allocSystem(path.length + 1, 0x9c)
U.memcpy(rmReq, 6, U.stringToUint8Array(path))
return this.talkAsync(rmReq, 5)
.then(resp => { })
}
isVmAsync(): Promise<boolean> {
let path = "/no/such/dir"
let mkdirReq = this.allocSystem(path.length + 1, 0x9b)
U.memcpy(mkdirReq, 6, U.stringToUint8Array(path))
return this.talkAsync(mkdirReq, -1)
.then(resp => {
let isVM = resp[6] == 0x05
log(`${isVM ? "PXT app" : "VM"} running`)
return isVM
})
}
private streamFileOnceAsync(path: string, cb: (d: Uint8Array) => void) {
let fileSize = 0
let filePtr = 0
let handle = -1
let resp = (buf: Uint8Array): Promise<void> => {
if (buf[6] == 2) {
// handle not ready - file is missing
this.isStreaming = false
return Promise.resolve()
}
if (buf[6] != 0 && buf[6] != 8)
U.userError("bad response when streaming file: " + buf[6] + " " + U.toHex(buf))
this.isStreaming = true
fileSize = HF2.read32(buf, 7)
if (handle == -1) {
handle = buf[11]
log(`stream on, handle=${handle}`)
}
let data = buf.slice(12)
filePtr += data.length
if (data.length > 0)
cb(data)
if (buf[6] == 8) {
// end of file
this.isStreaming = false
return this.rmAsync(path)
}
let contFileReq = this.allocSystem(1 + 2, 0x97)
HF2.write16(contFileReq, 7, 1000) // maxRead
contFileReq[6] = handle
return Promise.delay(data.length > 0 ? 0 : 500)
.then(() => this.talkAsync(contFileReq, -1))
.then(resp)
}
private resetState() {
let getFileReq = this.allocSystem(2 + path.length + 1, 0x96)
HF2.write16(getFileReq, 6, 1000) // maxRead
U.memcpy(getFileReq, 8, U.stringToUint8Array(path))
return this.talkAsync(getFileReq, -1).then(resp)
}
}
reconnectAsync(first = false): Promise<void> {
this.resetState()
if (first) return this.initAsync()
log(`reconnect`);
return this.io.reconnectAsync()
.then(() => this.initAsync())
}
disconnectAsync() {
log(`disconnect`);
return this.io.disconnectAsync()
}
streamFileAsync(path: string, cb: (d: Uint8Array) => void) {
let loop = (): Promise<void> =>
this.lock.enqueue("file", () =>
this.streamFileOnceAsync(path, cb))
.then(() => Promise.delay(500))
.then(loop)
return loop()
}
}
downloadFileAsync(path: string, cb: (d: Uint8Array) => void) {
return this.lock.enqueue("file", () =>
this.streamFileOnceAsync(path, cb))
}
private initAsync() {
return Promise.resolve()
}
private resetState() {
}
reconnectAsync(first = false): Promise<void> {
this.resetState()
if (first) return this.initAsync()
log(`reconnect`);
return this.io.reconnectAsync()
.then(() => this.initAsync())
}
disconnectAsync() {
log(`disconnect`);
return this.io.disconnectAsync()
}
}

13
ev3.code-workspace Normal file
View File

@ -0,0 +1,13 @@
{
"folders": [
{
"path": "."
},
{
"path": "../pxt-common-packages"
},
{
"path": "../pxt"
}
]
}

View File

@ -133,14 +133,27 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
this.setText(text);
}
getFirstValue(text: string) {
// Get first set of words up until last space
return this.normalizeText_(text.substring(0, text.lastIndexOf(' ')));
getFirstValue(value: string) {
const typeValue = value.indexOf('large') != -1 ? 'large' : 'medium';
const portValue = this.getSecondValue(value);
const isDual = portValue.length > 1;
return `${typeValue} motor${isDual ? 's' : ''}`;
}
getSecondValue(text: string) {
// Get last word
return this.normalizeText_(text.match(/\S*$/)[0]);
getSecondValue(value: string) {
return (value.indexOf('large') != -1) ?
value.substring(value.indexOf('large') + 5) :
value.substring(value.indexOf('medium') + 6);
}
getFirstValueI11n(value: string) {
const firstValue = this.getFirstValue(value);
const motorOptions = {
'medium motor': lf('medium motor'),
'large motor': lf('large motor'),
'large motors': lf('large motors')
}
return motorOptions[firstValue];
}
private normalizeText_(text: string) {
@ -198,8 +211,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
if (text === null) {
return text;
}
if (text.indexOf(' ') == -1) {
text = `large motors ${text}`;
if (text.indexOf('|') == -1) {
text = this.sourceBlock_.RTL ? `${text}|${lf("large motors")}` : `${lf("large motors")}|${text}`;
}
return text;
}
@ -296,16 +309,14 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
goog.dom.removeChildren(/** @type {!Element} */(this.textElement_));
goog.dom.removeChildren(/** @type {!Element} */(this.textElement2_));
var text = this.text_;
text = this.patchDualMotorText(text);
// First dropdown
const textNode1 = document.createTextNode(this.getFirstValue(text));
// Use one of the following options, medium motor, large motor or large motors (translated)
const textNode1 = document.createTextNode(this.getFirstValueI11n(this.value_));
this.textElement_.appendChild(textNode1);
// Second dropdown
// Second dropdown, no need to translate. Only port numbers
if (this.textElement2_) {
const textNode2 = document.createTextNode(this.getSecondValue(text));
const textNode2 = document.createTextNode(this.getSecondValue(this.value_));
this.textElement2_.appendChild(textNode2);
}
this.updateWidth();
@ -402,29 +413,28 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
contentDiv.setAttribute('aria-haspopup', 'true');
let options = this.getOptions();
// Hashmap of options
let opts = {};
let conts = {};
let vals = {};
// Go through all option values and split them into groups
for (let opt = 0; opt < options.length; opt++) {
let text = options[opt][0].alt ? options[opt][0].alt : options[opt][0];
if (text.indexOf(' ') == -1) {
// Patch dual motors as they don't have prefixes.
text = this.patchDualMotorText(text);
if (options[opt][0].alt) options[opt][0].alt = text;
}
const value = options[opt][1];
const firstValue = this.getFirstValue(text);
const secondValue = this.getSecondValue(text);
if (!opts[firstValue]) opts[firstValue] = [secondValue];
else opts[firstValue].push(secondValue);
// Store a hash of the original key value pairs for later
const motorValue = value.substring(value.indexOf('.') + 1);
const typeValue = motorValue.indexOf('large') == 0 ? 'large' : 'medium';
const portValue = motorValue.indexOf('large') == 0 ? motorValue.substring(5) : motorValue.substring(6);
const isDual = portValue.length > 1;
const text = `${typeValue} motor${isDual ? 's' : ''}|${portValue}`;
const key = `${typeValue} motor${isDual ? 's' : ''}`;
if (!opts[key]) opts[key] = [];
opts[key].push(portValue);
conts[text] = options[opt][0];
vals[text] = value;
}
const currentFirst = this.getFirstValue(this.text_);
const currentSecond = this.getSecondValue(this.text_);
const currentFirst = this.getFirstValue(this.value_);
const currentSecond = this.getSecondValue(this.value_);
if (!this.isFirst_) {
options = opts[currentFirst];
@ -432,9 +442,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
options = Object.keys(opts);
// Flip the first and second options to make it sorted the way we want it (medium, large, dual)
if (options.length == 3) {
const temp = options[1];
options[1] = options[0];
options[0] = temp;
options = [lf("medium motor"), lf("large motor"), lf("large motors")];
} else {
options.reverse();
}
@ -448,7 +456,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
const columns = options.length;
for (let i = 0, option: any; option = options[i]; i++) {
let text = this.isFirst_ ? option + ' ' + opts[option][0] : currentFirst + ' ' + option;
let text = this.isFirst_ ? option + '|' + (option.indexOf('motors') != -1 ? 'BC' : 'A') : currentFirst + '|' + option;
text = text.replace(/\xA0/g, ' ');
const content: any = conts[text];
const value = vals[text];
@ -466,7 +474,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
button.setAttribute('id', ':' + i); // For aria-activedescendant
button.setAttribute('role', 'menuitem');
button.setAttribute('class', 'blocklyDropDownButton');
button.title = this.isFirst_ ? this.getFirstValue(content.alt) : content.alt;
button.title = this.isFirst_ ? this.getFirstValueI11n(value) : this.getSecondValue(value);
button.style.width = ((this.itemWidth_) - 8) + 'px';
button.style.height = ((this.itemWidth_) - 8) + 'px';
let backgroundColor = this.backgroundColour_;
@ -495,7 +503,15 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
contentDiv.removeAttribute('aria-activedescendant');
});
let buttonImg = document.createElement('img');
buttonImg.src = this.isFirst_ ? isFirstUrl[option.replace(/\xA0/g, ' ')] : content.src;
let imgSrc = content.src;
if (this.isFirst_) {
const motorValue = value.substring(value.indexOf('.') + 1);
// Find out what kind of motor this is based on it's value, possible values: mediumX, largeX, and largeXY
if (motorValue.indexOf('medium') == 0) imgSrc = isFirstUrl['medium motor'];
else if (motorValue.length == 6) imgSrc = isFirstUrl['large motor'];
else imgSrc = isFirstUrl['large motors'];
}
buttonImg.src = imgSrc;
//buttonImg.alt = icon.alt;
// Upon click/touch, we will be able to get the clicked element as e.target
// Store a data attribute on all possible click targets so we can match it to the icon.

View File

@ -76,9 +76,10 @@ export class FieldSpeed extends Blockly.FieldSlider implements Blockly.FieldCust
};
setReadout_(readout: Element, value: string) {
this.updateSpeed(parseFloat(value));
let x = parseFloat(value) || 0;
this.updateSpeed(x);
// Update reporter
this.reporter.textContent = `${value}%`;
this.reporter.textContent = `${x}%`;
}
private updateSpeed(speed: number) {

View File

@ -23,7 +23,7 @@ export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.Field
* @constructor
*/
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
super(String(value_), '-100', '100', null, '10', 'TurnRatio', opt_validator);
super(String(value_), '-200', '200', null, '10', 'TurnRatio', opt_validator);
this.params = params;
(this as any).sliderColor_ = '#a8aaa8';
}
@ -76,26 +76,26 @@ export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.Field
if (!this.path_) {
return;
}
let v = goog.math.clamp(parseFloat(this.getText()), -100, 100);
let v = goog.math.clamp(parseFloat(this.getText()), -200, 200);
if (isNaN(v)) {
v = 0;
}
const x = goog.math.clamp(parseFloat(this.getText()), -100, 100) / 100;
const theta = x * Math.PI / 2;
const cx = FieldTurnRatio.HALF;
const cy = FieldTurnRatio.HALF - 14;
const gamma = Math.PI - 2 * theta;
const r = FieldTurnRatio.RADIUS;
const alpha = 0.2 + Math.abs(x) * 0.5;
const x1 = 0;
const x = v / 100;
const nx = Math.max(-1, Math.min(1, x));
const theta = Math.max(nx) * Math.PI / 2;
const r = FieldTurnRatio.RADIUS - 6;
let cx = FieldTurnRatio.HALF;
const cy = FieldTurnRatio.HALF - 22;
if (Math.abs(x) > 1) {
cx -= (x - (x > 0 ? 1 : -1)) * r / 2; // move center of circle
}
const alpha = 0.2 + Math.abs(nx) * 0.5;
const y1 = r * alpha;
const y2 = r * Math.sin(Math.PI / 2 - theta);
const x2 = r * Math.cos(Math.PI / 2 - theta);
const y3 = y2 - r * alpha * Math.cos(2 * theta);
const x3 = x2 - r * alpha * Math.sin(2 * theta);
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
this.path_.setAttribute('d', d);

View File

@ -1,41 +0,0 @@
import jobs.generation.Utilities;
import jobs.generation.InternalUtilities;
def project = GithubProject
def projectName = "pxt-ev3"
[true, false].each { isPR ->
def newJobName = projectName
if (isPR) {
newJobName += "_PR"
} else {
newJobName += "_Push"
}
def newJob = job(newJobName) {
steps {
shell("chmod +x ./jenkins.sh")
shell("./jenkins.sh ${isPR}")
}
if (!isPR) {
wrappers {
credentialsBinding {
string("PXT_ACCESS_TOKEN", "pxt_access_token")
string("PXT_RELEASE_REPO", "pxt_release_repo_ev3")
string("CROWDIN_KEY", "pxt_crowdin_key")
}
}
}
}
Utilities.setMachineAffinity(newJob, "Ubuntu", "20161020")
InternalUtilities.standardJobSetup(newJob, project, isPR, "*/*")
if (isPR) {
Utilities.addGithubPRTrigger(newJob, "Default Testing")
} else {
Utilities.addGithubPushTrigger(newJob)
}
}

View File

@ -1,56 +0,0 @@
#!/usr/bin/env bash
# Set up NVM
export NVM_DIR="/home/dotnet-bot/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 8
# Set up build environment variables
echo ---------- Setting build environment variables
echo Git branch: $GIT_BRANCH
echo isPR: $1
originRegex="^origin/.*"
branchRegex="^origin/\K.*(?=$)"
releaseBranchRegex="^(master|v\d+)$"
if [[ "$GIT_BRANCH" =~ $originRegex ]]; then
branchName=$(echo ${GIT_BRANCH} | grep -oP $branchRegex)
echo Setting TRAVIS_BRANCH to ${branchName}
export TRAVIS_BRANCH=${branchName}
else
echo Setting TRAVIS_BRANCH to $GIT_BRANCH
export TRAVIS_BRANCH=$GIT_BRANCH
fi
if [ "$1" == "false" ]; then
echo Setting TRAVIS_PULL_REQUEST to false
export TRAVIS_PULL_REQUEST=false
if [[ "$TRAVIS_BRANCH" =~ $releaseBranchRegex ]]; then
if [[ -z $PXT_RELEASE_REPO ]]; then
echo Cannot find release repo\; skipping tag checks
else
gitTag=$(git describe --tags --exact-match 2> /dev/null)
builtTag=$(git ls-remote --tags $PXT_RELEASE_REPO | grep -o "refs/tags/$gitTag$")
echo Current tag: $gitTag
echo Built tag: $builtTag
if [[ ! -z $gitTag && -z $builtTag ]]; then
echo Built tag not found\; building tag
echo Setting TRAVIS_BRANCH to $gitTag
export TRAVIS_BRANCH=$gitTag
echo Setting TRAVIS_TAG to $gitTag
export TRAVIS_TAG=$gitTag
else
echo Not a tag build
fi
fi
fi
fi
# Perform build
npm install
npm test

Some files were not shown because too many files have changed in this diff Show More