mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 23:12:24 -05:00
- Removed unused distance-mode from BoostMode-enum
- Added descriptions to BoostMode-enums - Improved motor-position handling - Added helper-functions for converting to/from motor position values - Added default value to BoostMotor._pendingPromiseFunction - Added changeLedColorBy-block - Only motors will now try to resolve motor-promises - Changed motor position wording from 'zero' to 'reset' - Modified tilt-thresholds to improve tilt-handling
This commit is contained in:
parent
e99a217ba5
commit
1d72b3b971
1 changed files with 75 additions and 24 deletions
|
@ -158,19 +158,23 @@ const BoostIOEvent = {
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
const BoostMode = {
|
const BoostMode = {
|
||||||
TILT: 0, // angle
|
TILT: 0, // angle (pitch/yaw)
|
||||||
DISTANCE: 0, // detect
|
LED: 1, // Set LED to accept RGB values
|
||||||
LED: 1, // RGB
|
COLOR: 0, // Read indexed colors from Vision Sensor
|
||||||
COLOR: 0, // Indexed colors
|
MOTOR: 2, // Set motors to report their position
|
||||||
MOTOR: 2, // Position
|
UNKNOWN: 0 // Anything else will use the default mode (mode 0)
|
||||||
UNKNOWN: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Debug function
|
||||||
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||||
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(' ');
|
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function number2int32array(number) {
|
/**
|
||||||
|
* Helper function for converting a number to a Int32Array
|
||||||
|
* @param {number} number
|
||||||
|
*/
|
||||||
|
function numberToInt32Array(number) {
|
||||||
var buffer = new ArrayBuffer(4)
|
var buffer = new ArrayBuffer(4)
|
||||||
var dataview = new DataView(buffer)
|
var dataview = new DataView(buffer)
|
||||||
dataview.setInt32(0, number)
|
dataview.setInt32(0, number)
|
||||||
|
@ -180,6 +184,16 @@ function number2int32array(number) {
|
||||||
dataview.getInt8(0)];
|
dataview.getInt8(0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for converting a regular array to a Little Endian INT32-value
|
||||||
|
* @param {Array} array
|
||||||
|
*/
|
||||||
|
function int32ArrayToNumber(array) {
|
||||||
|
var i = Uint8Array.from(array)
|
||||||
|
var d = new DataView(i.buffer);
|
||||||
|
return d.getInt32(0,true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage power, direction, position, and timers for one Boost motor.
|
* Manage power, direction, position, and timers for one Boost motor.
|
||||||
*/
|
*/
|
||||||
|
@ -226,7 +240,7 @@ class BoostMotor {
|
||||||
this._position = 0;
|
this._position = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This motor's current relative position
|
* This motor's current zero position, which the relative position can be calculated against.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
@ -262,12 +276,12 @@ class BoostMotor {
|
||||||
this._pendingTimeoutDelay = null;
|
this._pendingTimeoutDelay = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the motor has been turned on or is actively braking for a specific duration, this is the timeout ID for
|
* If the motor has been turned on run for a specific duration,
|
||||||
* the end-of-action handler. Cancel this when changing plans.
|
* this is the function that will be called once Scratch VM gets a notification from the Move Hub.
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this._pendingPromiseFunction = null;
|
this._pendingPromiseFunction = true;
|
||||||
|
|
||||||
this.startBraking = this.startBraking.bind(this);
|
this.startBraking = this.startBraking.bind(this);
|
||||||
this.turnOff = this.turnOff.bind(this);
|
this.turnOff = this.turnOff.bind(this);
|
||||||
|
@ -421,7 +435,7 @@ class BoostMotor {
|
||||||
this._index,
|
this._index,
|
||||||
0x0B,
|
0x0B,
|
||||||
null,
|
null,
|
||||||
number2int32array(degrees).concat(
|
numberToInt32Array(degrees).concat(
|
||||||
[
|
[
|
||||||
this._power * this._direction, // power in range 0-100
|
this._power * this._direction, // power in range 0-100
|
||||||
0xff, // max speed
|
0xff, // max speed
|
||||||
|
@ -554,6 +568,12 @@ class Boost {
|
||||||
color: 0,
|
color: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** TODO: Clean up
|
||||||
|
*/
|
||||||
|
|
||||||
|
this._led = 50
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bluetooth connection socket for reading/writing peripheral data.
|
* The Bluetooth connection socket for reading/writing peripheral data.
|
||||||
* @type {BLE}
|
* @type {BLE}
|
||||||
|
@ -697,7 +717,7 @@ class Boost {
|
||||||
filters: [{
|
filters: [{
|
||||||
services: [BLEService],
|
services: [BLEService],
|
||||||
manufacturerData: {
|
manufacturerData: {
|
||||||
0x0397: {
|
0: {
|
||||||
dataPrefix: [0x97, 0x03, 0x00, 0x40],
|
dataPrefix: [0x97, 0x03, 0x00, 0x40],
|
||||||
mask: [0xFF, 0xFF, 0, 0xFF]
|
mask: [0xFF, 0xFF, 0, 0xFF]
|
||||||
}
|
}
|
||||||
|
@ -824,7 +844,7 @@ class Boost {
|
||||||
0x41, // Message Type (Port Input Format Setup (Single)) TODO: Use enum
|
0x41, // Message Type (Port Input Format Setup (Single)) TODO: Use enum
|
||||||
portID,
|
portID,
|
||||||
mode,
|
mode,
|
||||||
].concat(number2int32array(delta)).concat([
|
].concat(numberToInt32Array(delta)).concat([
|
||||||
enableNotifications
|
enableNotifications
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -904,11 +924,11 @@ class Boost {
|
||||||
case BoostIO.MOTOREXT:
|
case BoostIO.MOTOREXT:
|
||||||
case BoostIO.MOTORINT:
|
case BoostIO.MOTORINT:
|
||||||
// Taken from EV3 extension tacho motor calculation
|
// Taken from EV3 extension tacho motor calculation
|
||||||
let value = data[4] + (data[5] * 256) + (data[6] * 256 * 256) + (data[7] * 256 * 256 * 256);
|
/*let value = data[4] + (data[5] * 256) + (data[6] * 256 * 256) + (data[7] * 256 * 256 * 256);
|
||||||
if (value > 0x7fffffff) {
|
if (value > 0x7fffffff) {
|
||||||
value = value - 0x100000000;
|
value = value - 0x100000000;
|
||||||
}
|
}*/
|
||||||
this._motors[portID]._position = value
|
this._motors[portID]._position = int32ArrayToNumber(data.slice(4,8))
|
||||||
break;
|
break;
|
||||||
case BoostIO.CURRENT:
|
case BoostIO.CURRENT:
|
||||||
case BoostIO.VOLTAGE:
|
case BoostIO.VOLTAGE:
|
||||||
|
@ -923,8 +943,10 @@ class Boost {
|
||||||
switch(feedback) {
|
switch(feedback) {
|
||||||
case BoostOutputCommandFeedback.BUFFER_EMPTY_COMMAND_COMPLETED ^ BoostOutputCommandFeedback.IDLE:
|
case BoostOutputCommandFeedback.BUFFER_EMPTY_COMMAND_COMPLETED ^ BoostOutputCommandFeedback.IDLE:
|
||||||
case BoostOutputCommandFeedback.CURRENT_COMMAND_DISCARDED ^ BoostOutputCommandFeedback.IDLE: // Resolve even if command didn't complete successfully
|
case BoostOutputCommandFeedback.CURRENT_COMMAND_DISCARDED ^ BoostOutputCommandFeedback.IDLE: // Resolve even if command didn't complete successfully
|
||||||
this._motors[portID].pendingPromiseFunction();
|
if(this._motors[portID]) {
|
||||||
break;
|
this._motors[portID].pendingPromiseFunction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
console.log(buf2hex(data))
|
console.log(buf2hex(data))
|
||||||
console.log("Got it but didn't find a motor on: " + portID)
|
console.log("Got it but didn't find a motor on: " + portID)
|
||||||
|
@ -1207,7 +1229,7 @@ class Scratch3BoostBlocks {
|
||||||
opcode: 'motorZero',
|
opcode: 'motorZero',
|
||||||
text: formatMessage({
|
text: formatMessage({
|
||||||
id: 'boost.motorZero',
|
id: 'boost.motorZero',
|
||||||
default: 'zero motor [MOTOR_ID]',
|
default: 'reset motor position [MOTOR_ID]',
|
||||||
description: 'set a motor\'s position to 0'
|
description: 'set a motor\'s position to 0'
|
||||||
}),
|
}),
|
||||||
blockType: BlockType.COMMAND,
|
blockType: BlockType.COMMAND,
|
||||||
|
@ -1234,6 +1256,21 @@ class Scratch3BoostBlocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
opcode: 'changeLightHueBy',
|
||||||
|
text: formatMessage({
|
||||||
|
id: 'boost.changeLightHueBy',
|
||||||
|
default: 'change light color by [HUE]',
|
||||||
|
description: 'change the LED color by a given amount'
|
||||||
|
}),
|
||||||
|
blockType: BlockType.COMMAND,
|
||||||
|
arguments: {
|
||||||
|
HUE: {
|
||||||
|
type: ArgumentType.NUMBER,
|
||||||
|
defaultValue: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
/*{
|
/*{
|
||||||
opcode: 'whenDistance',
|
opcode: 'whenDistance',
|
||||||
text: formatMessage({
|
text: formatMessage({
|
||||||
|
@ -1777,6 +1814,7 @@ class Scratch3BoostBlocks {
|
||||||
|
|
||||||
const rgbDecimal = color.rgbToDecimal(rgbObject);
|
const rgbDecimal = color.rgbToDecimal(rgbObject);
|
||||||
|
|
||||||
|
this._peripheral._led = inputHue;
|
||||||
this._peripheral.setLED(rgbDecimal);
|
this._peripheral.setLED(rgbDecimal);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
@ -1786,6 +1824,19 @@ class Scratch3BoostBlocks {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the LED's hue by a give number.
|
||||||
|
* @param {object} args - the block's arguments.
|
||||||
|
* @property {number} HUE - the hue to set, in the range [0,100].
|
||||||
|
* @return {Promise} - a Promise that resolves after some delay.
|
||||||
|
*/
|
||||||
|
changeLightHueBy (args) {
|
||||||
|
// TODO: Clean up this block and its opcode
|
||||||
|
let n = {};
|
||||||
|
n.HUE = Cast.toNumber(args.HUE) + this._peripheral._led;
|
||||||
|
this.setLightHue(n);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare the distance sensor's value to a reference.
|
* Compare the distance sensor's value to a reference.
|
||||||
* @param {object} args - the block's arguments.
|
* @param {object} args - the block's arguments.
|
||||||
|
@ -1915,13 +1966,13 @@ class Scratch3BoostBlocks {
|
||||||
_getTiltAngle (direction) {
|
_getTiltAngle (direction) {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case BoostTiltDirection.UP:
|
case BoostTiltDirection.UP:
|
||||||
return this._peripheral.tiltY > 45 ? 256 - this._peripheral.tiltY : -this._peripheral.tiltY;
|
return this._peripheral.tiltY > 90 ? 256 - this._peripheral.tiltY : -this._peripheral.tiltY;
|
||||||
case BoostTiltDirection.DOWN:
|
case BoostTiltDirection.DOWN:
|
||||||
return this._peripheral.tiltY > 45 ? this._peripheral.tiltY - 256 : this._peripheral.tiltY;
|
return this._peripheral.tiltY > 90 ? this._peripheral.tiltY - 256 : this._peripheral.tiltY;
|
||||||
case BoostTiltDirection.LEFT:
|
case BoostTiltDirection.LEFT:
|
||||||
return this._peripheral.tiltX > 45 ? 256 - this._peripheral.tiltX : -this._peripheral.tiltX;
|
return this._peripheral.tiltX > 90 ? 256 - this._peripheral.tiltX : -this._peripheral.tiltX;
|
||||||
case BoostTiltDirection.RIGHT:
|
case BoostTiltDirection.RIGHT:
|
||||||
return this._peripheral.tiltX > 45 ? this._peripheral.tiltX - 256 : this._peripheral.tiltX;
|
return this._peripheral.tiltX > 90 ? this._peripheral.tiltX - 256 : this._peripheral.tiltX;
|
||||||
default:
|
default:
|
||||||
log.warn(`Unknown tilt direction in _getTiltAngle: ${direction}`);
|
log.warn(`Unknown tilt direction in _getTiltAngle: ${direction}`);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue