Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e0aad7227f | ||
|
aca1b4a764 | ||
|
349caa4aed | ||
|
56bbcde299 | ||
|
7e9cc791ec | ||
|
d5194b8d28 | ||
|
12b1eb349b | ||
|
68dc195ea4 | ||
|
0251b914f2 | ||
|
1fc818767c | ||
|
9aeaec477f | ||
|
7fc796d2cb | ||
|
cb1cd2a4b4 |
@@ -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)
|
||||
|
||||
|
12
docs/fll.md
@@ -2,13 +2,15 @@
|
||||
|
||||

|
||||
|
||||
For teams participating in the Open Software Platform Pilot utilizing MakeCode, we’ve 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**, we’ve 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.
|
||||
|
@@ -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"
|
||||
}
|
||||
]
|
||||
```
|
@@ -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
|
||||
|
22
docs/reference/motors/motor/schedule.md
Normal 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)
|
20
docs/reference/motors/motor/set-run-acceleration-ramp.md
Normal 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)
|
||||
```
|
20
docs/reference/motors/motor/set-run-deceleration-ramp.md
Normal 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)
|
||||
```
|
@@ -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
After Width: | Height: | Size: 4.4 KiB |
BIN
docs/static/tutorials/coast-or-brake.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/static/tutorials/pause-until-pressed.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/static/tutorials/pivot-turn.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/static/tutorials/reflected-light-calibration.png
vendored
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
docs/static/tutorials/reflected-light-measure.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
docs/static/tutorials/smooth-turn.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/static/tutorials/spin-turn.png
vendored
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/static/tutorials/tank-zigzag.png
vendored
Normal file
After Width: | Height: | Size: 19 KiB |
@@ -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
@@ -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),
|
16
docs/tutorials/coast-or-brake.md
Normal 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)
|
||||
})
|
||||
```
|
43
docs/tutorials/color-sensor.md
Normal 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),
|
24
docs/tutorials/infrared-sensor.md
Normal 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
@@ -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)
|
9
docs/tutorials/pause-until-pressed.md
Normal 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()
|
||||
```
|
12
docs/tutorials/pivot-turn.md
Normal 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)
|
||||
})
|
||||
```
|
24
docs/tutorials/reflected-light-calibration.md
Normal 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)
|
||||
})
|
||||
```
|
29
docs/tutorials/reflected-light-measure.md
Normal 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)
|
||||
})
|
||||
```
|
12
docs/tutorials/smooth-turn.md
Normal 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)
|
||||
})
|
||||
```
|
12
docs/tutorials/spin-turn.md
Normal 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)
|
||||
})
|
||||
```
|
17
docs/tutorials/tank-zigzag.md
Normal 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)
|
||||
})
|
||||
```
|
31
docs/tutorials/touch-sensor.md
Normal 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)
|
@@ -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
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../pxt-common-packages"
|
||||
},
|
||||
{
|
||||
"path": "../pxt"
|
||||
}
|
||||
]
|
||||
}
|
@@ -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
|
||||
|
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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": [
|
||||
|
@@ -113,7 +113,7 @@
|
||||
"docMenu": [
|
||||
{
|
||||
"name": "Support",
|
||||
"path": "https://www.lego.com/service/"
|
||||
"path": "https://forum.makecode.com/"
|
||||
},
|
||||
{
|
||||
"name": "Troubleshoot",
|
||||
|
@@ -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);
|
||||
|
@@ -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",
|
||||
|