Added speed ramping capability

This commit is contained in:
Nathan Kellenicki 2018-08-04 23:24:06 +01:00
parent a976fd3f71
commit c9e0b0214e
6 changed files with 183 additions and 8 deletions

48
DOCS.md
View File

@ -82,6 +82,7 @@ Emits when a LPF2 Hub device is found.
* [.setLEDColor(color)](#WeDo2SmartHub+setLEDColor) ⇒ <code>Promise</code>
* [.setLEDRGB(red, green, blue)](#WeDo2SmartHub+setLEDRGB) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#WeDo2SmartHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#WeDo2SmartHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.playSound(frequency, time)](#WeDo2SmartHub+playSound) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
* [.disconnect()](#Hub+disconnect) ⇒ <code>Promise</code>
@ -198,6 +199,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="WeDo2SmartHub+rampMotorSpeed"></a>
### weDo2SmartHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>WeDo2SmartHub</code>](#WeDo2SmartHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="WeDo2SmartHub+playSound"></a>
### weDo2SmartHub.playSound(frequency, time) ⇒ <code>Promise</code>
@ -378,6 +394,7 @@ Emits when an attached motor or sensor is detached from the Hub.
* [.batteryLevel](#Hub+batteryLevel)
* [.setLEDColor(color)](#BoostMoveHub+setLEDColor) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#BoostMoveHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#BoostMoveHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.setMotorAngle(port, angle, [speed])](#BoostMoveHub+setMotorAngle) ⇒ <code>Promise</code>
* [.setName(name)](#LPF2Hub+setName) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
@ -480,6 +497,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> \| <code>Array.&lt;number&gt;</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. If you are specifying port AB to control both motors, you can optionally supply a tuple of speeds. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="BoostMoveHub+rampMotorSpeed"></a>
### boostMoveHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>BoostMoveHub</code>](#BoostMoveHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="BoostMoveHub+setMotorAngle"></a>
### boostMoveHub.setMotorAngle(port, angle, [speed]) ⇒ <code>Promise</code>
@ -673,6 +705,7 @@ Emits when an attached motor or sensor is detached from the Hub.
* [.batteryLevel](#Hub+batteryLevel)
* [.setLEDColor(color)](#PUPHub+setLEDColor) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#PUPHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#PUPHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.setName(name)](#LPF2Hub+setName) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
* [.disconnect()](#Hub+disconnect) ⇒ <code>Promise</code>
@ -773,6 +806,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> \| <code>Array.&lt;number&gt;</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. If you are specifying port AB to control both motors, you can optionally supply a tuple of speeds. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="PUPHub+rampMotorSpeed"></a>
### pupHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>PUPHub</code>](#PUPHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="LPF2Hub+setName"></a>
### pupHub.setName(name) ⇒ <code>Promise</code>

View File

@ -134,6 +134,7 @@ Emits when a LPF2 Hub device is found.
* [.setLEDColor(color)](#WeDo2SmartHub+setLEDColor) ⇒ <code>Promise</code>
* [.setLEDRGB(red, green, blue)](#WeDo2SmartHub+setLEDRGB) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#WeDo2SmartHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#WeDo2SmartHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.playSound(frequency, time)](#WeDo2SmartHub+playSound) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
* [.disconnect()](#Hub+disconnect) ⇒ <code>Promise</code>
@ -250,6 +251,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="WeDo2SmartHub+rampMotorSpeed"></a>
### weDo2SmartHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>WeDo2SmartHub</code>](#WeDo2SmartHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="WeDo2SmartHub+playSound"></a>
### weDo2SmartHub.playSound(frequency, time) ⇒ <code>Promise</code>
@ -430,6 +446,7 @@ Emits when an attached motor or sensor is detached from the Hub.
* [.batteryLevel](#Hub+batteryLevel)
* [.setLEDColor(color)](#BoostMoveHub+setLEDColor) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#BoostMoveHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#BoostMoveHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.setMotorAngle(port, angle, [speed])](#BoostMoveHub+setMotorAngle) ⇒ <code>Promise</code>
* [.setName(name)](#LPF2Hub+setName) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
@ -532,6 +549,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> \| <code>Array.&lt;number&gt;</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. If you are specifying port AB to control both motors, you can optionally supply a tuple of speeds. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="BoostMoveHub+rampMotorSpeed"></a>
### boostMoveHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>BoostMoveHub</code>](#BoostMoveHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="BoostMoveHub+setMotorAngle"></a>
### boostMoveHub.setMotorAngle(port, angle, [speed]) ⇒ <code>Promise</code>
@ -725,6 +757,7 @@ Emits when an attached motor or sensor is detached from the Hub.
* [.batteryLevel](#Hub+batteryLevel)
* [.setLEDColor(color)](#PUPHub+setLEDColor) ⇒ <code>Promise</code>
* [.setMotorSpeed(port, speed, [time])](#PUPHub+setMotorSpeed) ⇒ <code>Promise</code>
* [.rampMotorSpeed(port, fromSpeed, toSpeed, time)](#PUPHub+rampMotorSpeed) ⇒ <code>Promise</code>
* [.setName(name)](#LPF2Hub+setName) ⇒ <code>Promise</code>
* [.connect()](#Hub+connect) ⇒ <code>Promise</code>
* [.disconnect()](#Hub+disconnect) ⇒ <code>Promise</code>
@ -825,6 +858,21 @@ Set the motor speed on a given port.
| speed | <code>number</code> \| <code>Array.&lt;number&gt;</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. If you are specifying port AB to control both motors, you can optionally supply a tuple of speeds. |
| [time] | <code>number</code> | How long to activate the motor for (in milliseconds). Leave empty to turn the motor on indefinitely. |
<a name="PUPHub+rampMotorSpeed"></a>
### pupHub.rampMotorSpeed(port, fromSpeed, toSpeed, time) ⇒ <code>Promise</code>
Ramp the motor speed on a given port.
**Kind**: instance method of [<code>PUPHub</code>](#PUPHub)
**Returns**: <code>Promise</code> - Resolved upon successful completion of command.
| Param | Type | Description |
| --- | --- | --- |
| port | <code>string</code> | |
| fromSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| toSpeed | <code>number</code> | For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0. |
| time | <code>number</code> | How long the ramp should last (in milliseconds). |
<a name="LPF2Hub+setName"></a>
### pupHub.setName(name) ⇒ <code>Promise</code>

View File

@ -133,6 +133,24 @@ export class BoostMoveHub extends LPF2Hub {
}
/**
* Ramp the motor speed on a given port.
* @method BoostMoveHub#rampMotorSpeed
* @param {string} port
* @param {number} fromSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} toSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} time How long the ramp should last (in milliseconds).
* @returns {Promise} Resolved upon successful completion of command.
*/
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time).on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed);
}).on("finished", resolve);
});
}
/**
* Rotate a motor by a given angle.
* @method BoostMoveHub#setMotorAngle

40
hub.ts
View File

@ -6,6 +6,7 @@ import { Port } from "./port";
import * as Consts from "./consts";
import Debug = require("debug");
import { resolve } from "path";
const debug = Debug("hub");
@ -89,7 +90,6 @@ export class Hub extends EventEmitter {
this._peripheral.connect((err: string) => {
this._rssi = this._peripheral.rssi;
const rssiUpdateInterval = setInterval(() => {
this._peripheral.updateRssi((err: string, rssi: number) => {
if (!err) {
@ -113,22 +113,16 @@ export class Hub extends EventEmitter {
}
debug("Service/characteristic discovery started");
const servicePromises: Array<Promise<null>> = [];
services.forEach((service) => {
servicePromises.push(new Promise((resolve, reject) => {
service.discoverCharacteristics([], (err, characteristics) => {
characteristics.forEach((characteristic) => {
this._characteristics[characteristic.uuid] = characteristic;
});
return resolve();
});
}));
});
Promise.all(servicePromises).then(() => {
@ -303,13 +297,43 @@ export class Hub extends EventEmitter {
if (speed < -100) {
speed = -100;
}
return Math.round((speed - -100) * (240 - 158) / (-1 - -100) + 158); // In reverse, minimum speed is 245, maximum speed is 160
return Math.round((speed - -100) * (240 - 158) / (-1 - -100) + 158); // In reverse, minimum speed is 240, maximum speed is 158
} else {
return 0;
}
}
protected _calculateRamp (fromSpeed: number, toSpeed: number, time: number) {
const emitter = new EventEmitter();
const steps = Math.abs(toSpeed - fromSpeed);
let delay = time / steps;
let increment = 1;
if (delay < 50 && steps > 0) {
increment = 50 / delay;
delay = 50;
}
if (fromSpeed > toSpeed) {
increment = -increment;
}
let i = 0;
const interval = setInterval(() => {
let speed = Math.round(fromSpeed + (++i * increment));
if (toSpeed > fromSpeed && speed > toSpeed) {
speed = toSpeed;
} else if (fromSpeed > toSpeed && speed < toSpeed) {
speed = toSpeed;
}
emitter.emit("changeSpeed", speed);
if (speed === toSpeed) {
clearInterval(interval);
emitter.emit("finished");
}
}, delay);
return emitter;
}
protected _portLookup (port: string) {
if (!this._ports[port.toUpperCase()]) {
throw new Error(`Port ${port.toUpperCase()} does not exist on this Hub type`);

View File

@ -6,6 +6,7 @@ import { Port } from "./port";
import * as Consts from "./consts";
import Debug = require("debug");
import { resolve } from "path";
const debug = Debug("puphub");
@ -126,4 +127,22 @@ export class PUPHub extends LPF2Hub {
}
/**
* Ramp the motor speed on a given port.
* @method PUPHub#rampMotorSpeed
* @param {string} port
* @param {number} fromSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} toSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} time How long the ramp should last (in milliseconds).
* @returns {Promise} Resolved upon successful completion of command.
*/
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time).on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed);
}).on("finished", resolve);
});
}
}

View File

@ -136,6 +136,24 @@ export class WeDo2SmartHub extends Hub {
}
/**
* Ramp the motor speed on a given port.
* @method WeDo2SmartHub#rampMotorSpeed
* @param {string} port
* @param {number} fromSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} toSpeed For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} time How long the ramp should last (in milliseconds).
* @returns {Promise} Resolved upon successful completion of command.
*/
public rampMotorSpeed (port: string, fromSpeed: number, toSpeed: number, time: number) {
return new Promise((resolve, reject) => {
this._calculateRamp(fromSpeed, toSpeed, time).on("changeSpeed", (speed) => {
this.setMotorSpeed(port, speed);
}).on("finished", resolve);
});
}
/**
* Play a sound on the Hub's in-built buzzer
* @method WeDo2SmartHub#playSound