Compare commits

..

34 Commits

Author SHA1 Message Date
peli
623e57a30e 1.2.29 2020-09-08 23:56:34 -07:00
Maciej Mroziński
91235fb6d3 Change sound volume to level (#986) 2020-09-08 23:55:35 -07:00
Peli de Halleux
4a73c5d700 1.2.28 2020-08-21 06:07:32 +02:00
Peli de Halleux
a47a06ac19 Cooperate (#985)
* cooperate pause

* fix math

* update lastPause before pausing

* faster cooperation

Co-authored-by: Peli de Halleux <peli@DESKTOP-5B7QRAM.corp.microsoft.com>
2020-08-21 06:06:59 +02:00
Peli
3f598a3eee 1.2.27 2020-01-19 21:49:57 -08:00
Peli
ded2e9d82c don't close bt connection 2020-01-19 21:41:43 -08:00
Peli de Halleux
c8381d7626 1.2.26 2019-10-20 09:02:44 -07:00
Peli de Halleux
62b5941143 is color detected (#952)
* added query function

* reshuffle
2019-10-20 09:02:17 -07:00
Peli de Halleux
1d5d18dc88 1.2.25 2019-10-18 22:53:46 -07:00
Peli de Halleux
bc4b71e0d6 Pulling updates from master (#951)
* show ports on start

* don't run show ports automatically

* polarity in synched motor (#945)

* account for polarity

* more comments

* handle dual motor in runtime

* invert steer

* don't use firmware polarity

* add block to stop program (#943)

* add block to stop program

* renaming

* fix translation
2019-10-18 22:53:30 -07:00
Peli de Halleux
00194d4aa6 1.2.24 2019-10-13 00:36:00 -07:00
Peli de Halleux
ec900f805e 1.2.23 2019-10-13 00:35:47 -07:00
Peli de Halleux
5f5bdd7294 blink fix (#949) 2019-10-13 00:35:20 -07:00
Peli de Halleux
a06331eef1 added channel 2019-10-08 14:23:57 -07:00
Peli de Halleux
aa741ce8de rename again 2019-10-08 14:21:55 -07:00
Peli de Halleux
61fe5091fe rename 2019-10-08 14:21:45 -07:00
Peli de Halleux
3d90e13797 shrinkg image 2019-10-08 14:21:12 -07:00
vincentl
469767a40a Add information to Try example to show where to find downloaded programs on the control brick. (#936) 2019-10-08 14:12:43 -07:00
Peli de Halleux
604fa764e6 Create calibreapp-image-actions.yml 2019-10-08 14:03:58 -07:00
Peli de Halleux
25cf2a9cdb move electron to 1.2.22 (#937) 2019-10-07 14:43:34 -07:00
Peli de Halleux
7549f865d6 move master to 1.2.22 2019-10-02 13:59:58 -07:00
Peli de Halleux
a5de9d88bb adding latest video 2019-10-02 13:53:22 -07:00
Peli de Halleux
0437df10de 1.2.22 2019-10-02 13:27:53 -07:00
Peli de Halleux
2079173dfa lock execution thread before exiting (#935) 2019-10-02 12:40:45 -07:00
Peli de Halleux
018a1e7528 added proportional line follower 2019-10-02 12:26:51 -07:00
Peli de Halleux
757f95d984 move master to v1.2.21 2019-10-02 10:59:50 -07:00
Peli de Halleux
8bc3fdc8ba 1.2.21 2019-10-01 15:56:22 -07:00
Peli de Halleux
e8a1e73cf5 1.2.20 2019-10-01 14:54:42 -07:00
Peli de Halleux
e9b2b239ad More gyro lessons (#933)
* updated pauseuntil

* updated youtube link

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

* updated docs
2019-10-01 13:27:37 -07:00
Peli de Halleux
d179f18ef3 added gyro movies 2019-10-01 11:05:44 -07:00
35 changed files with 5430 additions and 106 deletions

View File

@@ -38,10 +38,7 @@ Next you need to enable the experimental features (this may change in the future
## Download over Bluetooth
* go to the **beta** editor https://makecode.mindstorms.com/beta
This feature is not yet released so make sure to use the beta editor.
* go to https://makecode.mindstorms.com/
* click on **Download** to start a file download as usual
* on the download dialog, you should see a **Bluetooth** button. Click on the
**Bluetooth** button to enable the mode.
@@ -51,8 +48,9 @@ This feature is not yet released so make sure to use the beta editor.
## Choosing the correct serial port
Unfortunately, the browser dialog does not make it easy to select which serial port is the brick.
On Windows, it typically reads "Standard Serial over Bluetooth" and you may
have multiple of those if you've paired different bricks.
* On Windows, choose ``Standard Serial over Bluetooth``. There might be multiple of those but only one works. Try your luck! Once you know the COM port number, remember it for the next time around.
* On Mac OS, choose ``cu.BRICKNAME-SerialPort``
## Known issues

View File

@@ -27,7 +27,6 @@ while (true) {
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
}
pause(1);
}
```
@@ -43,6 +42,5 @@ while (true) {
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
}
pause(1);
}
```

View File

@@ -35,6 +35,13 @@ On the home page, scroll down to the **FLL / City Shaper** section for specific
Yes.
### Can I run the program again on the brick?
![EV3 Brick with Try in BrkProg_Save Folder in File Manager](/static/getting-started/try-in-file-manager.png)
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder,
select your program and click the center button to run it again.
### Does it work without internet?
No, the editor is cached in your browser cache. However, you can also download the [offline app](/offline-app) in case you need to install it on a computer.
@@ -98,6 +105,12 @@ The official answer is currently no. That being said, we have **Experimental sup
https://youtu.be/VIq8-6Egtqs
## Are there YouTube videos on MakeCode for EV3?
The MakeCode has a [FLL / City Shaper YouTube Channel](https://www.youtube.com/watch?v=IqL0Pyeu5Ng&list=PLMMBk9hE-SeqkOObethhlZtBTEK6FYx3n) with useful videos.
https://youtu.be/-AirqwC9DL4
### 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.

View File

@@ -54,6 +54,12 @@ Verify that the program you just created shows eyes on the Brick Display, and th
**Well done!**
## Run it Again
![EV3 Brick with Try in BrkProg_Save Folder in File Manager](/static/getting-started/try-in-file-manager.png)
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder, select **Try** and click the center button to run it again.
## Connect a Large Motor
Now you will learn to control the Large Motor.

View File

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

View File

@@ -388,12 +388,12 @@
}
function downloadWin64() {
// TODO: Keep this link up-to-date with the desired release version
window.open("https://makecode.com/api/release/ev3/v1.1.20/win64");
window.open("https://makecode.com/api/release/ev3/v1.2.22/win64");
tickEvent("offlineapp.download", { "target": "ev3", "platform": "win64" });
}
function downloadMac64() {
// TODO: Keep this link up-to-date with the desired release version
window.open("https://makecode.com/api/release/ev3/v1.1.20/mac64");
window.open("https://makecode.com/api/release/ev3/v1.2.22/mac64");
tickEvent("offlineapp.download", { "target": "ev3", "platform": "mac64" });
}
</script>

View File

@@ -0,0 +1,18 @@
# exit Program
Stops the program and returns to the brick menu
```sig
brick.exitProgram();
```
## Example
Do a sequence of motor commands and stop the program.
```blocks
motors.largeA.run(50)
pause(500)
motors.stopAll()
brick.exitProgram();
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -24,6 +24,26 @@
"name": "Bluetooth download (beta)",
"description": "EXPERIMENTAL! Learn how to download code via Bluetooth.",
"youTubeId": "VIq8-6Egtqs"
}, {
"name": "Turn with Gyro",
"description": "Use the gyro for precise turns.",
"youTubeId": "I7ncuXAfBwk"
}, {
"name": "Moving with Gyro",
"description": "Use the gyro for correct the robot trajectory.",
"youTubeId": "ufiOPvW37xc"
}, {
"name": "Line following with 1 color sensor",
"description": "Simple line following using the color sensor.",
"youTubeId": "_LeduyKQVjg"
}, {
"name": "Proportional line following with 1 color sensor",
"description": "Proportional line following using the color sensor.",
"youTubeId": "-AirqwC9DL4"
}, {
"name": "Proportional line following with 2 color sensors",
"description": "Proportional line following using two color sensor.",
"youTubeId": "QWOflBuu9Oo"
}]
```

View File

@@ -9,6 +9,12 @@
"cardType": "tutorial",
"url":"/tutorials/calibrate-gyro",
"imageUrl":"/static/tutorials/calibrate-gyro.png"
}, {
"name": "Turn",
"description": "Use the gyro to turn precisely",
"cardType": "tutorial",
"url":"/tutorials/turn-with-gyro",
"imageUrl":"/static/tutorials/turn-with-gyro.png"
}, {
"name": "Move Straight",
"description": "Use the gyro to correct the trajectory of the robot",

View File

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

View File

@@ -64,6 +64,7 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
private _writer: any;
constructor(private port: SerialPort, private options: SerialOptions) {
console.log(`serial: new io`)
}
async readSerialAsync() {
@@ -90,17 +91,24 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
return !!(<any>navigator).serial;
}
static portIos: WebSerialPackageIO[] = [];
static async mkPacketIOAsync(): Promise<pxt.HF2.PacketIO> {
const serial = (<any>navigator).serial;
if (serial) {
try {
const requestOptions: SerialPortRequestOptions = {};
const port = await serial.requestPort(requestOptions);
const options: SerialOptions = {
baudrate: 460800,
buffersize: 4096
};
return new WebSerialPackageIO(port, options);
let io = WebSerialPackageIO.portIos.filter(i => i.port == port)[0];
if (!io) {
const options: SerialOptions = {
baudrate: 460800,
buffersize: 4096
};
io = new WebSerialPackageIO(port, options);
WebSerialPackageIO.portIos.push(io);
}
return io;
} catch (e) {
console.log(`connection error`, e)
}
@@ -125,11 +133,8 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
});
}
private closeAsync() {
console.log(`serial: closing port`);
this.port.close();
this._reader = undefined;
this._writer = undefined;
private async closeAsync() {
// don't close port
return Promise.delay(500);
}

View File

@@ -149,9 +149,9 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
getFirstValueI11n(value: string) {
const firstValue = this.getFirstValue(value);
const motorOptions = {
'medium motor': lf('medium motor'),
'large motor': lf('large motor'),
'large motors': lf('large motors')
'medium motor': lf("medium motor"),
'large motor': lf("large motor"),
'large motors': lf("large motors")
}
return motorOptions[firstValue];
}

View File

@@ -1,5 +1,4 @@
const enum ColorSensorMode {
None = 0,
//% block="reflected light intensity"
ReflectedLightIntensity = 0,
//% block="ambient light intensity"
@@ -59,7 +58,6 @@ namespace sensors {
constructor(port: number) {
super(port)
this._setMode(ColorSensorMode.None);
this.thresholdDetector = new sensors.ThresholdDetector(this.id());
this.calibrating = false;
}
@@ -73,13 +71,7 @@ namespace sensors {
}
setMode(m: ColorSensorMode) {
if (m == ColorSensorMode.AmbientLightIntensity) {
this.thresholdDetector.setLowThreshold(5);
this.thresholdDetector.setHighThreshold(20);
} else {
this.thresholdDetector.setLowThreshold(20);
this.thresholdDetector.setHighThreshold(80);
}
// don't change threshold after initialization
this._setMode(m)
}
@@ -187,6 +179,22 @@ namespace sensors {
return this.getNumber(NumberFormat.UInt8LE, 0)
}
/**
* Checks the color is being detected
* @param color the color to detect
*/
//% help=sensors/color-sensor/is-color-detected
//% block="is **color sensor** %this|detected|%color=colorEnumPicker"
//% blockId=colorisColorDetectedDetected
//% parts="colorsensor"
//% blockNamespace=sensors
//% this.fieldEditor="ports"
//% weight=99 blockGap=8
//% group="Color Sensor"
isColorDetected(color: number) {
return this.color() == color;
}
/**
* Get the current raw rgb values as an array from the color sensor.
* @param sensor the color sensor to query the request

View File

@@ -0,0 +1,30 @@
# Is Color Detected
Checks the color is detected
```sig
let b = sensors.color1.isColorDetected(ColorSensorColor.Blue)
```
The [color](/reference/sensors/color) you choose to look for is one of the colors that the sensor can detect. If you want to use colors for tracking, it's best to use a color that is the same or very close to the ones the sensor detects.
## Parameters
* **color**: the [color](/reference/sensors/color) to watch for.
## Example
Wait for the sensor to see ``blue``. Then, show an expression on the screen.
```blocks
brick.showString("Waiting for blue", 1)
while(!sensors.color1.isColorDetected(ColorSensorColor.Blue)) {
pause(20)
}
brick.clearScreen()
brick.showImage(images.expressionsSick)
```
## See also
[on color detected](/reference/sensors/color-sensor/on-color-detected), [color](/reference/sensors/color)

View File

@@ -26,6 +26,7 @@ namespace brick {
*/
//% blockId=brickBatteryProperty block="battery %property"
//% group="Battery"
//% blockGap=8
//% help=brick/battery-property
export function batteryInfo(property: BatteryProperty): number {
const info = sensors.internal.getBatteryInfo();

View File

@@ -85,7 +85,7 @@ namespace brick {
//% blockId=buttonIsPressed
//% parts="brick"
//% blockNamespace=brick
//% weight=81 blockGap=8
//% weight=81
//% group="Buttons"
//% button.fieldEditor="brickbuttons"
isPressed() {

11
libs/core/cooperate.ts Normal file
View File

@@ -0,0 +1,11 @@
namespace control {
let lastPause = 0;
const COOPERATION_INTERVAL = 20
export function cooperate() {
const now = control.millis()
if (now - lastPause > COOPERATION_INTERVAL) {
lastPause = now
pause(1)
}
}
}

View File

@@ -21,8 +21,7 @@ namespace sensors.internal {
const now = control.millis();
if (now - this.lastQuery >= this.interval * 2)
this.queryAndUpdate(); // sensor poller is not allowed to run
if (now - this.lastPause >= this.interval * 5)
pause(1); // allow events to trigger
control.cooperate(); // allow events to trigger
}
private queryAndUpdate() {
@@ -104,7 +103,7 @@ namespace sensors.internal {
}
}
function init() {
export function init() {
if (sensorInfos) return
sensorInfos = []
for (let i = 0; i < DAL.NUM_INPUTS; ++i) sensorInfos.push(new SensorInfo(i))
@@ -137,6 +136,7 @@ namespace sensors.internal {
buf[UartCtlOff.Port] = port
buf[UartCtlOff.Mode] = mode
uartMM.ioctl(IO.UART_READ_MODE_INFO, buf)
control.dmesg(`UART_READ_MODE_INFO ${buf.toHex()}`)
return buf
//let info = `t:${buf[TypesOff.Type]} c:${buf[TypesOff.Connection]} m:${buf[TypesOff.Mode]} n:${buf.slice(0, 12).toHex()}`
//serial.writeLine("UART " + port + " / " + mode + " - " + info)
@@ -275,21 +275,23 @@ void cUiUpdatePower(void)
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let r = 0;
for (let i = 0; i < conns.length; ++i) {
r = (r << 8 | conns[i]);
r = conns[i] + (r << 6) + (r << 16) - r;
}
return r;
}
let nonActivated = 0;
function detectDevices() {
//control.dmesg(`detect devices (${nonActivated} na)`)
control.dmesg(`detect devices (hash ${hashDevices()})`)
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let numChanged = 0;
const uartSensors: SensorInfo[] = [];
for (const sensorInfo of sensorInfos) {
const newConn = conns[sensorInfo.port]
if (newConn == sensorInfo.connType) {
if (newConn == sensorInfo.connType
&& sensorInfo.sensor
&& sensorInfo.sensor.isActive()) {
// control.dmesg(`connection unchanged ${newConn} at ${sensorInfo.port}`)
continue;
}
@@ -425,11 +427,11 @@ void cUiUpdatePower(void)
constructor(port: number) {
super(port)
this.mode = 0
this.realmode = 0
this.realmode = -1
}
_activated() {
this.realmode = 0
this.realmode = -1
this._setMode(this.mode)
}
@@ -456,7 +458,7 @@ void cUiUpdatePower(void)
reset() {
if (this.isActive()) uartReset(this._port);
this.realmode = 0;
this.realmode = -1;
}
}
@@ -556,7 +558,7 @@ void cUiUpdatePower(void)
}
function setUartModes() {
control.dmesg(`UART set modes`)
control.dmesg(`UART set modes ${devcon.toHex()}`)
uartMM.ioctl(IO.UART_SET_CONN, devcon)
const ports: number[] = [];
for (let port = 0; port < DAL.NUM_INPUTS; ++port) {
@@ -568,7 +570,7 @@ void cUiUpdatePower(void)
while (ports.length) {
const port = ports.pop();
const status = waitNonZeroUartStatus(port)
control.dmesg(`UART set mode ${status} at ${port}`);
control.dmesg(`UART status ${status} at ${port}`);
}
}
@@ -584,6 +586,7 @@ void cUiUpdatePower(void)
while (true) {
if (port < 0) return
updateUartMode(port, mode);
control.dmesg(`UART_SET_CONN ${devcon.toHex()}`)
uartMM.ioctl(IO.UART_SET_CONN, devcon)
let status = waitNonZeroUartStatus(port)
if (status & UART_PORT_CHANGED) {
@@ -814,10 +817,10 @@ namespace sensors {
export class ThresholdDetector {
public id: number;
public min: number;
public max: number;
public lowThreshold: number;
public highThreshold: number;
private min: number;
private max: number;
private lowThreshold: number;
private highThreshold: number;
public level: number;
public state: ThresholdState;

View File

@@ -524,6 +524,7 @@ void stopProgram() {
}
extern "C" void target_reset() {
pthread_mutex_trylock(&execMutex);
stopMotors();
stopProgram();
if (lmsPid)

View File

@@ -55,7 +55,7 @@ namespace motors {
Size = 12
}
function init() {
export function init() {
if (pwmMM) return
pwmMM = control.mmap("/dev/lms_pwm", 0, 0)
if (!pwmMM) control.fail("no PWM file")
@@ -124,7 +124,7 @@ namespace motors {
export function stopAll() {
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
writePWM(b);
pause(1);
control.cooperate();
}
/**
@@ -136,7 +136,7 @@ namespace motors {
//% help=motors/reset-all
export function resetAll() {
reset(Output.ALL)
pause(1);
control.cooperate();
}
interface MoveSchedule {
@@ -159,6 +159,7 @@ namespace motors {
private _accelerationTime: number;
private _decelerationSteps: number;
private _decelerationTime: number;
private _inverted: boolean;
protected static output_types: number[] = [0x7, 0x7, 0x7, 0x7];
@@ -176,6 +177,7 @@ namespace motors {
this._accelerationTime = 0;
this._decelerationSteps = 0;
this._decelerationTime = 0;
this._inverted = false;
}
/**
@@ -225,9 +227,11 @@ namespace motors {
//% help=motors/motor/set-inverted
setInverted(inverted: boolean) {
this.init();
const b = mkCmd(this._port, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, inverted ? 0 : 1);
writePWM(b)
this._inverted = inverted;
}
protected invertedFactor(): number {
return this._inverted ? -1 : 1;
}
/**
@@ -265,7 +269,7 @@ namespace motors {
if (this._brake && this._brakeSettleTime > 0)
pause(this._brakeSettleTime);
else {
pause(1);
control.cooperate();
}
}
@@ -276,7 +280,7 @@ namespace motors {
// allow robot to settle
this.settle();
} else {
pause(1);
control.cooperate();
}
}
@@ -294,8 +298,9 @@ namespace motors {
}
private normalizeSchedule(speed: number, step1: number, step2: number, step3: number, unit: MoveUnit): MoveSchedule {
// motor polarity is not supported at the firmware level for sync motor operations
const r: MoveSchedule = {
speed: Math.clamp(-100, 100, speed >> 0),
speed: Math.clamp(-100, 100, speed | 0) * this.invertedFactor(),
useSteps: true,
steps: [step1 || 0, step2 || 0, step3 || 0]
}
@@ -352,7 +357,7 @@ namespace motors {
// special: 0 is infinity
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
this._run(schedule.speed);
pause(1);
control.cooperate();
return;
}
@@ -562,6 +567,7 @@ namespace motors {
private __init() {
this.setOutputType(this._large);
this.setInverted(false);
}
/**
@@ -741,7 +747,7 @@ namespace motors {
//% help=motors/synced/steer
steer(turnRatio: number, speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
this.init();
speed = Math.clamp(-100, 100, speed >> 0);
speed = Math.clamp(-100, 100, speed >> 0) * this.invertedFactor();
if (!speed) {
this.stop();
return;

View File

@@ -26,7 +26,8 @@
"icons.jres",
"ns.ts",
"platform.h",
"integrator.ts"
"integrator.ts",
"cooperate.ts"
],
"testFiles": [
"test.ts"

13
libs/ev3/brick.ts Normal file
View File

@@ -0,0 +1,13 @@
namespace brick {
/**
* Exits the program to the main menu. (in the simulator restarts it)
*/
//% blockId=loopstop block="exit program"
//% help=reference/brick/exit-program
//% weight=10
//% blockGap=8
//% group="Buttons"
export function exitProgram() {
control.reset();
}
}

View File

@@ -1,6 +1,6 @@
//% color="#68C3E2" weight=100 icon="\uf106"
//% groups='["Buttons", "Screen", "Battery"]'
//% groups='["Buttons", "Screen", "Power"]'
//% labelLineWidth=60
namespace brick {
}

View File

@@ -2,8 +2,9 @@
"name": "ev3",
"description": "The EV3 library",
"files": [
"README.md",
"README.md",
"ns.ts",
"brick.ts",
"startup.ts",
"images.jres",
"images.ts",

View File

@@ -2,9 +2,5 @@
console.addListener(function(msg: string) {
control.dmesg(msg.substr(0, msg.length - 1))
})
// pulse green, play startup sound, turn off light
brick.setStatusLight(StatusLight.GreenPulse);
// We pause for 100ms to give time to read sensor values, so they work in on_start block
pause(400)
// and we're ready
brick.setStatusLight(StatusLight.Off);
brick.showBoot();

View File

@@ -229,14 +229,15 @@ namespace sensors {
/**
* Pauses the program until the gyro detected
* that the angle changed by the desired amount of degrees.
* @param degrees the degrees to turn
* @param degrees the degrees to turn
*/
//% help=sensors/gyro/pause-until-rotated
//% block="pause **gyro** %this|until rotated %degrees|degrees"
//% block="pause until **gyro** %this|rotated %degrees=rotationPicker|degrees"
//% blockId=gyroPauseUntilRotated
//% parts="gyroscope"
//% blockNamespace=sensors
//% this.fieldEditor="ports"
//% degrees.defl=90
//% weight=63
//% group="Gyro Sensor"
pauseUntilRotated(degrees: number, timeOut?: number): void {
@@ -281,4 +282,17 @@ namespace sensors {
//% fixedInstance whenUsed block="4" jres=icons.port4
export const gyro4: GyroSensor = new GyroSensor(4)
/**
* Get the rotation angle field editor
* @param degrees angle in degrees, eg: 90
*/
//% blockId=rotationPicker block="%degrees"
//% blockHidden=true shim=TD_ID
//% colorSecondary="#FFFFFF"
//% degrees.fieldEditor="numberdropdown" degrees.fieldOptions.decompileLiterals=true
//% degrees.fieldOptions.data='[["30", 30], ["45", 45], ["60", 60], ["90", 90], ["180", 180], ["-30", -30], ["-45", -45], ["-60", -60], ["-90", -90], ["-180", -180]]'
export function __rotationPicker(degrees: number): number {
return degrees;
}
}

View File

@@ -45,7 +45,7 @@ void setVolume(int volume) {
struct ToneCmd {
uint8_t cmd;
uint8_t vol;
uint8_t lvl;
uint16_t freq;
uint16_t duration;
};
@@ -55,10 +55,26 @@ static void _stopSound() {
writeDev(&cmd, sizeof(cmd));
}
static uint8_t _getVolumeLevel(uint8_t volume, uint8_t levels) {
uint8_t level;
uint8_t step = (uint8_t) (100 / (levels - 1));
if (volume < step) {
level = 0;
} else if (volume > step * (levels - 1)) {
level = levels;
} else {
level = (uint8_t) (volume / step);
}
return level;
}
static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume) {
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L471
uint8_t level = _getVolumeLevel(volume, 13);
ToneCmd cmd;
cmd.cmd = SOUND_CMD_TONE;
cmd.vol = volume;
cmd.lvl = level;
cmd.freq = frequency;
cmd.duration = duration;
// (*SoundInstance.pSound).Busy = TRUE;
@@ -122,7 +138,8 @@ void playSample(Buffer buf) {
stopUser();
pthread_mutex_lock(&pumpMutex);
*lmsSoundMMap = 1; // BUSY
uint8_t cmd[] = {SOUND_CMD_PLAY, (uint8_t)((currVolume / 33) + 1)};
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L605
uint8_t cmd[] = {SOUND_CMD_PLAY, _getVolumeLevel(currVolume, 8)};
writeDev(cmd, 2);
decrRC(currentSample);
currentSample = buf;

View File

@@ -129,8 +129,8 @@ namespace brick {
screenMode = ScreenMode.Ports;
renderPorts();
control.runInParallel(function() {
while(screenMode == ScreenMode.Ports) {
control.runInParallel(function () {
while (screenMode == ScreenMode.Ports) {
renderPorts();
pause(50);
}
@@ -140,8 +140,20 @@ namespace brick {
function renderPorts() {
const col = 44;
const lineHeight8 = image.font8.charHeight + 2;
const h = screen.height;
const w = screen.width;
const blink = (control.millis() >> 5) % (h - 1);
clearScreen();
for (let i = 0; i < 4; ++i) {
const x = i * col + 2;
screen.print("ABCD"[i], x, 1 * lineHeight8, 1, image.font8)
screen.print((i + 1).toString(), x, h - lineHeight8, 1, image.font8)
}
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1)
function scale(x: number) {
if (Math.abs(x) >= 5000) {
const k = Math.floor(x / 1000);
@@ -155,25 +167,38 @@ namespace brick {
const datas = motors.getAllMotorData();
for (let i = 0; i < datas.length; ++i) {
const data = datas[i];
const x = i * col + 2;
if (!data.actualSpeed && !data.count) continue;
const x = i * col;
screen.print("ABCD"[i], x + 2, 1 * lineHeight8, 1, image.font8)
screen.print(`${scale(data.actualSpeed)}%`, x + 2, 3 * lineHeight8, 1, image.font8)
screen.print(`${scale(data.count)}>`, x + 2, 4 * lineHeight8, 1, image.font8)
screen.print(`${scale(data.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8)
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8)
}
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
// sensors
const sis = sensors.internal.getActiveSensors();
const h = screen.height;
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1)
for (let i = 0; i < sis.length; ++i) {
const si = sis[i];
const x = (si.port() - 1) * col;
const x = (si.port() - 1) * col + 2;
const inf = si._info();
screen.print(si.port() + "", x, h - 4 * lineHeight8, 1, image.font8)
screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
if (inf)
screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
}
// alive dot
screen.setPixel(w - 1, blink, 1);
screen.setPixel(w - 1, blink - 1, 1);
screen.setPixel(w - 2, blink - 1, 1);
screen.setPixel(w - 2, blink, 1);
}
export function showBoot() {
// pulse green, play startup sound, turn off light
brick.setStatusLight(StatusLight.GreenPulse);
// We pause for 100ms to give time to read sensor values, so they work in on_start block
sensors.internal.init();
motors.init();
pause(800);
// and we're ready
brick.setStatusLight(StatusLight.Off);
}
/**

5105
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -9,7 +9,6 @@ namespace pxsim {
private angle: number = 0;
private tacho: number = 0;
private speed: number = 0;
private polarity: number = 1; // -1, 1 or -1
private started: boolean;
private speedCmd: DAL;
@@ -31,7 +30,7 @@ namespace pxsim {
}
getSpeed() {
return Math.round(this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1));
return Math.round(this.speed);
}
getAngle() {
@@ -82,16 +81,6 @@ namespace pxsim {
return this.id == NodeType.LargeMotor;
}
setPolarity(polarity: number) {
// Either 1 or 255 (reverse)
/*
-1 : Motor will run backward
0 : Motor will run opposite direction
1 : Motor will run forward
*/
this.polarity = polarity;
}
reset() {
// not sure what reset does...
}

View File

@@ -119,11 +119,7 @@ namespace pxsim {
return 2;
}
case DAL.opOutputPolarity: {
// reverse
const port = buf.data[1];
const polarity = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2);
const motors = ev3board().getMotor(port);
motors.forEach(motor => motor.setPolarity(polarity));
console.error("opOutputPolarity not supported");
return 2;
}
case DAL.opOutputSetType: {

View File

@@ -18,7 +18,7 @@
"Touch Sensor Tutorials": "tutorials/touch-sensor",
"Color Sensor Tutorials": "tutorials/color-sensor",
"Ultrasonic Sensor Tutorials": "tutorials/ultrasonic-sensor",
"Gyro Sensor Tutorials": "tutorials/gyro",
"Gyro Tutorials": "tutorials/gyro",
"Infrared Sensor Tutorials": "tutorials/infrared-sensor",
"FLL / City Shaper": "tutorials/city-shaper",
"Design Engineering": "design-engineering",
@@ -27,6 +27,6 @@
"Videos": "videos"
},
"electronManifest": {
"latest": "v1.1.20"
"latest": "v1.2.22"
}
}