Skip to content

Commit

Permalink
Add support for PWM resolutions other than 8-bit
Browse files Browse the repository at this point in the history
Required for ESP32. Addresses rwaldron#1275, rwaldron#1276, and rwaldron#1280
  • Loading branch information
dtex committed Sep 11, 2018
1 parent 210aaf4 commit 6c6b191
Show file tree
Hide file tree
Showing 12 changed files with 642 additions and 6 deletions.
6 changes: 6 additions & 0 deletions lib/board.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ function Board(opts) {
this.transport = this.io.transport || null;
this.port = this.io.name;
this.pins = Board.Pins(this);
this.RESOLUTION = this.io.RESOLUTION || { ADC: 1023, DAC: null, PWM: 255 };
} else {

if (this.port && opts.port) {
Expand Down Expand Up @@ -459,6 +460,11 @@ function finalizeAndBroadcast(data, type, io) {
}.bind(this), 1);
}.bind(this));
}

// Older versions of Firmata and some IO plugins
// may not have set RESOLUTION.
this.RESOLUTION = io.RESOLUTION || { ADC: 1023, DAC: null, PWM: 255 };

}

// If there is a REPL...
Expand Down
1 change: 1 addition & 0 deletions lib/led/led.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ var Controllers = {
var state = priv.get(this);
var output = typeof input !== "undefined" ? input : state.value;
var value = state.isAnode ? 255 - Board.constrain(output, 0, 255) : output;
value = Fn.map(value, 0, 255, 0, this.board.RESOLUTION.PWM);

// If pin is not a PWM pin and brightness is not HIGH or LOW, emit an error
if (value !== this.io.LOW && value !== this.io.HIGH && this.mode !== this.io.MODES.PWM) {
Expand Down
1 change: 1 addition & 0 deletions lib/led/rgb.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ var Controllers = {
if (state.isAnode) {
value = 255 - Board.constrain(value, 0, 255);
}
value = Fn.map(value, 0, 255, 0, this.board.RESOLUTION.PWM);

this.io.analogWrite(pin, value);
}, this);
Expand Down
4 changes: 2 additions & 2 deletions lib/motor.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ Motor.prototype.setPin = function(pin, value) {
};

Motor.prototype.setPWM = function(pin, value) {
this.io.analogWrite(pin, value);
this.io.analogWrite(pin, __.map(value, 0, 255, 0, this.board.RESOLUTION.PWM));
};

Motor.prototype.speed = function(opts) {
Expand All @@ -663,7 +663,7 @@ Motor.prototype.speed = function(opts) {
}

opts.speed = Board.constrain(opts.speed, 0, 255);

opts.saveSpeed = typeof opts.saveSpeed !== "undefined" ?
opts.saveSpeed : true;

Expand Down
2 changes: 1 addition & 1 deletion lib/pin.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ Pin.prototype.query = function(callback) {
*/

Pin.prototype.high = function() {
var value = this.type === "analog" ? 255 : 1;
var value = this.type === "analog" ? this.board.RESOLUTION.PWM : 1;
Pin.write(this, value);
this.emit("high");
return this;
Expand Down
6 changes: 6 additions & 0 deletions test/board.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ exports["Board"] = {
new Board();
},

defaultResolution: function(test) {
test.expect(1);
test.deepEqual(this.board.RESOLUTION, {PWM: 255, DAC: null, ADC: 1023});
test.done();
},

explicitTransport: function(test) {
test.expect(1);

Expand Down
4 changes: 2 additions & 2 deletions test/extended/servo.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ exports["Servo"] = {

this.servo.on("move:complete", function() {
test.equal(this.servo.value, 80);
test.equal(this.servoWrite.lastCall.args[1], 70);
test.equal(this.servoWrite.lastCall.args[1], 1300);
test.done();
}.bind(this));

Expand All @@ -237,7 +237,7 @@ exports["Servo"] = {

this.servo.on("move:complete", function() {
test.equal(this.servo.value, 80);
test.equal(this.servoWrite.lastCall.args[1], 110);
test.equal(this.servoWrite.lastCall.args[1], 1700);
test.done();
}.bind(this));

Expand Down
145 changes: 145 additions & 0 deletions test/led.js
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,151 @@ exports["Led - PWM"] = {
},
};

exports["Led - 10-bit PWM"] = {
setUp: function(done) {
this.board = newBoard();
this.sandbox = sinon.sandbox.create();
this.clock = this.sandbox.useFakeTimers();
this.analogWrite = this.sandbox.spy(MockFirmata.prototype, "analogWrite");
this.pinMode = this.sandbox.spy(MockFirmata.prototype, "pinMode");
this.enqueue = this.sandbox.stub(Animation.prototype, "enqueue");

// Override PWM Resolution
this.board.RESOLUTION.PWM = 1023;

this.led = new Led({
pin: 11,
board: this.board
});

done();
},

tearDown: function(done) {
Board.purge();
this.sandbox.restore();
done();
},

shape: testLedShape,

on: function(test) {
test.expect(2);

this.led.on();
test.ok(this.analogWrite.firstCall.calledWith(11, 1023));
test.equal(this.analogWrite.callCount, 1);
test.done();
},

onFromNull: function(test) {
test.expect(4);

this.mapget = this.sandbox.spy(Map.prototype, "get");

this.led = new Led({
pin: 11,
board: this.board
});

var state = this.mapget.lastCall.returnValue;

test.equal(state.value, null);

this.led.on();

test.equal(state.value, 255);
test.equal(this.analogWrite.callCount, 1);
test.ok(this.analogWrite.firstCall.calledWith(11, 1023));
test.done();
},

off: function(test) {
test.expect(2);

this.led.off();
test.ok(this.analogWrite.firstCall.calledWith(11, 0));
test.equal(this.analogWrite.callCount, 1);

test.done();
},

blink: function(test) {
test.expect(4);
/*
This test is incredibly important!
What this is asserting is that blinking PWM LED will
analogWrite the correct value of 255 when there is an
ACTIVE interval and the last value was 0.
*/
this.mapget = this.sandbox.spy(Map.prototype, "get");

this.led.off();
test.equal(this.led.isOn, false);

this.led.blink(1);

var state = this.mapget.lastCall.returnValue;

test.equal(state.value, 0);

this.clock.tick(1);
test.equal(this.led.isOn, true);
test.ok(this.analogWrite.lastCall.calledWith(11, 1023));

test.done();
},

toggle: function(test) {
test.expect(5);

this.led.off();
this.analogWrite.reset();

this.led.toggle();
test.ok(this.analogWrite.lastCall.calledWith(11, 1023));
test.ok(this.led.isOn);

this.led.toggle();
test.ok(this.analogWrite.lastCall.calledWith(11, 0));
test.ok(!this.led.isOn);

test.equal(this.analogWrite.callCount, 2);

test.done();
},

brightness: function(test) {
test.expect(4);

this.led.off();
this.analogWrite.reset();

this.led.brightness(255);
test.ok(this.analogWrite.lastCall.calledWith(11, 1023));

this.led.brightness(100);
test.ok(this.analogWrite.lastCall.calledWith(11, 401));

this.led.brightness(0);
test.ok(this.analogWrite.lastCall.calledWith(11, 0));

test.equal(this.analogWrite.callCount, 3);

test.done();
},

pulse: function(test) {
test.expect(1);

this.led.pulse();

test.equal(this.enqueue.callCount, 1);
test.done();
}
};

exports["Led - PCA9685 (I2C)"] = {
setUp: function(done) {
this.board = newBoard();
Expand Down
Loading

0 comments on commit 6c6b191

Please sign in to comment.