Compare commits

...

13 Commits

Author SHA1 Message Date
Michal Moskal
e0aad7227f Add file listing and delete apis 2019-09-03 16:00:46 -07:00
Michal Moskal
aca1b4a764 Improve naming of command line programs 2019-09-03 16:00:33 -07:00
Peli de Halleux
349caa4aed 1.1.17 2019-09-02 20:58:29 -07:00
Peli de Halleux
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
Galen Nickel
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
Peli de Halleux
d5194b8d28 More samples (#896)
* coast or brake

* fix title

* added lesson
2019-08-31 06:05:36 -07:00
Peli de Halleux
12b1eb349b 1.1.16 2019-08-30 16:53:03 -07:00
Peli de Halleux
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
Peli de Halleux
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
Peli de Halleux
1fc818767c added vscode workspace 2019-08-30 13:57:27 -07:00
Peli de Halleux
9aeaec477f updated FLL page 2019-08-30 12:03:43 -07:00
Peli de Halleux
7fc796d2cb 1.1.15 2019-08-30 11:55:49 -07:00
Galen Nickel
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
39 changed files with 725 additions and 218 deletions

View File

@@ -19,11 +19,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

@@ -2,13 +2,15 @@
![FIRST LEGO League logo](/static/fll/fll-logo.png)
For teams participating in the Open Software Platform Pilot utilizing MakeCode, weve compiled a list of resources and information that we hope will be helpful for you.
**For teams participating in the Open Software Platform Pilot utilizing MakeCode**, 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 open an issue at https://github.com/microsoft/pxt-ev3/issues.
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?
@@ -108,9 +110,3 @@ For other common questions, try the FAQ page https://makecode.mindstorms.com/faq
>* 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
## Community connection
For questions, issues, feedback and community for the Open Software Platform Pilot:
We are using a messaging service called **Slack**. Slack can be accessed via an app you download to your computer or mobile device, and via a web interface. For more information about Slack, click [here](https://slack.com/). Anyone in the pilot can participate by signing up with Slack first, and then clicking this [FIRST LEGO League Robot SW](https://fllrobotsw.slack.com/join/shared_invite/enQtNDgxOTQ5MDc2OTkyLTg2ZTRkYzQ4OGMyZTg1OTZmMDFhMWNlOTQ1OWRlNDdmNzNmMjlhMmZiM2M3OWUxYjU1ODEwY2FmODJkNjZkOTA) link to join the Slack workspace.

View File

@@ -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

@@ -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,22 @@
# Schedule
Schedules an acceleration, constant and deceleration phase at a given speed.
```sig
motors.largeA.schedule(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.
## See also
[tank](/reference/motors/synced/tank), [steer](/reference/motors/synced/steer), [stop](/reference/motors/motor/stop)

View File

@@ -0,0 +1,20 @@
# Set Run Acceleration Ramp
```sig
motors.largeD.setRunAccelerationRamp(1, MoveUnit.Seconds)
```
## Examples
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
motors.largeB.run(50, 6, MoveUnit.Rotations)
})
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
motors.largeC.run(50, 6, MoveUnit.Seconds)
})
motors.largeB.setRunAccelerationRamp(360, MoveUnit.Degrees)
motors.largeB.setRunDecelerationRamp(360, MoveUnit.Degrees)
motors.largeC.setRunAccelerationRamp(2, MoveUnit.Seconds)
motors.largeC.setRunDecelerationRamp(2, MoveUnit.Seconds)
```

View File

@@ -0,0 +1,20 @@
# Set Run Deceleration Ramp
```sig
motors.largeD.setRunDecelerationRamp(1, MoveUnit.Seconds)
```
## Examples
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
motors.largeB.run(50, 6, MoveUnit.Rotations)
})
brick.buttonLeft.onEvent(ButtonEvent.Pressed, function () {
motors.largeC.run(50, 6, MoveUnit.Seconds)
})
motors.largeB.setRunAccelerationRamp(360, MoveUnit.Degrees)
motors.largeB.setRunDecelerationRamp(360, MoveUnit.Degrees)
motors.largeC.setRunAccelerationRamp(2, MoveUnit.Seconds)
motors.largeC.setRunDecelerationRamp(2, MoveUnit.Seconds)
```

View File

@@ -84,7 +84,7 @@ motors.stopAll()
### Tank tester
This program lets you change the tank values using the brick buttons
This program lets you change the tank values using the brick buttons.
```typescript
let tankB = 0;

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 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

View File

@@ -2,113 +2,41 @@
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": "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": "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)

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

@@ -0,0 +1,38 @@
# 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"
}]
```
## 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,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,43 @@
# 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": "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),

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": "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
[Object Near?](/tutorials/object-near),
[Security Alert](/tutorials/security-alert)

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

@@ -0,0 +1,52 @@
# 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"
}]
```
## 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)

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,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": "Pause Until Pressed",
"description": "Waits for the sensor to be pressed before continuing the program",
"cardType": "tutorial",
"url":"/tutorials/pause-until-pressed",
"imageUrl":"/static/tutorials/pause-until-pressed.png"
}]
```
## See Also
[Touch to Run](/tutorials/touch-to-run),
[Touch Sensor Values](/tutorials/touch-sensor-values),
[Pause Until Pressed](/tutorials/pause-until-pressed)

View File

@@ -63,7 +63,9 @@ const rbfTemplate = `
export function deployCoreAsync(resp: pxtc.CompileResult) {
let w: pxt.editor.Ev3Wrapper
let filename = resp.downloadFileBaseName || "pxt"
const origElfUF2 = UF2.parseFile(pxt.U.stringToUint8Array(ts.pxtc.decodeBase64(resp.outfiles[pxt.outputName()])))
let filename = resp.downloadFileBaseName || (origElfUF2[0].filename || "").replace(/^Projects\//, "").replace(/\.elf$/, "") || "pxt"
filename = filename.replace(/^lego-/, "")
let fspath = "../prjs/BrkProg_SAVE/"
@@ -77,8 +79,6 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
let rbfBIN = pxt.U.fromHex(rbfHex)
pxt.HF2.write16(rbfBIN, 4, rbfBIN.length)
let origElfUF2 = UF2.parseFile(pxt.U.stringToUint8Array(ts.pxtc.decodeBase64(resp.outfiles[pxt.outputName()])))
let mkFile = (ext: string, data: Uint8Array = null) => {
let f = UF2.newBlockFile()
f.filename = "Projects/" + filename + ext

13
ev3.code-workspace Normal file
View File

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

View File

@@ -23,6 +23,10 @@
#define MALLOC_LIMIT (8 * 1024 * 1024)
#define MALLOC_CHECK_PERIOD (1024 * 1024)
namespace Array_ {
RefCollection *mk(unsigned flags);
}
void *xmalloc(size_t sz) {
static size_t allocBytes = 0;
allocBytes += sz;
@@ -476,7 +480,7 @@ void stopLMS() {
if (!pid)
continue;
char namebuf[100];
snprintf(namebuf, 1000, "/proc/%d/cmdline", pid);
snprintf(namebuf, 100, "/proc/%d/cmdline", pid);
FILE *f = fopen(namebuf, "r");
if (f) {
fread(namebuf, 1, 99, f);
@@ -590,4 +594,66 @@ void dmesg(const char *format, ...) {
fflush(dmesgFile);
fdatasync(fileno(dmesgFile));
}
const char *progPath = "/mnt/ramdisk/prjs/BrkProg_SAVE";
//%
void deleteAllPrograms() {
char buf[1024];
struct dirent *ent;
DIR *dir;
dir = opendir(progPath);
if (dir == NULL)
return;
while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] == '.')
continue;
snprintf(buf, sizeof(buf), "%s/%s", progPath, ent->d_name);
DMESG("FN: %s", ent->d_name);
// unlink(buf);
}
closedir(dir);
}
//%
void deletePrjFile(String filename) {
if (strlen(filename->data) > 500 || strchr(filename->data, '/'))
return;
char buf[1024];
snprintf(buf, sizeof(buf), "%s/%s", progPath, filename->data);
unlink(buf);
}
//%
RefCollection *listPrjFiles() {
auto res = Array_::mk(0);
//registerGCObj(res);
auto dp = opendir(progPath);
for (;;) {
dirent *ep = dp ? readdir(dp) : NULL;
if (!ep)
break;
if (ep->d_name[0] == '.')
continue;
auto str = mkString(ep->d_name, -1);
//registerGCObj(str);
res->push((TValue)str);
//unregisterGCObj(str);
}
if (dp)
closedir(dp);
//unregisterGCObj(res);
return res;
}
} // namespace pxt

View File

@@ -127,31 +127,43 @@ namespace motors {
reset(Output.ALL)
}
interface MoveSchedule {
speed: number;
useSteps: boolean;
steps: number[];
}
//% fixedInstances
export class MotorBase extends control.Component {
protected _port: Output;
protected _portName: string;
protected _brake: boolean;
protected _regulated: boolean;
private _pauseOnRun: boolean;
private _initialized: boolean;
private _brakeSettleTime: number;
private _init: () => void;
private _run: (speed: number) => void;
private _move: (steps: boolean, stepsOrTime: number, speed: number) => void;
private _accelerationSteps: number;
private _accelerationTime: number;
private _decelerationSteps: number;
private _decelerationTime: number;
protected static output_types: number[] = [0x7, 0x7, 0x7, 0x7];
constructor(port: Output, init: () => void, run: (speed: number) => void, move: (steps: boolean, stepsOrTime: number, speed: number) => void) {
constructor(port: Output, init: () => void) {
super();
this._port = port;
this._portName = outputToName(this._port);
this._brake = false;
this._regulated = true;
this._pauseOnRun = true;
this._initialized = false;
this._brakeSettleTime = 10;
this._init = init;
this._run = run;
this._move = move;
this._accelerationSteps = 0;
this._accelerationTime = 0;
this._decelerationSteps = 0;
this._decelerationTime = 0;
}
/**
@@ -263,6 +275,34 @@ namespace motors {
reset(this._port);
}
private normalizeSchedule(speed: number, step1: number, step2: number, step3: number, unit: MoveUnit): MoveSchedule {
const r: MoveSchedule = {
speed: Math.clamp(-100, 100, speed >> 0),
useSteps: true,
steps: [step1, step2, step3]
}
let scale = 1;
switch (unit) {
case MoveUnit.Rotations:
scale = 360;
r.useSteps = true;
break;
case MoveUnit.Degrees:
r.useSteps = true;
break;
case MoveUnit.Seconds:
scale = 1000;
r.useSteps = false;
break;
default:
r.useSteps = false;
break;
}
for (let i = 0; i < r.steps.length; ++i)
r.steps[i] = Math.max(0, (r.steps[i] * scale) | 0);
return r;
}
/**
* Runs the motor at a given speed for limited time or distance.
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
@@ -277,41 +317,162 @@ namespace motors {
//% help=motors/motor/run
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
this.init();
speed = Math.clamp(-100, 100, speed >> 0);
const schedule = this.normalizeSchedule(speed, 0, value, 0, unit);
// stop if speed is 0
if (!speed) {
if (!schedule.speed) {
this.stop();
return;
}
// special: 0 is infinity
if (value == 0) {
this._run(speed);
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
this._run(schedule.speed);
return;
}
// timed motor moves
const steps = schedule.steps;
const useSteps = schedule.useSteps;
// compute ramp up and down
steps[0] = (useSteps ? this._accelerationSteps : this._accelerationTime) || 0;
steps[2] = (useSteps ? this._decelerationSteps : this._decelerationTime) || 0;
if (steps[0] + steps[2] > steps[1]) {
// rescale
const r = steps[1] / (steps[0] + steps[2]);
steps[0] = Math.floor(steps[0] * r);
steps[2] *= Math.floor(steps[2] * r);
}
steps[1] -= (steps[0] + steps[2]);
// send ramped command
this._schedule(schedule);
this.pauseOnRun(steps[0] + steps[1] + steps[2]);
}
/**
* Schedules a run of the motor with an acceleration, constant and deceleration phase.
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
* @param acceleration acceleration phase measured distance or rotation
* @param value measured distance or rotation
* @param deceleration deceleration phase measured distance or rotation
* @param unit (optional) unit of the value
*/
//% blockId=motorSchedule block="schedule %motor at %speed=motorSpeedPicker|\\%|for %acceleration|%value|%deceleration||%unit"
//% weight=99 blockGap=8
//% group="Move"
//% motor.fieldEditor="motors"
//% help=motors/motor/schedule
//% inlineInputMode=inline
schedule(speed: number, acceleration: number, value: number, deceleration: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
this.init();
const schedule = this.normalizeSchedule(speed, acceleration, value, deceleration, unit);
// stop if speed is 0
if (!schedule.speed) {
this.stop();
return;
}
// special case: do nothing
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
return;
}
// timed motor moves
let useSteps: boolean;
let stepsOrTime: number;
const steps = schedule.steps;
// send ramped command
this._schedule(schedule);
this.pauseOnRun(steps[0] + steps[1] + steps[2]);
}
/**
* Specifies the amount of rotation or time for the acceleration
* of run commands.
*/
//% blockId=outputMotorsetRunAcceleration block="set %motor|run acceleration to $value||$unit"
//% motor.fieldEditor="motors"
//% weight=21 blockGap=8
//% group="Properties"
//% help=motors/motor/set-run-acceleration-ramp
setRunAccelerationRamp(value: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
switch (unit) {
case MoveUnit.Rotations:
stepsOrTime = (value * 360) >> 0;
useSteps = true;
this._accelerationSteps = Math.max(0, (value * 360) | 0);
break;
case MoveUnit.Degrees:
stepsOrTime = value >> 0;
useSteps = true;
this._accelerationSteps = Math.max(0, value | 0);
break;
case MoveUnit.Seconds:
stepsOrTime = (value * 1000) >> 0;
useSteps = false;
this._accelerationTime = Math.max(0, (value * 1000) | 0);
break;
default:
stepsOrTime = value;
useSteps = false;
case MoveUnit.MilliSeconds:
this._accelerationTime = Math.max(0, value | 0);
break;
}
}
this._move(useSteps, stepsOrTime, speed);
this.pauseOnRun(stepsOrTime);
/**
* Specifies the amount of rotation or time for the acceleration
* of run commands.
*/
//% blockId=outputMotorsetRunDeceleration block="set %motor|run deceleration ramp to $value||$unit"
//% motor.fieldEditor="motors"
//% weight=20 blockGap=8
//% group="Properties"
//% help=motors/motor/set-run-deceleration-ramp
setRunDecelerationRamp(value: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
switch (unit) {
case MoveUnit.Rotations:
this._decelerationSteps = Math.max(0, (value * 360) | 0);
break;
case MoveUnit.Degrees:
this._decelerationSteps = Math.max(0, value | 0);
break;
case MoveUnit.Seconds:
this._decelerationTime = Math.max(0, (value * 1000) | 0);
break;
case MoveUnit.MilliSeconds:
this._decelerationTime = Math.max(0, value | 0);
break;
}
}
private _run(speed: number) {
// ramp up acceleration
if (this._accelerationTime) {
this._schedule({ speed: speed, useSteps: false, steps: [this._accelerationTime, 100, 0] });
pause(this._accelerationTime);
}
// keep going
const b = mkCmd(this._port, this._regulated ? DAL.opOutputSpeed : DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, speed)
writePWM(b)
if (speed) {
writePWM(mkCmd(this._port, DAL.opOutputStart, 0))
}
}
private _schedule(schedule: MoveSchedule) {
const p = {
useSteps: schedule.useSteps,
step1: schedule.steps[0],
step2: schedule.steps[1],
step3: schedule.steps[2],
speed: this._regulated ? schedule.speed : undefined,
power: this._regulated ? undefined : schedule.speed,
useBrake: this._brake
};
step(this._port, p)
}
/**
* Indicates if the motor(s) speed should be regulated. Default is true.
* @param value true for regulated motor
*/
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% motor.fieldEditor="motors"
//% weight=58 blockGap=8
//% group="Properties"
//% help=motors/motor/set-regulated
setRegulated(value: boolean) {
this._regulated = value;
}
/**
@@ -338,6 +499,10 @@ namespace motors {
pauseUntil(() => this.isReady(), timeOut);
}
setRunSmoothness(accelerationPercent: number, decelerationPercent: number) {
}
protected setOutputType(large: boolean) {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (this._port & (1 << i)) {
@@ -364,12 +529,10 @@ namespace motors {
//% fixedInstances
export class Motor extends MotorBase {
private _large: boolean;
private _regulated: boolean;
constructor(port: Output, large: boolean) {
super(port, () => this.__init(), (speed) => this.__setSpeed(speed), (steps, stepsOrTime, speed) => this.__move(steps, stepsOrTime, speed));
super(port, () => this.__init());
this._large = large;
this._regulated = true;
this.markUsed();
}
@@ -381,44 +544,6 @@ namespace motors {
this.setOutputType(this._large);
}
private __setSpeed(speed: number) {
const b = mkCmd(this._port, this._regulated ? DAL.opOutputSpeed : DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, speed)
writePWM(b)
if (speed) {
writePWM(mkCmd(this._port, DAL.opOutputStart, 0))
}
}
private __move(steps: boolean, stepsOrTime: number, speed: number) {
control.dmesg("motor.__move")
const p = {
useSteps: steps,
step1: 0,
step2: stepsOrTime,
step3: 0,
speed: this._regulated ? speed : undefined,
power: this._regulated ? undefined : speed,
useBrake: this._brake
};
control.dmesg("motor.1")
step(this._port, p)
control.dmesg("motor.__move end")
}
/**
* Indicates if the motor speed should be regulated. Default is true.
* @param value true for regulated motor
*/
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% motor.fieldEditor="motors"
//% weight=58 blockGap=8
//% group="Properties"
//% help=motors/motor/set-regulated
setRegulated(value: boolean) {
this._regulated = value;
}
/**
* Gets motor actual speed.
* @param motor the port which connects to the motor
@@ -506,7 +631,7 @@ namespace motors {
export class SynchedMotorPair extends MotorBase {
constructor(ports: Output) {
super(ports, () => this.__init(), (speed) => this.__setSpeed(speed), (steps, stepsOrTime, speed) => this.__move(steps, stepsOrTime, speed));
super(ports, () => this.__init());
this.markUsed();
}
@@ -518,24 +643,6 @@ namespace motors {
this.setOutputType(true);
}
private __setSpeed(speed: number) {
syncMotors(this._port, {
speed: speed,
turnRatio: 0, // same speed
useBrake: !!this._brake
})
}
private __move(steps: boolean, stepsOrTime: number, speed: number) {
syncMotors(this._port, {
useSteps: steps,
speed: speed,
turnRatio: 0, // same speed
stepsOrTime: stepsOrTime,
useBrake: this._brake
});
}
/**
* The Move Tank block can make a robot drive forward, backward, turn, or stop.
* Use the Move Tank block for robot vehicles that have two Large Motors,
@@ -745,26 +852,15 @@ namespace motors {
return
}
speed = Math.clamp(-100, 100, speed)
control.dmesg('speed: ' + speed)
let b = mkCmd(out, op, 15)
control.dmesg('STEP 5')
b.setNumber(NumberFormat.Int8LE, 2, speed)
// note that b[3] is padding
control.dmesg('STEP 1')
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 0, opts.step1)
control.dmesg('STEP 2')
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 1, opts.step2)
control.dmesg('STEP 3')
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 2, opts.step3)
control.dmesg('STEP 4')
control.dmesg('br ' + opts.useBrake);
const br = !!opts.useBrake ? 1 : 0;
control.dmesg('Step 4.5 ' + br)
b.setNumber(NumberFormat.Int8LE, 4 + 4 * 3, br)
control.dmesg('STEP 5')
writePWM(b)
control.dmesg('end step')
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "1.1.14",
"version": "1.1.17",
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
"private": false,
"keywords": [

View File

@@ -113,7 +113,7 @@
"docMenu": [
{
"name": "Support",
"path": "https://www.lego.com/service/"
"path": "https://forum.makecode.com/"
},
{
"name": "Troubleshoot",

View File

@@ -1,4 +1,5 @@
namespace pxsim {
const MIN_RAMP_SPEED = 3;
export class MotorNode extends BaseNode {
isOutput = true;
@@ -30,11 +31,11 @@ namespace pxsim {
}
getSpeed() {
return this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1);
return Math.round(this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1));
}
getAngle() {
return this.angle;
return Math.round(this.angle);
}
// returns the slave motor if any
@@ -64,7 +65,7 @@ namespace pxsim {
delete this.speedCmdValues;
delete this._synchedMotor;
this.setChangedState();
}
}
clearSyncCmd() {
if (this._synchedMotor)
@@ -160,13 +161,19 @@ namespace pxsim {
const dstep = isTimeCommand
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
if (dstep < step1) // rampup
if (step1 && dstep < step1) { // rampup
this.speed = speed * dstep / step1;
// ensure non-zero speed
this.speed = Math.max(MIN_RAMP_SPEED, Math.ceil(Math.abs(this.speed))) * Math.sign(speed);
}
else if (dstep < step1 + step2) // run
this.speed = speed;
else if (dstep < step1 + step2 + step3)
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
else {
else if (step2 && dstep < step1 + step2 + step3) {
this.speed = speed * (step1 + step2 + step3 - dstep)
/ (step1 + step2 + step3) + 5;
// ensure non-zero speed
this.speed = Math.max(MIN_RAMP_SPEED, Math.ceil(Math.abs(this.speed))) * Math.sign(speed);
} else {
if (brake) this.speed = 0;
if (!isTimeCommand) {
// we need to patch the actual position of the motor when
@@ -227,11 +234,10 @@ namespace pxsim {
this.angle = this.manualReferenceAngle + this.manualAngle;
this.setChangedState();
}
this.speed = Math.round(this.speed); // integer only
// don't round speed
// compute delta angle
const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed;
const deltaAngle = Math.round(rotations * 360);
const rotations = this.speed / 100 * this.rotationsPerMilliSecond * elapsed;
const deltaAngle = rotations * 360;
if (deltaAngle) {
this.angle += deltaAngle;
this.tacho += Math.abs(deltaAngle);

View File

@@ -9,7 +9,11 @@
},
"galleries": {
"Getting Started": "getting-started",
"Tutorials": "tutorials",
"Brick Tutorials": "tutorials/brick",
"Motor Tutorials": "tutorials/motors",
"Touch Sensor Tutorials": "tutorials/touch-sensor",
"Color Sensor Tutorials": "tutorials/color-sensor",
"Infrared Sensor Tutorials": "tutorials/infrared-sensor",
"Design Engineering": "design-engineering",
"Coding": "coding",
"Maker": "maker",