Skip to content

Commit 0d5ca14

Browse files
committed
ESC: deprecate speed(percent), introduce throttle(us).
- Eliminates "history" memory leak - Deprecates speed() - Introduces throttle(us)
1 parent b3c5df9 commit 0d5ca14

File tree

2 files changed

+86
-291
lines changed

2 files changed

+86
-291
lines changed

lib/esc.js

+59-111
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var Controllers = {
1616
var state = priv.get(this);
1717

1818
this.address = opts.address || 0x40;
19-
this.pwmRange = opts.pwmRange || [544, 2400];
19+
this.pwmRange = opts.pwmRange || [1000, 2000];
2020
this.frequency = opts.frequency || 50;
2121

2222
state.expander = Expander.get({
@@ -32,9 +32,9 @@ var Controllers = {
3232
},
3333
write: {
3434
writable: true,
35-
value: function(pin, microseconds) {
35+
value: function(pin, us) {
3636
var state = priv.get(this);
37-
state.expander.servoWrite(pin, microseconds);
37+
state.expander.servoWrite(pin, us);
3838
}
3939
}
4040
},
@@ -56,20 +56,19 @@ var Controllers = {
5656
},
5757
write: {
5858
writable: true,
59-
value: function(pin, microseconds) {
60-
microseconds |= 0;
61-
this.io.servoWrite(pin, microseconds);
59+
value: function(pin, us) {
60+
this.io.servoWrite(pin, us | 0);
6261
}
6362
}
6463
}
6564
};
6665

66+
6767
var Devices = {
6868
FORWARD: {
6969
deviceName: {
70-
get: function() {
71-
return "FORWARD";
72-
}
70+
value: "FORWARD",
71+
writable: false,
7372
},
7473
dir: {
7574
value: function(speed, dir) {
@@ -81,9 +80,8 @@ var Devices = {
8180
},
8281
FORWARD_REVERSE: {
8382
deviceName: {
84-
get: function() {
85-
return "FORWARD_REVERSE";
86-
}
83+
value: "FORWARD_REVERSE",
84+
writable: false,
8785
},
8886
dir: {
8987
value: function(speed, dir) {
@@ -97,9 +95,8 @@ var Devices = {
9795
},
9896
FORWARD_BRAKE_REVERSE: {
9997
deviceName: {
100-
get: function() {
101-
return "FORWARD_BRAKE_REVERSE";
102-
}
98+
value: "FORWARD_BRAKE_REVERSE",
99+
writable: false,
103100
},
104101
dir: {
105102
value: function(speed, dir) {
@@ -140,14 +137,7 @@ function ESC(opts) {
140137
var pinValue;
141138
var device;
142139
var state = {
143-
// All speed history for this ESC
144-
// history = [
145-
// {
146-
// timestamp: Date.now(),
147-
// speed: speed
148-
// }
149-
// ];
150-
history: [],
140+
last: { speed: null },
151141
value: 0
152142
};
153143

@@ -157,12 +147,19 @@ function ESC(opts) {
157147

158148
priv.set(this, state);
159149

160-
this.startAt = typeof opts.startAt !== "undefined" ? opts.startAt : null;
161-
this.neutral = opts.neutral;
162150
this.range = opts.range || [0, 100];
163-
this.pwmRange = opts.pwmRange || [544, 2400];
151+
this.pwmRange = opts.pwmRange || [1000, 2000];
152+
this.neutral = opts.neutral || this.pwmRange[0];
164153
this.interval = null;
165154

155+
// Scale to pwm range
156+
if (typeof this.neutral !== "undefined" && this.neutral <= 100) {
157+
this.neutral = Fn.scale(this.neutral, 0, 100, this.pwmRange[0], this.pwmRange[1]);
158+
}
159+
160+
// Enforce pwm range on neutral point
161+
this.neutral = Fn.constrain(this.neutral, this.pwmRange[0], this.pwmRange[1]);
162+
166163
// StandardFirmata on Arduino allows controlling
167164
// servos from analog pins.
168165
// If we're currently operating with an Arduino
@@ -209,34 +206,22 @@ function ESC(opts) {
209206
return state.value;
210207
}
211208
},
212-
history: {
213-
get: function() {
214-
return state.history.slice(-5);
215-
}
216-
},
217209
last: {
218210
get: function() {
219-
return state.history[state.history.length - 1] || {
220-
last: null
221-
};
211+
return state.last;
222212
}
223213
}
224214
}));
225215

226216
this.initialize(opts);
227217

228218
if (this.deviceName !== "FORWARD") {
229-
if (Number.isNaN(+this.neutral)) {
230-
throw new Error("Directional speed controllers require a neutral point from 0-100 (number)");
219+
if (this.neutral === this.pwmRange[0]) {
220+
throw new Error("Bidirectional speed controllers require a non-zero neutral point");
231221
}
232-
233-
this.startAt = this.neutral;
234222
}
235223

236-
// Match either null or undefined, but not 0
237-
if (this.startAt !== null && this.startAt !== undefined) {
238-
this.speed(this.startAt);
239-
}
224+
this.throttle(this.neutral);
240225
}
241226

242227
util.inherits(ESC, Emitter);
@@ -249,11 +234,11 @@ util.inherits(ESC, Emitter);
249234
* @param {Float} speed 0...100 (full range)
250235
*
251236
* @return {ESC} instance
237+
* @deprecated Will be deleted in version 1.0.0. Use throttle(us) instead.
252238
*/
253-
254-
ESC.prototype.speed = function(speed) {
239+
/* istanbul ignore next */
240+
ESC.prototype.speed = util.deprecate(function(speed) {
255241
var state = priv.get(this);
256-
var history = state.history;
257242
var noInterval = false;
258243
var steps = 0;
259244
var lspeed, hspeed;
@@ -263,7 +248,7 @@ ESC.prototype.speed = function(speed) {
263248
if (this.interval) {
264249
// Bail out if speed is the same as whatever was
265250
// last _provided_
266-
if (this.value === speed) {
251+
if (state.value === speed) {
267252
return this;
268253
} else {
269254
clearInterval(this.interval);
@@ -276,18 +261,18 @@ ESC.prototype.speed = function(speed) {
276261
// This is the very first speed command being received.
277262
// Safe to assume that the ESC and Brushless motor are
278263
// not yet moving.
279-
if (history.length === 0) {
264+
if (state.last.speed === null) {
280265
noInterval = true;
266+
state.last.speed = this.neutral;
267+
} else {
268+
// Bail out if speed is the same as whatever was
269+
// last _written_
270+
if (state.last.speed === speed) {
271+
return this;
272+
}
281273
}
282274

283-
// Bail out if speed is the same as whatever was
284-
// last _written_
285-
286-
if (this.last.speed === speed) {
287-
return this;
288-
}
289-
290-
lspeed = this.last.speed;
275+
lspeed = state.last.speed;
291276
hspeed = speed;
292277
steps = Math.ceil(Math.abs(lspeed - hspeed));
293278

@@ -298,10 +283,7 @@ ESC.prototype.speed = function(speed) {
298283
if (noInterval) {
299284
this.write(this.pin, Fn.fscale(speed, 0, 100, this.pwmRange[0], this.pwmRange[1]));
300285

301-
history.push({
302-
timestamp: Date.now(),
303-
speed: speed
304-
});
286+
state.last.speed = speed;
305287
return this;
306288
}
307289

@@ -317,10 +299,7 @@ ESC.prototype.speed = function(speed) {
317299

318300
this.write(this.pin, Fn.fscale(throttle, 0, 100, this.pwmRange[0], this.pwmRange[1]));
319301

320-
history.push({
321-
timestamp: Date.now(),
322-
speed: throttle
323-
});
302+
state.last.speed = throttle;
324303

325304
if (steps) {
326305
steps--;
@@ -333,24 +312,29 @@ ESC.prototype.speed = function(speed) {
333312
}.bind(this), 1);
334313

335314
return this;
336-
};
315+
}, "ESC.prototype.speed: Use `throttle(μs)` (544-2400μs) instead");
316+
337317

318+
/**
319+
* throttle
320+
*
321+
* Throttle the ESC's speed by setting the pulse
322+
*
323+
* @param {Integer} throttle pwmRange[0]...pwmRange[1] (full usec range)
324+
*
325+
* @return {ESC} instance
326+
*/
327+
ESC.prototype.throttle = function(pulse) {
328+
this.write(this.pin, Fn.constrain(pulse, this.pwmRange[0], this.pwmRange[1]));
329+
return this;
330+
};
338331

339332
/**
340333
* brake Stop the ESC by hitting the brakes ;)
341334
* @return {Object} instance
342335
*/
343336
ESC.prototype.brake = function() {
344-
var state = priv.get(this);
345-
var speed = this.neutral || 0;
346-
347-
this.speed(speed);
348-
349-
state.history.push({
350-
timestamp: Date.now(),
351-
speed: speed
352-
});
353-
337+
this.write(this.pin, this.neutral);
354338
return this;
355339
};
356340

@@ -394,17 +378,7 @@ ESC.prototype.brake = function() {
394378
* @return {Object} instance
395379
*/
396380
ESC.prototype.stop = function() {
397-
var state = priv.get(this);
398-
var history = state.history;
399-
var speed = this.type === "bidirectional" ? this.neutral : 0;
400-
401-
this.write(this.pin, Fn.fscale(speed, 0, 100, this.pwmRange[0], this.pwmRange[1]));
402-
403-
history.push({
404-
timestamp: Date.now(),
405-
speed: speed
406-
});
407-
381+
this.write(this.pin, this.neutral);
408382
return this;
409383
};
410384

@@ -428,32 +402,6 @@ function ESCs(numsOrObjects) {
428402

429403
util.inherits(ESCs, Collection);
430404

431-
/**
432-
*
433-
* ESCs, speed(0-100%)
434-
*
435-
* set all escs to the specified speed from 0-100%
436-
*
437-
* eg. array.min();
438-
439-
* ESCs, min()
440-
*
441-
* set all escs to the minimum throttle
442-
*
443-
* eg. array.min();
444-
445-
* ESCs, max()
446-
*
447-
* set all escs to the maximum throttle
448-
*
449-
* eg. array.max();
450-
451-
* ESCs, stop()
452-
*
453-
* stop all escs
454-
*
455-
* eg. array.stop();
456-
*/
457405

458406
Collection.installMethodForwarding(
459407
ESCs.prototype, ESC.prototype

0 commit comments

Comments
 (0)