Skip to content

Commit

Permalink
PWM Support (requires latest, unreleased t2-firmware)
Browse files Browse the repository at this point in the history
Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
  • Loading branch information
rwaldron committed Apr 1, 2016
1 parent 8544337 commit 464bcf2
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 25 deletions.
81 changes: 64 additions & 17 deletions lib/tessel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var modes = Object.freeze({
OUTPUT: 1,
ANALOG: 2,
PWM: 3,
// SERVO: 4,
SERVO: 4,
I2C: 6,
});

Expand All @@ -35,17 +35,17 @@ var pinModes = [
{ modes: [0, 1 ] },
{ modes: [0, 1 ] },
{ modes: [0, 1, 2 ], analogChannel: 0 },
{ modes: [0, 1 ] },
{ modes: [0, 1 ] },
{ modes: [0, 1, 3, 4, ] },
{ modes: [0, 1, 3, 4, ] },
{ modes: [0, 1, 2 ], analogChannel: 1 },
// Port B
{ modes: [0, 1, 2 , 6], analogChannel: 2 },
{ modes: [0, 1, 2 , 6], analogChannel: 3 },
{ modes: [0, 1, 2 ], analogChannel: 4 },
{ modes: [0, 1, 2 ], analogChannel: 5 },
{ modes: [0, 1, 2 ], analogChannel: 6 },
{ modes: [0, 1, 2 ], analogChannel: 7 },
{ modes: [0, 1, 2 ], analogChannel: 8 },
{ modes: [0, 1, 2, 3, 4, ], analogChannel: 7 },
{ modes: [0, 1, 2, 3, 4, ], analogChannel: 8 },
{ modes: [0, 1, 2, 3 ], analogChannel: 9 },
];

Expand Down Expand Up @@ -115,7 +115,7 @@ function ToI2CBusPort(value) {
return undefined;
}

var samplingInterval = 0;
var samplingInterval = 5;

function read() {
if (read.interval) {
Expand All @@ -137,8 +137,6 @@ function read() {
}, samplingInterval);
}

samplingInterval = 10;

function processRead(board, report, value) {
value = +value;

Expand Down Expand Up @@ -190,7 +188,7 @@ function Pin(options) {
var state = {
isAnalog: false,
pin: pin,
index: pin.pin,
index: (options.port === "B" ? 8 : 0) + pin.pin,
mode: 0
};

Expand Down Expand Up @@ -222,14 +220,15 @@ function Pin(options) {
pin.input();
}

if (value === 1 || value === 3) {
if (value === 1 || value === 3 || value === 4) {
// TODO: Make sure this doesn't
// interfere with pwmWrite
pin.output();
}

state.isPwm = value === 3;
state.isAnalog = value === 2;
state.isPwm = value === 3 || value === 4;
state.isServo = value === 4;
state.mode = value;
}
}
Expand All @@ -243,8 +242,12 @@ function Pin(options) {
Pin.prototype.write = function(value) {
var state = priv.get(this);

if (state.isPwm) {
state.pin._port.sock.write(new Buffer([Port.CMD.ANALOG_WRITE, value >> 8, value & 0xff]));
if (state.isPwm || state.isServo) {
if (state.index === 15) {
state.pin._port.sock.write(new Buffer([Port.CMD.ANALOG_WRITE, value >> 8, value & 0xff]));
} else {
state.pin.pwmDutyCycle(value);
}
} else {
state.pin.write(value);
}
Expand Down Expand Up @@ -299,6 +302,10 @@ function Tessel(options) {
options = options || {};

var state = {
pwm: {
// MHz
frequency: null,
},
i2c: {
// Defaults to Port A I2C bus
bus: ToPortI2CBus(options.i2c !== undefined ? options.i2c.bus : 4),
Expand Down Expand Up @@ -348,7 +355,7 @@ Tessel.prototype = Object.create(Emitter.prototype, {
});

Tessel.prototype.setSamplingInterval = function(ms) {
samplingInterval = Math.min(Math.max(ms, 10), 65535);
samplingInterval = Math.min(Math.max(ms, 5), 65535);
global.clearInterval(read.interval);
read();
};
Expand Down Expand Up @@ -412,16 +419,56 @@ Tessel.prototype.analogRead = function(pin, handler) {
return this;
};

var PWM_FREQUENCY = 490;
var PWM_MIN = 0;
var PWM_MAX = 1;

var SERVO_FREQUENCY = 50;
var SERVO_MIN = 0.03;
var SERVO_MAX = 0.12;

var pwms = [5, 6, 13, 14, 15];

// This is not really correct, but the resulting behavior is observably similar.
Tessel.prototype.pwmWrite = function(pin, value) {
this.pins[ToPinIndex(pin)].write(scale(constrain(value, 0, 255), 0, 255, 0, 1023));
var state = priv.get(this);
var index = ToPinIndex(pin);
var constrained = constrain(value, 0, 255);
var output = 0;

if (pwms.includes(index)) {
// For B7/15, use the DAC
if (index === 15) {
output = scale(constrained, 0, 255, 0, 1023) | 0;
} else {
if (state.pwm.frequency !== PWM_FREQUENCY) {
state.pwm.frequency = PWM_FREQUENCY;
tessel.pwmFrequency(PWM_FREQUENCY);
}
output = scale(constrained, 0, 255, 0, 1);
}

this.pins[index].write(output);
}
return this;
};

Tessel.prototype.analogWrite = Tessel.prototype.pwmWrite;

Tessel.prototype.servoWrite = function(pin, value) {
var state = priv.get(this);
var index = ToPinIndex(pin);
var constrained = constrain(value, 0, 180);

if (pwms.slice(0, -1).includes(index)) {
if (state.pwm.frequency !== SERVO_FREQUENCY) {
state.pwm.frequency = SERVO_FREQUENCY;
tessel.pwmFrequency(SERVO_FREQUENCY);
}
this.pins[index].write(scale(constrained, 0, 180, 0.03, 0.12));
}
return this;
};

// Note: Tessel-IO will default to Port A if no bus is specified.
Tessel.prototype.i2cConfig = function(options) {
var state = priv.get(this);
Expand Down Expand Up @@ -591,7 +638,7 @@ function constrain(value, low, high) {

function scale(value, fromLow, fromHigh, toLow, toHigh) {
return ((value - fromLow) * (toHigh - toLow) /
(fromHigh - fromLow) + toLow) | 0;
(fromHigh - fromLow) + toLow);
}

if (process.env.IS_TEST_ENV) {
Expand Down
6 changes: 6 additions & 0 deletions test/tessel-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ function Tessel() {
this.version = 2;
}

Tessel.prototype.pwmFrequency = function(frequency, cb) {};

Tessel.Port = function(name, socketPath, board) {
var port = this;

Expand Down Expand Up @@ -316,6 +318,8 @@ Tessel.Pin.prototype.readPulse = function(type, timeout, callback) {
var ANALOG_RESOLUTION = 4096;
Tessel.Pin.prototype.resolution = ANALOG_RESOLUTION;

Tessel.Pin.prototype.pwmDutyCycle = function(duty, callback) {};

Tessel.Pin.prototype.analogRead = function(cb) {
if (!this.analogSupported) {
console.warn("pin.analogRead is not supoprted on this pin. Analog read is supported on port A pins 4 and 7 and on all pins on port B");
Expand Down Expand Up @@ -548,6 +552,8 @@ var CMD = {
TXRX: 18,
START: 19,
STOP: 20,
PWM_DUTY_CYCLE: 27,
PWM_PERIOD: 28,
};

var REPLY = {
Expand Down
Loading

0 comments on commit 464bcf2

Please sign in to comment.