Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0aad7227f | ||
|
|
aca1b4a764 | ||
|
|
349caa4aed | ||
|
|
56bbcde299 | ||
|
|
7e9cc791ec | ||
|
|
d5194b8d28 |
@@ -6,9 +6,9 @@ Set the rotation speed of the motor as a percentage of maximum speed.
|
|||||||
motors.largeA.run(50)
|
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**.
|
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.
|
// Run motor for 700 Milliseconds.
|
||||||
motors.largeA.run(25, 700, MoveUnit.MilliSeconds);
|
motors.largeA.run(25, 700, MoveUnit.MilliSeconds);
|
||||||
|
|
||||||
// Run motor for 700 Milliseconds again but no units specified.
|
// Run motors B and C for 700 Milliseconds again but no units specified.
|
||||||
motors.largeA.run(25, 700);
|
motors.largeBC.run(25, 700);
|
||||||
|
|
||||||
// Run the motor for 45 seconds
|
// Run the motor for 45 seconds
|
||||||
motors.largeA.run(50, 45, MoveUnit.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
|
## Examples
|
||||||
|
|
||||||
### Drive the motor for 20 seconds
|
### Drive the motor for 20 seconds
|
||||||
|
|||||||
22
docs/reference/motors/motor/schedule.md
Normal file
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
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
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
|
### 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
|
```typescript
|
||||||
let tankB = 0;
|
let tankB = 0;
|
||||||
|
|||||||
BIN
docs/static/tutorials/coast-or-brake.png
vendored
Normal file
BIN
docs/static/tutorials/coast-or-brake.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/static/tutorials/pause-until-pressed.png
vendored
Normal file
BIN
docs/static/tutorials/pause-until-pressed.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
16
docs/tutorials/coast-or-brake.md
Normal file
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)
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"imageUrl":"/static/tutorials/pivot-turn.png"
|
"imageUrl":"/static/tutorials/pivot-turn.png"
|
||||||
}, {
|
}, {
|
||||||
"name": "Smooth Turn",
|
"name": "Smooth Turn",
|
||||||
"description": "Turn the driving base in a smooth motion.",
|
"description": "Turn the driving base in a smooth, steering motion.",
|
||||||
"cardType": "example",
|
"cardType": "example",
|
||||||
"url":"/tutorials/smooth-turn",
|
"url":"/tutorials/smooth-turn",
|
||||||
"imageUrl":"/static/tutorials/smooth-turn.png"
|
"imageUrl":"/static/tutorials/smooth-turn.png"
|
||||||
@@ -33,6 +33,12 @@
|
|||||||
"cardType": "example",
|
"cardType": "example",
|
||||||
"url":"/tutorials/tank-zigzag",
|
"url":"/tutorials/tank-zigzag",
|
||||||
"imageUrl":"/static/tutorials/tank-zigzag.png"
|
"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"
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -43,3 +49,4 @@
|
|||||||
[Pivot Turn](/tutorials/pivot-turn),
|
[Pivot Turn](/tutorials/pivot-turn),
|
||||||
[Smooth Turn](/tutorials/smooth-turn),
|
[Smooth Turn](/tutorials/smooth-turn),
|
||||||
[Tank ZigZag](/tutorials/tank-zigzag),
|
[Tank ZigZag](/tutorials/tank-zigzag),
|
||||||
|
[Coast Or Brake](/tutorials/coast-or-brake)
|
||||||
|
|||||||
9
docs/tutorials/pause-until-pressed.md
Normal file
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()
|
||||||
|
```
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Pivot Turn
|
# 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 a wheel by spinning a single wheel.
|
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 achieve turn with a ``tank`` or a ``steer`` block.
|
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
|
||||||
|
|
||||||
```blocks
|
```blocks
|
||||||
forever(function() {
|
forever(function() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Reflected light calibration
|
# Reflected light calibration
|
||||||
|
|
||||||
The ``calibrateLight`` blocks allows you to calibrate the reflected light of the color sensor in one block. Start the block and move the sensor over the dark and bright surface; then stop moving it.
|
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
|
```blocks
|
||||||
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
|
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Reflected light measure
|
# Reflected light measure
|
||||||
|
|
||||||
This example uses a color sensor to measure the reflected light on the dark and light surface
|
This example uses a color sensor to measure the reflected light from a dark and light surface
|
||||||
and set the light/dark thresholds.
|
and sets the light/dark thresholds.
|
||||||
|
|
||||||
```blocks
|
```blocks
|
||||||
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
|
sensors.color3.onLightDetected(LightIntensityMode.Reflected, Light.Dark, function () {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Smooth Turn
|
# 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) turns around both wheels at a different speed.
|
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 achieve turn with a ``tank`` or a ``steer`` block.
|
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
|
||||||
|
|
||||||
```blocks
|
```blocks
|
||||||
forever(function() {
|
forever(function() {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Spin Turn
|
# 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 on the spot, by spinning both wheels in opposite directions.
|
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 achieve turn with a ``tank`` or a ``steer`` block.
|
You can make a turn happen with either a ``||motors:tank||`` or a ``||motors:steer||`` block.
|
||||||
|
|
||||||
```blocks
|
```blocks
|
||||||
forever(function() {
|
forever(function() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Tank ZigZag
|
# Tank ZigZag
|
||||||
|
|
||||||
This example shows how to use the [tank](/reference/motors/tank) block to keep the speed of 2 large motors synchronized. In this example, a [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
|
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 on a zig zag pattern.
|
) will move in a zig zag pattern.
|
||||||
|
|
||||||
```blocks
|
```blocks
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,11 +10,17 @@
|
|||||||
"url":"/tutorials/touch-to-run",
|
"url":"/tutorials/touch-to-run",
|
||||||
"imageUrl":"/static/tutorials/touch-to-run.png"
|
"imageUrl":"/static/tutorials/touch-to-run.png"
|
||||||
}, {
|
}, {
|
||||||
"name": "Touch Sensor Values",
|
"name": "Sensor Values",
|
||||||
"description": "Check the value of a Touch Sensor and stop a motor if pressed.",
|
"description": "Check the value of a Touch Sensor and stop a motor if pressed.",
|
||||||
"cardType": "tutorial",
|
"cardType": "tutorial",
|
||||||
"url":"/tutorials/touch-sensor-values",
|
"url":"/tutorials/touch-sensor-values",
|
||||||
"imageUrl":"/static/tutorials/touch-sensor-values.png"
|
"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"
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -22,3 +28,4 @@
|
|||||||
|
|
||||||
[Touch to Run](/tutorials/touch-to-run),
|
[Touch to Run](/tutorials/touch-to-run),
|
||||||
[Touch Sensor Values](/tutorials/touch-sensor-values),
|
[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) {
|
export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||||
let w: pxt.editor.Ev3Wrapper
|
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-/, "")
|
filename = filename.replace(/^lego-/, "")
|
||||||
|
|
||||||
let fspath = "../prjs/BrkProg_SAVE/"
|
let fspath = "../prjs/BrkProg_SAVE/"
|
||||||
@@ -77,8 +79,6 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
|||||||
let rbfBIN = pxt.U.fromHex(rbfHex)
|
let rbfBIN = pxt.U.fromHex(rbfHex)
|
||||||
pxt.HF2.write16(rbfBIN, 4, rbfBIN.length)
|
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 mkFile = (ext: string, data: Uint8Array = null) => {
|
||||||
let f = UF2.newBlockFile()
|
let f = UF2.newBlockFile()
|
||||||
f.filename = "Projects/" + filename + ext
|
f.filename = "Projects/" + filename + ext
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#define MALLOC_LIMIT (8 * 1024 * 1024)
|
#define MALLOC_LIMIT (8 * 1024 * 1024)
|
||||||
#define MALLOC_CHECK_PERIOD (1024 * 1024)
|
#define MALLOC_CHECK_PERIOD (1024 * 1024)
|
||||||
|
|
||||||
|
namespace Array_ {
|
||||||
|
RefCollection *mk(unsigned flags);
|
||||||
|
}
|
||||||
|
|
||||||
void *xmalloc(size_t sz) {
|
void *xmalloc(size_t sz) {
|
||||||
static size_t allocBytes = 0;
|
static size_t allocBytes = 0;
|
||||||
allocBytes += sz;
|
allocBytes += sz;
|
||||||
@@ -476,7 +480,7 @@ void stopLMS() {
|
|||||||
if (!pid)
|
if (!pid)
|
||||||
continue;
|
continue;
|
||||||
char namebuf[100];
|
char namebuf[100];
|
||||||
snprintf(namebuf, 1000, "/proc/%d/cmdline", pid);
|
snprintf(namebuf, 100, "/proc/%d/cmdline", pid);
|
||||||
FILE *f = fopen(namebuf, "r");
|
FILE *f = fopen(namebuf, "r");
|
||||||
if (f) {
|
if (f) {
|
||||||
fread(namebuf, 1, 99, f);
|
fread(namebuf, 1, 99, f);
|
||||||
@@ -590,4 +594,66 @@ void dmesg(const char *format, ...) {
|
|||||||
fflush(dmesgFile);
|
fflush(dmesgFile);
|
||||||
fdatasync(fileno(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
|
} // namespace pxt
|
||||||
|
|||||||
@@ -127,31 +127,43 @@ namespace motors {
|
|||||||
reset(Output.ALL)
|
reset(Output.ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MoveSchedule {
|
||||||
|
speed: number;
|
||||||
|
useSteps: boolean;
|
||||||
|
steps: number[];
|
||||||
|
}
|
||||||
|
|
||||||
//% fixedInstances
|
//% fixedInstances
|
||||||
export class MotorBase extends control.Component {
|
export class MotorBase extends control.Component {
|
||||||
protected _port: Output;
|
protected _port: Output;
|
||||||
protected _portName: string;
|
protected _portName: string;
|
||||||
protected _brake: boolean;
|
protected _brake: boolean;
|
||||||
|
protected _regulated: boolean;
|
||||||
private _pauseOnRun: boolean;
|
private _pauseOnRun: boolean;
|
||||||
private _initialized: boolean;
|
private _initialized: boolean;
|
||||||
private _brakeSettleTime: number;
|
private _brakeSettleTime: number;
|
||||||
private _init: () => void;
|
private _init: () => void;
|
||||||
private _run: (speed: number) => void;
|
private _accelerationSteps: number;
|
||||||
private _move: (steps: boolean, stepsOrTime: number, speed: number) => void;
|
private _accelerationTime: number;
|
||||||
|
private _decelerationSteps: number;
|
||||||
|
private _decelerationTime: number;
|
||||||
|
|
||||||
protected static output_types: number[] = [0x7, 0x7, 0x7, 0x7];
|
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();
|
super();
|
||||||
this._port = port;
|
this._port = port;
|
||||||
this._portName = outputToName(this._port);
|
this._portName = outputToName(this._port);
|
||||||
this._brake = false;
|
this._brake = false;
|
||||||
|
this._regulated = true;
|
||||||
this._pauseOnRun = true;
|
this._pauseOnRun = true;
|
||||||
this._initialized = false;
|
this._initialized = false;
|
||||||
this._brakeSettleTime = 10;
|
this._brakeSettleTime = 10;
|
||||||
this._init = init;
|
this._init = init;
|
||||||
this._run = run;
|
this._accelerationSteps = 0;
|
||||||
this._move = move;
|
this._accelerationTime = 0;
|
||||||
|
this._decelerationSteps = 0;
|
||||||
|
this._decelerationTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,6 +275,34 @@ namespace motors {
|
|||||||
reset(this._port);
|
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.
|
* 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
|
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
|
||||||
@@ -277,41 +317,162 @@ namespace motors {
|
|||||||
//% help=motors/motor/run
|
//% help=motors/motor/run
|
||||||
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||||
this.init();
|
this.init();
|
||||||
speed = Math.clamp(-100, 100, speed >> 0);
|
const schedule = this.normalizeSchedule(speed, 0, value, 0, unit);
|
||||||
// stop if speed is 0
|
// stop if speed is 0
|
||||||
if (!speed) {
|
if (!schedule.speed) {
|
||||||
this.stop();
|
this.stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// special: 0 is infinity
|
// special: 0 is infinity
|
||||||
if (value == 0) {
|
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
|
||||||
this._run(speed);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// timed motor moves
|
// timed motor moves
|
||||||
let useSteps: boolean;
|
const steps = schedule.steps;
|
||||||
let stepsOrTime: number;
|
// 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) {
|
switch (unit) {
|
||||||
case MoveUnit.Rotations:
|
case MoveUnit.Rotations:
|
||||||
stepsOrTime = (value * 360) >> 0;
|
this._accelerationSteps = Math.max(0, (value * 360) | 0);
|
||||||
useSteps = true;
|
|
||||||
break;
|
break;
|
||||||
case MoveUnit.Degrees:
|
case MoveUnit.Degrees:
|
||||||
stepsOrTime = value >> 0;
|
this._accelerationSteps = Math.max(0, value | 0);
|
||||||
useSteps = true;
|
|
||||||
break;
|
break;
|
||||||
case MoveUnit.Seconds:
|
case MoveUnit.Seconds:
|
||||||
stepsOrTime = (value * 1000) >> 0;
|
this._accelerationTime = Math.max(0, (value * 1000) | 0);
|
||||||
useSteps = false;
|
|
||||||
break;
|
break;
|
||||||
default:
|
case MoveUnit.MilliSeconds:
|
||||||
stepsOrTime = value;
|
this._accelerationTime = Math.max(0, value | 0);
|
||||||
useSteps = false;
|
|
||||||
break;
|
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);
|
pauseUntil(() => this.isReady(), timeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setRunSmoothness(accelerationPercent: number, decelerationPercent: number) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected setOutputType(large: boolean) {
|
protected setOutputType(large: boolean) {
|
||||||
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
|
||||||
if (this._port & (1 << i)) {
|
if (this._port & (1 << i)) {
|
||||||
@@ -364,12 +529,10 @@ namespace motors {
|
|||||||
//% fixedInstances
|
//% fixedInstances
|
||||||
export class Motor extends MotorBase {
|
export class Motor extends MotorBase {
|
||||||
private _large: boolean;
|
private _large: boolean;
|
||||||
private _regulated: boolean;
|
|
||||||
|
|
||||||
constructor(port: Output, large: 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._large = large;
|
||||||
this._regulated = true;
|
|
||||||
this.markUsed();
|
this.markUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,44 +544,6 @@ namespace motors {
|
|||||||
this.setOutputType(this._large);
|
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.
|
* Gets motor actual speed.
|
||||||
* @param motor the port which connects to the motor
|
* @param motor the port which connects to the motor
|
||||||
@@ -506,7 +631,7 @@ namespace motors {
|
|||||||
export class SynchedMotorPair extends MotorBase {
|
export class SynchedMotorPair extends MotorBase {
|
||||||
|
|
||||||
constructor(ports: Output) {
|
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();
|
this.markUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,24 +643,6 @@ namespace motors {
|
|||||||
this.setOutputType(true);
|
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.
|
* 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,
|
* Use the Move Tank block for robot vehicles that have two Large Motors,
|
||||||
@@ -745,26 +852,15 @@ namespace motors {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
speed = Math.clamp(-100, 100, speed)
|
speed = Math.clamp(-100, 100, speed)
|
||||||
control.dmesg('speed: ' + speed)
|
|
||||||
|
|
||||||
let b = mkCmd(out, op, 15)
|
let b = mkCmd(out, op, 15)
|
||||||
control.dmesg('STEP 5')
|
|
||||||
b.setNumber(NumberFormat.Int8LE, 2, speed)
|
b.setNumber(NumberFormat.Int8LE, 2, speed)
|
||||||
// note that b[3] is padding
|
// note that b[3] is padding
|
||||||
control.dmesg('STEP 1')
|
|
||||||
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 0, opts.step1)
|
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 0, opts.step1)
|
||||||
control.dmesg('STEP 2')
|
|
||||||
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 1, opts.step2)
|
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 1, opts.step2)
|
||||||
control.dmesg('STEP 3')
|
|
||||||
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 2, opts.step3)
|
b.setNumber(NumberFormat.Int32LE, 4 + 4 * 2, opts.step3)
|
||||||
control.dmesg('STEP 4')
|
|
||||||
control.dmesg('br ' + opts.useBrake);
|
|
||||||
const br = !!opts.useBrake ? 1 : 0;
|
const br = !!opts.useBrake ? 1 : 0;
|
||||||
control.dmesg('Step 4.5 ' + br)
|
|
||||||
b.setNumber(NumberFormat.Int8LE, 4 + 4 * 3, br)
|
b.setNumber(NumberFormat.Int8LE, 4 + 4 * 3, br)
|
||||||
control.dmesg('STEP 5')
|
|
||||||
writePWM(b)
|
writePWM(b)
|
||||||
control.dmesg('end step')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-ev3",
|
"name": "pxt-ev3",
|
||||||
"version": "1.1.16",
|
"version": "1.1.17",
|
||||||
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
||||||
"private": false,
|
"private": false,
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
|
const MIN_RAMP_SPEED = 3;
|
||||||
|
|
||||||
export class MotorNode extends BaseNode {
|
export class MotorNode extends BaseNode {
|
||||||
isOutput = true;
|
isOutput = true;
|
||||||
@@ -30,11 +31,11 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpeed() {
|
getSpeed() {
|
||||||
return this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1);
|
return Math.round(this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
getAngle() {
|
getAngle() {
|
||||||
return this.angle;
|
return Math.round(this.angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the slave motor if any
|
// returns the slave motor if any
|
||||||
@@ -64,7 +65,7 @@ namespace pxsim {
|
|||||||
delete this.speedCmdValues;
|
delete this.speedCmdValues;
|
||||||
delete this._synchedMotor;
|
delete this._synchedMotor;
|
||||||
this.setChangedState();
|
this.setChangedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSyncCmd() {
|
clearSyncCmd() {
|
||||||
if (this._synchedMotor)
|
if (this._synchedMotor)
|
||||||
@@ -160,13 +161,19 @@ namespace pxsim {
|
|||||||
const dstep = isTimeCommand
|
const dstep = isTimeCommand
|
||||||
? pxsim.U.now() - this.speedCmdTime
|
? pxsim.U.now() - this.speedCmdTime
|
||||||
: this.tacho - this.speedCmdTacho;
|
: this.tacho - this.speedCmdTacho;
|
||||||
if (dstep < step1) // rampup
|
if (step1 && dstep < step1) { // rampup
|
||||||
this.speed = speed * dstep / step1;
|
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
|
else if (dstep < step1 + step2) // run
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
else if (dstep < step1 + step2 + step3)
|
else if (step2 && dstep < step1 + step2 + step3) {
|
||||||
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
|
this.speed = speed * (step1 + step2 + step3 - dstep)
|
||||||
else {
|
/ (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 (brake) this.speed = 0;
|
||||||
if (!isTimeCommand) {
|
if (!isTimeCommand) {
|
||||||
// we need to patch the actual position of the motor when
|
// we need to patch the actual position of the motor when
|
||||||
@@ -227,11 +234,10 @@ namespace pxsim {
|
|||||||
this.angle = this.manualReferenceAngle + this.manualAngle;
|
this.angle = this.manualReferenceAngle + this.manualAngle;
|
||||||
this.setChangedState();
|
this.setChangedState();
|
||||||
}
|
}
|
||||||
this.speed = Math.round(this.speed); // integer only
|
// don't round speed
|
||||||
|
|
||||||
// compute delta angle
|
// compute delta angle
|
||||||
const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed;
|
const rotations = this.speed / 100 * this.rotationsPerMilliSecond * elapsed;
|
||||||
const deltaAngle = Math.round(rotations * 360);
|
const deltaAngle = rotations * 360;
|
||||||
if (deltaAngle) {
|
if (deltaAngle) {
|
||||||
this.angle += deltaAngle;
|
this.angle += deltaAngle;
|
||||||
this.tacho += Math.abs(deltaAngle);
|
this.tacho += Math.abs(deltaAngle);
|
||||||
|
|||||||
Reference in New Issue
Block a user