Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
72a0940235 | |||
b08dd8a7d2 | |||
def648a98b | |||
32a92789b3 | |||
9956bb06fb | |||
83b9aecd7a | |||
17ab24eaa9 | |||
9c5d5f9a86 | |||
43a13e0877 | |||
fe0915484d | |||
87a65aa38f | |||
1317da8904 | |||
62b2881e2a | |||
bf482a2ac9 | |||
243600ad8f |
BIN
docs/file-manager.pdf
Normal file
BIN
docs/file-manager.pdf
Normal file
Binary file not shown.
15
docs/fll.md
15
docs/fll.md
@ -89,18 +89,11 @@ Sharing programs is also shown in the [Tips and Tricks](https://legoeducation.vi
|
|||||||
|
|
||||||
### Why can't I delete my program (*.uf2) files from the Brick?
|
### 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. As a workaround, you can temporarily downgrade your firmware version, delete the files, and then upgrade back to the version that works with MakeCode.
|
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.
|
||||||
|
|
||||||
Follow these steps to downgrade your firmware version, delete the files, and uprgade back again:
|
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.
|
||||||
1. Go into **EV3 LabVIEW** - if it's not installed get it [here](https://education.lego.com/en-us/downloads/mindstorms-ev3/software)
|
This will present you with an menu for deleting files.
|
||||||
2. Plug in your EV3 Brick and start a new project
|
|
||||||
3. Go to the **Tools** menu in the upper right corner, select **Firmware Update**
|
|
||||||
4. In the **Firmware Update** dialog box, click on the **Show Details** button
|
|
||||||
5. From the **Available Firmware Files** list, select **EV3 Firmware V1.09E**
|
|
||||||
6. Click the **Update Firmware** button and wait for the update to complete
|
|
||||||
|
|
||||||
Now the firmware version on the EV3 Brick will be **V1.09E**. Also, in the process, the downgrade deleted all of the saved programs from the EV3 Brick. To continue to use MakeCode, the firmware version must be at **V1.10E** or above. So, the Brick firmware needs to be upgraded again. If you don't know or do remember how to do this, see the **Upgrade your @drivename@** section in the [troubleshooting](/troubleshoot) page.
|
|
||||||
|
|
||||||
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.
|
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.
|
||||||
|
|
||||||
|
47
docs/reference/brick/battery-property.md
Normal file
47
docs/reference/brick/battery-property.md
Normal 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)
|
||||||
|
})
|
||||||
|
```
|
59
docs/reference/motors/motor/ramp.md
Normal file
59
docs/reference/motors/motor/ramp.md
Normal 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)
|
@ -1,22 +0,0 @@
|
|||||||
# 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)
|
|
30
docs/reference/motors/motor/set-brake-settle-time.md
Normal file
30
docs/reference/motors/motor/set-brake-settle-time.md
Normal 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)
|
@ -1,28 +1,28 @@
|
|||||||
# set Brake
|
# 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
|
```sig
|
||||||
motors.largeA.setBrake(false)
|
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.
|
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.
|
* **brake**: a [boolean](/types/boolean) value which is either `true` to set the brake on or `false` to set the brake off.
|
||||||
|
|
||||||
## Example
|
## 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
|
```blocks
|
||||||
|
motors.largeA.setBrake(true)
|
||||||
motors.largeA.run(30)
|
motors.largeA.run(30)
|
||||||
pause(2000)
|
pause(2000)
|
||||||
motors.largeA.stop()
|
motors.largeA.stop()
|
||||||
motors.largeA.setBrake(true)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# 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)
|
|
||||||
```
|
|
@ -1,20 +0,0 @@
|
|||||||
# 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)
|
|
||||||
```
|
|
26
docs/reference/motors/motor/set-run-phase.md
Normal file
26
docs/reference/motors/motor/set-run-phase.md
Normal 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)
|
||||||
|
})
|
||||||
|
```
|
BIN
docs/static/tutorials/wall-follower.png
vendored
Normal file
BIN
docs/static/tutorials/wall-follower.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -25,6 +25,11 @@ Step by step guides to coding your @boardname@.
|
|||||||
"description": "Use the color sensor to follow line or detect colors",
|
"description": "Use the color sensor to follow line or detect colors",
|
||||||
"url":"/tutorials/color-sensor",
|
"url":"/tutorials/color-sensor",
|
||||||
"imageUrl":"/static/tutorials/what-color.png"
|
"imageUrl":"/static/tutorials/what-color.png"
|
||||||
|
}, {
|
||||||
|
"name": "Ultrasonic Sensor",
|
||||||
|
"description": "Use the ultrasonic sensor to detect obstacles",
|
||||||
|
"url":"/tutorials/ultrasonic-sensor",
|
||||||
|
"imageUrl":"/static/tutorials/object-near.png"
|
||||||
}, {
|
}, {
|
||||||
"name": "Infrared Sensor",
|
"name": "Infrared Sensor",
|
||||||
"description": "Use the infrared sensor to detect objects",
|
"description": "Use the infrared sensor to detect objects",
|
||||||
|
@ -4,12 +4,6 @@
|
|||||||
|
|
||||||
```codecard
|
```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",
|
"name": "Security Alert",
|
||||||
"description": "Build an security alert using the Infrared Sensor.",
|
"description": "Build an security alert using the Infrared Sensor.",
|
||||||
"cardType": "tutorial",
|
"cardType": "tutorial",
|
||||||
@ -20,5 +14,4 @@
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
[Object Near?](/tutorials/object-near),
|
|
||||||
[Security Alert](/tutorials/security-alert)
|
[Security Alert](/tutorials/security-alert)
|
||||||
|
24
docs/tutorials/ultrasonic-sensor.md
Normal file
24
docs/tutorials/ultrasonic-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": "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)
|
191
docs/tutorials/wall-follower.md
Normal file
191
docs/tutorials/wall-follower.md
Normal 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.
|
@ -1,13 +1,40 @@
|
|||||||
|
|
||||||
|
const enum BatteryProperty {
|
||||||
|
//% block="level (%)"
|
||||||
|
Level,
|
||||||
|
//% block="current (I)"
|
||||||
|
Current,
|
||||||
|
//% block="voltage (V)"
|
||||||
|
Voltage
|
||||||
|
}
|
||||||
|
|
||||||
namespace brick {
|
namespace brick {
|
||||||
/**
|
/**
|
||||||
* Returns the current battery level
|
* Returns the current battery level
|
||||||
*/
|
*/
|
||||||
//% blockId=brickBatteryLevel block="battery level"
|
//% blockId=brickBatteryLevel block="battery level"
|
||||||
//% group="More"
|
//% group="Battery"
|
||||||
//% help=brick/battery-level
|
//% help=brick/battery-level
|
||||||
|
//% deprecated blockHidden=1
|
||||||
export function batteryLevel(): number {
|
export function batteryLevel(): number {
|
||||||
const info = sensors.internal.getBatteryInfo();
|
const info = sensors.internal.getBatteryInfo();
|
||||||
return info.current;
|
return info.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns information about the battery
|
||||||
|
*/
|
||||||
|
//% blockId=brickBatteryProperty block="battery %property"
|
||||||
|
//% group="Battery"
|
||||||
|
//% help=brick/battery-property
|
||||||
|
export function batteryInfo(property: BatteryProperty): number {
|
||||||
|
const info = sensors.internal.getBatteryInfo();
|
||||||
|
switch(property) {
|
||||||
|
case BatteryProperty.Level: return info.level;
|
||||||
|
case BatteryProperty.Current: return info.Ibatt;
|
||||||
|
case BatteryProperty.Voltage: return info.Vbatt;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,8 +36,17 @@ namespace sensors.internal {
|
|||||||
let analogMM: MMap
|
let analogMM: MMap
|
||||||
let uartMM: MMap
|
let uartMM: MMap
|
||||||
let IICMM: MMap
|
let IICMM: MMap
|
||||||
|
let powerMM: MMap
|
||||||
let devcon: Buffer
|
let devcon: Buffer
|
||||||
let sensorInfos: SensorInfo[]
|
let sensorInfos: SensorInfo[];
|
||||||
|
|
||||||
|
let batteryInfo: {
|
||||||
|
CinCnt: number;
|
||||||
|
CoutCnt: number;
|
||||||
|
VinCnt: number;
|
||||||
|
};
|
||||||
|
let batteryVMin: number;
|
||||||
|
let batteryVMax: number;
|
||||||
|
|
||||||
class SensorInfo {
|
class SensorInfo {
|
||||||
port: number
|
port: number
|
||||||
@ -71,10 +80,13 @@ namespace sensors.internal {
|
|||||||
IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
|
IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
|
||||||
if (!IICMM) control.fail("no iic sensor")
|
if (!IICMM) control.fail("no iic sensor")
|
||||||
|
|
||||||
|
powerMM = control.mmap("/dev/lms_power", 2, 0)
|
||||||
|
|
||||||
unsafePollForChanges(500,
|
unsafePollForChanges(500,
|
||||||
() => { return hashDevices(); },
|
() => { return hashDevices(); },
|
||||||
(prev, curr) => { detectDevices();
|
(prev, curr) => {
|
||||||
});
|
detectDevices();
|
||||||
|
});
|
||||||
sensorInfos.forEach(info => {
|
sensorInfos.forEach(info => {
|
||||||
unsafePollForChanges(50, () => {
|
unsafePollForChanges(50, () => {
|
||||||
if (info.sensor) return info.sensor._query()
|
if (info.sensor) return info.sensor._query()
|
||||||
@ -83,8 +95,7 @@ namespace sensors.internal {
|
|||||||
if (info.sensor) info.sensor._update(prev, curr)
|
if (info.sensor) info.sensor._update(prev, curr)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export function getActiveSensors(): Sensor[] {
|
export function getActiveSensors(): Sensor[] {
|
||||||
init();
|
init();
|
||||||
@ -110,18 +121,130 @@ namespace sensors.internal {
|
|||||||
return manufacturer + sensorType;
|
return manufacturer + sensorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBatteryInfo(): { temp: number; current: number } {
|
const ADC_REF = 5000 //!< [mV] maximal value on ADC
|
||||||
init();
|
const ADC_RES = 4095 //!< [CNT] maximal count on ADC
|
||||||
return {
|
// see c_ui.c
|
||||||
temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
|
const SHUNT_IN = 0.11 // [Ohm]
|
||||||
current: Math.round(analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent) / 10)
|
const AMP_CIN = 22.0 // [Times]
|
||||||
|
|
||||||
|
const EP2_SHUNT_IN = 0.05 // [Ohm]
|
||||||
|
const EP2_AMP_CIN = 15.0 // [Times]
|
||||||
|
|
||||||
|
const SHUNT_OUT = 0.055 // [Ohm]
|
||||||
|
const AMP_COUT = 19.0 // [Times]
|
||||||
|
|
||||||
|
const VCE = 0.05 // [V]
|
||||||
|
const AMP_VIN = 0.5 // [Times]
|
||||||
|
|
||||||
|
const AVR_CIN = 300
|
||||||
|
const AVR_COUT = 30
|
||||||
|
const AVR_VIN = 30
|
||||||
|
// lms2012
|
||||||
|
const BATT_INDICATOR_HIGH = 7500 //!< Battery indicator high [mV]
|
||||||
|
const BATT_INDICATOR_LOW = 6200 //!< Battery indicator low [mV]
|
||||||
|
const ACCU_INDICATOR_HIGH = 7500 //!< Rechargeable battery indicator high [mV]
|
||||||
|
const ACCU_INDICATOR_LOW = 7100 //!< Rechargeable battery indicator low [mV]
|
||||||
|
|
||||||
|
function CNT_V(C: number) {
|
||||||
|
return ((C * ADC_REF) / (ADC_RES * 1000.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBatteryInfo() {
|
||||||
|
let CinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent);
|
||||||
|
let CoutCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.MotorCurrent);
|
||||||
|
let VinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.Cell123456);
|
||||||
|
if (!batteryInfo) {
|
||||||
|
batteryVMin = BATT_INDICATOR_LOW;
|
||||||
|
batteryVMax = BATT_INDICATOR_HIGH;
|
||||||
|
if (powerMM) {
|
||||||
|
const accu = powerMM.getNumber(NumberFormat.UInt8LE, 0);
|
||||||
|
if (accu > 0) {
|
||||||
|
control.dmesg("rechargeable battery")
|
||||||
|
batteryVMin = ACCU_INDICATOR_LOW;
|
||||||
|
batteryVMax = ACCU_INDICATOR_HIGH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
batteryInfo = {
|
||||||
|
CinCnt: CinCnt,
|
||||||
|
CoutCnt: CoutCnt,
|
||||||
|
VinCnt: VinCnt
|
||||||
|
};
|
||||||
|
// update in background
|
||||||
|
control.runInParallel(() => forever(updateBatteryInfo));
|
||||||
|
} else {
|
||||||
|
CinCnt = batteryInfo.CinCnt = ((batteryInfo.CinCnt * (AVR_CIN - 1)) + CinCnt) / AVR_CIN;
|
||||||
|
CoutCnt = batteryInfo.CoutCnt = ((batteryInfo.CoutCnt * (AVR_COUT - 1)) + CoutCnt) / AVR_COUT;
|
||||||
|
VinCnt = batteryInfo.VinCnt = ((batteryInfo.VinCnt * (AVR_VIN - 1)) + VinCnt) / AVR_VIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getBatteryInfo(): {
|
||||||
|
level: number;
|
||||||
|
Ibatt: number,
|
||||||
|
Vbatt: number,
|
||||||
|
Imotor: number
|
||||||
|
} {
|
||||||
|
init();
|
||||||
|
if (!batteryInfo) updateBatteryInfo();
|
||||||
|
const CinCnt = batteryInfo.CinCnt;
|
||||||
|
const CoutCnt = batteryInfo.CoutCnt;
|
||||||
|
const VinCnt = batteryInfo.VinCnt;
|
||||||
|
/*
|
||||||
|
void cUiUpdatePower(void)
|
||||||
|
{
|
||||||
|
#ifndef Linux_X86
|
||||||
|
DATAF CinV;
|
||||||
|
DATAF CoutV;
|
||||||
|
|
||||||
|
if ((UiInstance.Hw == FINAL) || (UiInstance.Hw == FINALB))
|
||||||
|
{
|
||||||
|
CinV = CNT_V(UiInstance.CinCnt) / AMP_CIN;
|
||||||
|
UiInstance.Vbatt = (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
|
||||||
|
|
||||||
|
UiInstance.Ibatt = CinV / SHUNT_IN;
|
||||||
|
CoutV = CNT_V(UiInstance.CoutCnt) / AMP_COUT;
|
||||||
|
UiInstance.Imotor = CoutV / SHUNT_OUT;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CinV = CNT_V(UiInstance.CinCnt) / EP2_AMP_CIN;
|
||||||
|
UiInstance.Vbatt = (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
|
||||||
|
|
||||||
|
UiInstance.Ibatt = CinV / EP2_SHUNT_IN;
|
||||||
|
UiInstance.Imotor = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_TEMP_SHUTDOWN
|
||||||
|
|
||||||
|
UiInstance.Vbatt = 7.0;
|
||||||
|
UiInstance.Ibatt = 5.0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const CinV = CNT_V(CinCnt) / AMP_CIN;
|
||||||
|
const Vbatt = CNT_V(VinCnt) / AMP_VIN + CinV + VCE;
|
||||||
|
const Ibatt = CinV / SHUNT_IN;
|
||||||
|
const CoutV = CNT_V(CoutCnt) / AMP_COUT;
|
||||||
|
const Imotor = CoutV / SHUNT_OUT;
|
||||||
|
const level = Math.max(0, Math.min(100, Math.floor((Vbatt * 1000.0 - batteryVMin)
|
||||||
|
/ (batteryVMax - batteryVMin) * 100)));
|
||||||
|
|
||||||
|
return {
|
||||||
|
level: level,
|
||||||
|
Vbatt: Vbatt,
|
||||||
|
Ibatt: Ibatt,
|
||||||
|
Imotor: Imotor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function hashDevices(): number {
|
function hashDevices(): number {
|
||||||
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
|
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
|
||||||
let r = 0;
|
let r = 0;
|
||||||
for(let i = 0; i < conns.length; ++i) {
|
for (let i = 0; i < conns.length; ++i) {
|
||||||
r = (r << 8 | conns[i]);
|
r = (r << 8 | conns[i]);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -36,6 +36,13 @@ enum MoveUnit {
|
|||||||
MilliSeconds
|
MilliSeconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MovePhase {
|
||||||
|
//% block="acceleration"
|
||||||
|
Acceleration,
|
||||||
|
//% block="deceleration"
|
||||||
|
Deceleration
|
||||||
|
}
|
||||||
|
|
||||||
namespace motors {
|
namespace motors {
|
||||||
let pwmMM: MMap
|
let pwmMM: MMap
|
||||||
let motorMM: MMap
|
let motorMM: MMap
|
||||||
@ -226,6 +233,7 @@ namespace motors {
|
|||||||
//% weight=1 blockGap=8
|
//% weight=1 blockGap=8
|
||||||
//% group="Properties"
|
//% group="Properties"
|
||||||
//% millis.defl=200 millis.min=0 millis.max=500
|
//% millis.defl=200 millis.min=0 millis.max=500
|
||||||
|
//% help=motors/motor/set-brake-settle-time
|
||||||
setBrakeSettleTime(millis: number) {
|
setBrakeSettleTime(millis: number) {
|
||||||
this.init();
|
this.init();
|
||||||
// ensure in [0,500]
|
// ensure in [0,500]
|
||||||
@ -279,7 +287,7 @@ namespace motors {
|
|||||||
const r: MoveSchedule = {
|
const r: MoveSchedule = {
|
||||||
speed: Math.clamp(-100, 100, speed >> 0),
|
speed: Math.clamp(-100, 100, speed >> 0),
|
||||||
useSteps: true,
|
useSteps: true,
|
||||||
steps: [step1, step2, step3]
|
steps: [step1 || 0, step2 || 0, step3 || 0]
|
||||||
}
|
}
|
||||||
let scale = 1;
|
let scale = 1;
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
@ -352,18 +360,20 @@ namespace motors {
|
|||||||
/**
|
/**
|
||||||
* Schedules a run of the motor with an acceleration, constant and deceleration phase.
|
* 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 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, eg: 500
|
||||||
* @param value measured distance or rotation
|
* @param unit (optional) unit of the value, eg: MoveUnit.MilliSeconds
|
||||||
* @param deceleration deceleration phase measured distance or rotation
|
* @param acceleration acceleration phase measured distance or rotation, eg: 500
|
||||||
* @param unit (optional) unit of the value
|
* @param deceleration deceleration phase measured distance or rotation, eg: 500
|
||||||
*/
|
*/
|
||||||
//% blockId=motorSchedule block="schedule %motor at %speed=motorSpeedPicker|\\%|for %acceleration|%value|%deceleration||%unit"
|
//% blockId=motorSchedule block="ramp %motor at %speed=motorSpeedPicker|\\%|for %value|%unit||accelerate %acceleration|decelerate %deceleration"
|
||||||
//% weight=99 blockGap=8
|
//% weight=99 blockGap=8
|
||||||
//% group="Move"
|
//% group="Move"
|
||||||
//% motor.fieldEditor="motors"
|
//% motor.fieldEditor="motors"
|
||||||
//% help=motors/motor/schedule
|
//% help=motors/motor/ramp
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
schedule(speed: number, acceleration: number, value: number, deceleration: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
//% expandableArgumentMode=toggle
|
||||||
|
//% value.defl=500
|
||||||
|
ramp(speed: number, value: number = 500, unit: MoveUnit = MoveUnit.MilliSeconds, acceleration?: number, deceleration?: number) {
|
||||||
this.init();
|
this.init();
|
||||||
const schedule = this.normalizeSchedule(speed, acceleration, value, deceleration, unit);
|
const schedule = this.normalizeSchedule(speed, acceleration, value, deceleration, unit);
|
||||||
// stop if speed is 0
|
// stop if speed is 0
|
||||||
@ -386,50 +396,41 @@ namespace motors {
|
|||||||
* Specifies the amount of rotation or time for the acceleration
|
* Specifies the amount of rotation or time for the acceleration
|
||||||
* of run commands.
|
* of run commands.
|
||||||
*/
|
*/
|
||||||
//% blockId=outputMotorsetRunAcceleration block="set %motor|run acceleration to $value||$unit"
|
//% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit"
|
||||||
//% motor.fieldEditor="motors"
|
//% motor.fieldEditor="motors"
|
||||||
//% weight=21 blockGap=8
|
//% weight=21 blockGap=8
|
||||||
//% group="Properties"
|
//% group="Properties"
|
||||||
//% help=motors/motor/set-run-acceleration-ramp
|
//% help=motors/motor/set-run-phase
|
||||||
setRunAccelerationRamp(value: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
setRunPhase(phase: MovePhase, value: number, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||||
|
let temp: number;
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case MoveUnit.Rotations:
|
case MoveUnit.Rotations:
|
||||||
this._accelerationSteps = Math.max(0, (value * 360) | 0);
|
temp = Math.max(0, (value * 360) | 0);
|
||||||
|
if (phase == MovePhase.Acceleration)
|
||||||
|
this._accelerationSteps = temp;
|
||||||
|
else
|
||||||
|
this._decelerationSteps = temp;
|
||||||
break;
|
break;
|
||||||
case MoveUnit.Degrees:
|
case MoveUnit.Degrees:
|
||||||
this._accelerationSteps = Math.max(0, value | 0);
|
temp = Math.max(0, value | 0);
|
||||||
|
if (phase == MovePhase.Acceleration)
|
||||||
|
this._accelerationSteps = temp;
|
||||||
|
else
|
||||||
|
this._decelerationSteps = temp;
|
||||||
break;
|
break;
|
||||||
case MoveUnit.Seconds:
|
case MoveUnit.Seconds:
|
||||||
this._accelerationTime = Math.max(0, (value * 1000) | 0);
|
temp = Math.max(0, (value * 1000) | 0);
|
||||||
|
if (phase == MovePhase.Acceleration)
|
||||||
|
this._accelerationTime = temp;
|
||||||
|
else
|
||||||
|
this._decelerationTime = temp;
|
||||||
break;
|
break;
|
||||||
case MoveUnit.MilliSeconds:
|
case MoveUnit.MilliSeconds:
|
||||||
this._accelerationTime = Math.max(0, value | 0);
|
temp = Math.max(0, value | 0);
|
||||||
break;
|
if (phase == MovePhase.Acceleration)
|
||||||
}
|
this._accelerationTime = temp;
|
||||||
}
|
else
|
||||||
|
this._decelerationTime = temp;
|
||||||
/**
|
|
||||||
* 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
//% color="#68C3E2" weight=100 icon="\uf106"
|
//% color="#68C3E2" weight=100 icon="\uf106"
|
||||||
//% groups='["Buttons", "Screen"]'
|
//% groups='["Buttons", "Screen", "Battery"]'
|
||||||
//% labelLineWidth=60
|
//% labelLineWidth=60
|
||||||
namespace brick {
|
namespace brick {
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-ev3",
|
"name": "pxt-ev3",
|
||||||
"version": "1.1.17",
|
"version": "1.1.20",
|
||||||
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
||||||
"private": false,
|
"private": false,
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"Motor Tutorials": "tutorials/motors",
|
"Motor Tutorials": "tutorials/motors",
|
||||||
"Touch Sensor Tutorials": "tutorials/touch-sensor",
|
"Touch Sensor Tutorials": "tutorials/touch-sensor",
|
||||||
"Color Sensor Tutorials": "tutorials/color-sensor",
|
"Color Sensor Tutorials": "tutorials/color-sensor",
|
||||||
|
"Ultrasonic Sensor Tutorials": "tutorials/ultrasonic-sensor",
|
||||||
"Infrared Sensor Tutorials": "tutorials/infrared-sensor",
|
"Infrared Sensor Tutorials": "tutorials/infrared-sensor",
|
||||||
"Design Engineering": "design-engineering",
|
"Design Engineering": "design-engineering",
|
||||||
"Coding": "coding",
|
"Coding": "coding",
|
||||||
|
Reference in New Issue
Block a user