Adding power and brightness ramping back in
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Nathan Kellenicki 2020-01-13 10:58:57 -08:00
parent 63f1c10fcc
commit 5fde49c0c2
6 changed files with 104 additions and 4 deletions

View File

@ -44,6 +44,7 @@ export class AbsoluteMotor extends TachoMotor {
if (this.isWeDo2SmartHub) {
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
}
this.cancelEventTimer();
return new Promise((resolve) => {
this._busy = true;
if (speed === undefined || speed === null) {
@ -78,6 +79,7 @@ export class AbsoluteMotor extends TachoMotor {
if (this.isWeDo2SmartHub) {
throw new Error("Absolute positioning is not available on the WeDo 2.0 Smart Hub");
}
this.cancelEventTimer();
return new Promise((resolve) => {
this._busy = true;
let message;
@ -97,6 +99,7 @@ export class AbsoluteMotor extends TachoMotor {
}
public async calibrateServo () {
this.cancelEventTimer();
const oldMode = this.mode;
let currentAngle = 0;
const listener = ({ angle }: { angle: number }) => {
@ -142,6 +145,7 @@ export class AbsoluteMotor extends TachoMotor {
}
public async resetServo (angle: number) {
this.cancelEventTimer();
const oldMode = this.mode;
let currentAngle = 0;
const listener = ({ angle }: { angle: number }) => {

View File

@ -4,7 +4,7 @@ import { IDeviceInterface } from "../interfaces";
import * as Consts from "../consts";
import { mapSpeed } from "../utils";
import { calculateRamp, mapSpeed } from "../utils";
export class BasicMotor extends Device {
@ -20,7 +20,10 @@ export class BasicMotor extends Device {
* @param {number} power For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @returns {Promise} Resolved upon successful completion of command.
*/
public setPower (power: number) {
public setPower (power: number, interrupt: boolean = true) {
if (interrupt) {
this.cancelEventTimer();
}
return new Promise((resolve) => {
this.writeDirect(0x00, Buffer.from([mapSpeed(power)]));
return resolve();
@ -28,12 +31,33 @@ export class BasicMotor extends Device {
}
/**
* Ramp the motor power.
* @method BasicMotor#rampPower
* @param {number} fromPower For forward, a value between 1 - 100 should be set. For reverse, a value between -1 to -100. Stop is 0.
* @param {number} toPower 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 rampPower (fromPower: number, toPower: number, time: number) {
this.cancelEventTimer();
return new Promise((resolve) => {
calculateRamp(this, fromPower, toPower, time)
.on("changePower", (power) => {
this.setPower(power, false);
})
.on("finished", resolve);
});
}
/**
* Stop the motor.
* @method BasicMotor#stop
* @returns {Promise} Resolved upon successful completion of command.
*/
public stop () {
this.cancelEventTimer();
return this.setPower(0);
}
@ -44,6 +68,7 @@ export class BasicMotor extends Device {
* @returns {Promise} Resolved upon successful completion of command.
*/
public brake () {
this.cancelEventTimer();
return this.setPower(127);
}

View File

@ -20,6 +20,7 @@ export class Device extends EventEmitter {
private _isWeDo2SmartHub: boolean;
private _isVirtualPort: boolean = false;
private _eventTimer: NodeJS.Timer | null = null;
constructor (hub: IDeviceInterface, portId: number, modeMap: {[event: string]: number} = {}, type: Consts.DeviceType = Consts.DeviceType.UNKNOWN) {
super();
@ -136,6 +137,17 @@ export class Device extends EventEmitter {
}
}
public setEventTimer (timer: NodeJS.Timer) {
this._eventTimer = timer;
}
public cancelEventTimer () {
if (this._eventTimer) {
clearTimeout(this._eventTimer);
this._eventTimer = null;
}
}
private _ensureConnected () {
if (!this.connected) {
throw new Error("Device is not connected");

View File

@ -3,6 +3,7 @@ import { Device } from "./device";
import { IDeviceInterface } from "../interfaces";
import * as Consts from "../consts";
import { calculateRamp } from "../utils";
export class Light extends Device {
@ -14,11 +15,14 @@ export class Light extends Device {
/**
* Set the light brightness.
* @method Light#brightness
* @method Light#setBrightness
* @param {number} brightness Brightness value between 0-100 (0 is off)
* @returns {Promise} Resolved upon successful completion of command.
*/
public setBrightness (brightness: number) {
public setBrightness (brightness: number, interrupt: boolean = true) {
if (interrupt) {
this.cancelEventTimer();
}
return new Promise((resolve) => {
this.writeDirect(0x00, Buffer.from([brightness]));
return resolve();
@ -26,4 +30,24 @@ export class Light extends Device {
}
/**
* Ramp the light brightness.
* @method Light#rampBrightness
* @param {number} fromBrightness Brightness value between 0-100 (0 is off)
* @param {number} toBrightness Brightness value between 0-100 (0 is off)
* @param {number} time How long the ramp should last (in milliseconds).
* @returns {Promise} Resolved upon successful completion of command.
*/
public rampBrightness (fromBrightness: number, toBrightness: number, time: number) {
this.cancelEventTimer();
return new Promise((resolve) => {
calculateRamp(this, fromBrightness, toBrightness, time)
.on("changePower", (power) => {
this.setBrightness(power, false);
})
.on("finished", resolve);
});
}
}

View File

@ -40,6 +40,7 @@ export class TachoMotor extends BasicMotor {
if (this.isWeDo2SmartHub) {
throw new Error("Motor speed is not available on the WeDo 2.0 Smart Hub");
}
this.cancelEventTimer();
return new Promise((resolve) => {
this._busy = true;
if (speed === undefined || speed === null) {
@ -81,6 +82,7 @@ export class TachoMotor extends BasicMotor {
if (this.isWeDo2SmartHub) {
throw new Error("Rotation is not available on the WeDo 2.0 Smart Hub");
}
this.cancelEventTimer();
return new Promise((resolve) => {
this._busy = true;
if (speed === undefined || speed === null) {

View File

@ -1,3 +1,6 @@
import { EventEmitter } from "events";
import { Device } from "./devices/device";
// @ts-ignore
export const isWebBluetooth = (typeof navigator !== "undefined" && navigator && navigator.bluetooth);
@ -55,3 +58,33 @@ export const roundAngleToNearest90 = (angle: number) => {
}
return -180;
};
export const calculateRamp = (device: Device, fromPower: number, toPower: number, time: number) => {
const emitter = new EventEmitter();
const steps = Math.abs(toPower - fromPower);
let delay = time / steps;
let increment = 1;
if (delay < 50 && steps > 0) {
increment = 50 / delay;
delay = 50;
}
if (fromPower > toPower) {
increment = -increment;
}
let i = 0;
const interval = setInterval(() => {
let power = Math.round(fromPower + (++i * increment));
if (toPower > fromPower && power > toPower) {
power = toPower;
} else if (fromPower > toPower && power < toPower) {
power = toPower;
}
emitter.emit("changePower", power);
if (power === toPower) {
clearInterval(interval);
emitter.emit("finished");
}
}, delay);
device.setEventTimer(interval);
return emitter;
};