- 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:
Kevin Andersen 2019-02-21 13:35:21 -05:00
parent e99a217ba5
commit 1d72b3b971

View file

@ -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}`);
} }