web serial cleanup (#928)
* updated ticks * fix enable and compile * add debug mode * don't try to change UI while downloading * cleanup * don't double open * use cu * add delay before reconnecting * support for 200 ragne in field turn ratio * updated docs * fix docs
This commit is contained in:
parent
d85b5c5129
commit
8ca4558fc2
@ -61,6 +61,12 @@ motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations);
|
|||||||
motors.largeBC.stop();
|
motors.largeBC.stop();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### ~ hint
|
||||||
|
|
||||||
|
The **turn ratio range is -200, 200** unlike LabView who used -100,100.
|
||||||
|
|
||||||
|
### ~
|
||||||
|
|
||||||
## Tank
|
## Tank
|
||||||
|
|
||||||
The **tank** blocks control the speed of two motors. These are commonly used for a differential drive robot. The blocks can also specify the duration, angle, or number of rotations.
|
The **tank** blocks control the speed of two motors. These are commonly used for a differential drive robot. The blocks can also specify the duration, angle, or number of rotations.
|
||||||
|
@ -22,7 +22,7 @@ If you decide to use a **value** of rotation distance, you need to choose a type
|
|||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
* **turnRatio**: a [number](/types/number) that is the percentage of speed of the drive motor. The follower motor runs at this speed. A negative number steers to the left and a positive number steers to the right. This is a number between `-100` and `100`.
|
* **turnRatio**: a [number](/types/number) that is the percentage of speed of the drive motor. The follower motor runs at this speed. A negative number steers to the left and a positive number steers to the right. This is a number between `-200` and `200`.
|
||||||
* **speed**: a [number](/types/number) that is the percentage of full speed. A negative value runs the motors in the reverse direction. This is the speed that the drive motor runs at.
|
* **speed**: a [number](/types/number) that is the percentage of full speed. A negative value runs the motors in the reverse direction. This is the speed that the drive motor runs at.
|
||||||
* **value**: the [number](/types/number) of movement units to rotate for. A value of `0` means run the motor continuously.
|
* **value**: the [number](/types/number) of movement units to rotate for. A value of `0` means run the motor continuously.
|
||||||
* **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.
|
* **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.
|
||||||
|
@ -64,7 +64,6 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
|||||||
private _writer: any;
|
private _writer: any;
|
||||||
|
|
||||||
constructor(private port: SerialPort, private options: SerialOptions) {
|
constructor(private port: SerialPort, private options: SerialOptions) {
|
||||||
this.openAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async readSerialAsync() {
|
async readSerialAsync() {
|
||||||
@ -173,7 +172,7 @@ export function initAsync(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WebSerialPackageIO.isSupported())
|
if (WebSerialPackageIO.isSupported())
|
||||||
pxt.tickEvent("bluetooth.supported");
|
pxt.tickEvent("webserial.supported");
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
@ -274,7 +273,7 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
|||||||
|
|
||||||
if (!useHID) return saveUF2Async()
|
if (!useHID) return saveUF2Async()
|
||||||
|
|
||||||
pxt.tickEvent("bluetooth.flash");
|
pxt.tickEvent("webserial.flash");
|
||||||
let w: Ev3Wrapper;
|
let w: Ev3Wrapper;
|
||||||
return initHidAsync()
|
return initHidAsync()
|
||||||
.then(w_ => {
|
.then(w_ => {
|
||||||
@ -291,12 +290,14 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
|||||||
`<ul>
|
`<ul>
|
||||||
<li>${lf("Make sure to stop your program or exit portview on the EV3.")}</li>
|
<li>${lf("Make sure to stop your program or exit portview on the EV3.")}</li>
|
||||||
<li>${lf("Check your battery level.")}</li>
|
<li>${lf("Check your battery level.")}</li>
|
||||||
|
<li>${lf("Close EV3 LabView or other MakeCode editor tabs.")}
|
||||||
</ul>`,
|
</ul>`,
|
||||||
hasCloseIcon: true,
|
hasCloseIcon: true,
|
||||||
hideCancel: true,
|
hideCancel: true,
|
||||||
hideAgree: false,
|
hideAgree: false,
|
||||||
agreeLbl: lf("Try again"),
|
agreeLbl: lf("Try again"),
|
||||||
}).then(() => w.disconnectAsync())
|
}).then(() => w.disconnectAsync())
|
||||||
|
.then(() => Promise.delay(1000))
|
||||||
.then(() => w.reconnectAsync());
|
.then(() => w.reconnectAsync());
|
||||||
|
|
||||||
// nothing we can do
|
// nothing we can do
|
||||||
@ -309,11 +310,11 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
|||||||
.then(() => w.flashAsync(rbfPath, rbfBIN))
|
.then(() => w.flashAsync(rbfPath, rbfBIN))
|
||||||
.then(() => w.runAsync(rbfPath))
|
.then(() => w.runAsync(rbfPath))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
pxt.tickEvent("bluetooth.success");
|
pxt.tickEvent("webserial.success");
|
||||||
return w.disconnectAsync()
|
return w.disconnectAsync()
|
||||||
//return Promise.delay(1000).then(() => w.dmesgAsync())
|
//return Promise.delay(1000).then(() => w.dmesgAsync())
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
pxt.tickEvent("bluetooth.fail");
|
pxt.tickEvent("webserial.fail");
|
||||||
useHID = false;
|
useHID = false;
|
||||||
useWebSerial = false;
|
useWebSerial = false;
|
||||||
// if we failed to initalize, tell the user to retry
|
// if we failed to initalize, tell the user to retry
|
||||||
|
@ -7,6 +7,13 @@ let bluetoothDialogShown = false;
|
|||||||
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
||||||
const projectView = opts.projectView;
|
const projectView = opts.projectView;
|
||||||
pxt.debug('loading pxt-ev3 target extensions...')
|
pxt.debug('loading pxt-ev3 target extensions...')
|
||||||
|
|
||||||
|
function enableWebSerialAndCompileAsync() {
|
||||||
|
return enableWebSerialAsync()
|
||||||
|
.then(() => Promise.delay(500))
|
||||||
|
.then(() => projectView.compile());
|
||||||
|
}
|
||||||
|
|
||||||
const res: pxt.editor.ExtensionResult = {
|
const res: pxt.editor.ExtensionResult = {
|
||||||
deployCoreAsync,
|
deployCoreAsync,
|
||||||
showUploadInstructionsAsync: (fn: string, url: string, confirmAsync: (options: any) => Promise<number>) => {
|
showUploadInstructionsAsync: (fn: string, url: string, confirmAsync: (options: any) => Promise<number>) => {
|
||||||
@ -84,7 +91,7 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
onclick: () => {
|
onclick: () => {
|
||||||
pxt.tickEvent("bluetooth.enable");
|
pxt.tickEvent("bluetooth.enable");
|
||||||
if (bluetoothDialogShown) {
|
if (bluetoothDialogShown) {
|
||||||
enableWebSerialAsync().done();
|
enableWebSerialAndCompileAsync().done();
|
||||||
} else {
|
} else {
|
||||||
bluetoothDialogShown = true;
|
bluetoothDialogShown = true;
|
||||||
confirmAsync({
|
confirmAsync({
|
||||||
@ -99,13 +106,13 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
}],
|
}],
|
||||||
htmlBody: `<p>
|
htmlBody: `<p>
|
||||||
${lf("You will be prompted to select a serial port.")}
|
${lf("You will be prompted to select a serial port.")}
|
||||||
${pxt.BrowserUtils.isWindows() ? lf("Look for 'Standard Serial over Bluetooth link'.") : lf("Loop for 'tty.EV3-SerialPort' or 'cu.EV3-SerialPort'")}
|
${pxt.BrowserUtils.isWindows()
|
||||||
|
? lf("Look for 'Standard Serial over Bluetooth link'.")
|
||||||
|
: lf("Loop for 'cu.EV3-SerialPort'.")}
|
||||||
${lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")}
|
${lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")}
|
||||||
</p>
|
</p>
|
||||||
`
|
`
|
||||||
}).then(() => enableWebSerialAsync())
|
}).then(() => enableWebSerialAndCompileAsync())
|
||||||
.then(() => Promise.delay(500))
|
|
||||||
.then(() => projectView.compile())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} : undefined, downloadAgain ? {
|
} : undefined, downloadAgain ? {
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* See https://www.lego.com/cdn/cs/set/assets/blt6879b00ae6951482/LEGO_MINDSTORMS_EV3_Communication_Developer_Kit.pdf
|
||||||
|
* https://github.com/mindboards/ev3sources/blob/master/lms2012/lms2012/source/bytecodes.h#L146
|
||||||
|
*/
|
||||||
import HF2 = pxt.HF2
|
import HF2 = pxt.HF2
|
||||||
import U = pxt.U
|
import U = pxt.U
|
||||||
|
|
||||||
function log(msg: string) {
|
function log(msg: string) {
|
||||||
pxt.debug("EWRAP: " + msg)
|
pxt.log("serial: " + msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DirEntry {
|
export interface DirEntry {
|
||||||
@ -19,7 +23,7 @@ export class Ev3Wrapper {
|
|||||||
private cmdSeq = U.randomUint32() & 0xffff;
|
private cmdSeq = U.randomUint32() & 0xffff;
|
||||||
private lock = new U.PromiseQueue();
|
private lock = new U.PromiseQueue();
|
||||||
isStreaming = false;
|
isStreaming = false;
|
||||||
dataDump = false;
|
dataDump = /talkdbg=1/.test(window.location.href);
|
||||||
|
|
||||||
constructor(public io: pxt.HF2.PacketIO) {
|
constructor(public io: pxt.HF2.PacketIO) {
|
||||||
io.onData = buf => {
|
io.onData = buf => {
|
||||||
|
@ -23,7 +23,7 @@ export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.Field
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
|
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
|
||||||
super(String(value_), '-100', '100', null, '10', 'TurnRatio', opt_validator);
|
super(String(value_), '-200', '200', null, '10', 'TurnRatio', opt_validator);
|
||||||
this.params = params;
|
this.params = params;
|
||||||
(this as any).sliderColor_ = '#a8aaa8';
|
(this as any).sliderColor_ = '#a8aaa8';
|
||||||
}
|
}
|
||||||
@ -76,26 +76,26 @@ export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.Field
|
|||||||
if (!this.path_) {
|
if (!this.path_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let v = goog.math.clamp(parseFloat(this.getText()), -100, 100);
|
let v = goog.math.clamp(parseFloat(this.getText()), -200, 200);
|
||||||
if (isNaN(v)) {
|
if (isNaN(v)) {
|
||||||
v = 0;
|
v = 0;
|
||||||
}
|
}
|
||||||
|
const x = v / 100;
|
||||||
const x = goog.math.clamp(parseFloat(this.getText()), -100, 100) / 100;
|
const nx = Math.max(-1, Math.min(1, x));
|
||||||
const theta = x * Math.PI / 2;
|
const theta = Math.max(nx) * Math.PI / 2;
|
||||||
const cx = FieldTurnRatio.HALF;
|
const r = FieldTurnRatio.RADIUS - 6;
|
||||||
const cy = FieldTurnRatio.HALF - 14;
|
let cx = FieldTurnRatio.HALF;
|
||||||
const gamma = Math.PI - 2 * theta;
|
const cy = FieldTurnRatio.HALF - 22;
|
||||||
const r = FieldTurnRatio.RADIUS;
|
if (Math.abs(x) > 1) {
|
||||||
const alpha = 0.2 + Math.abs(x) * 0.5;
|
cx -= (x - (x > 0 ? 1 : -1)) * r / 2; // move center of circle
|
||||||
const x1 = 0;
|
}
|
||||||
|
const alpha = 0.2 + Math.abs(nx) * 0.5;
|
||||||
const y1 = r * alpha;
|
const y1 = r * alpha;
|
||||||
const y2 = r * Math.sin(Math.PI / 2 - theta);
|
const y2 = r * Math.sin(Math.PI / 2 - theta);
|
||||||
const x2 = r * Math.cos(Math.PI / 2 - theta);
|
const x2 = r * Math.cos(Math.PI / 2 - theta);
|
||||||
const y3 = y2 - r * alpha * Math.cos(2 * theta);
|
const y3 = y2 - r * alpha * Math.cos(2 * theta);
|
||||||
const x3 = x2 - r * alpha * Math.sin(2 * theta);
|
const x3 = x2 - r * alpha * Math.sin(2 * theta);
|
||||||
|
|
||||||
|
|
||||||
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
|
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
|
||||||
this.path_.setAttribute('d', d);
|
this.path_.setAttribute('d', d);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user