diff --git a/README.md b/README.md index 8e51eac9f..d2a71b277 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,12 @@ To interactively navigate the examples, visit the [Johnny-Five examples](http:// - [IR Reflectance](https://github.com/rwaldron/johnny-five/blob/master/docs/ir-reflect.md) - [IR Reflectance Array](https://github.com/rwaldron/johnny-five/blob/master/docs/ir-reflect-array.md) +### Proximity +- [Proximity](https://github.com/rwaldron/johnny-five/blob/master/docs/proximity.md) +- [Proximity - SRF10](https://github.com/rwaldron/johnny-five/blob/master/docs/proximity-srf10.md) +- [Proximity - MB1003](https://github.com/rwaldron/johnny-five/blob/master/docs/proximity-mb1003.md) +- [Proximity - HC-SR04](https://github.com/rwaldron/johnny-five/blob/master/docs/proximity-hcsr04.md) + ### Joystick - [Joystick](https://github.com/rwaldron/johnny-five/blob/master/docs/joystick.md) - [Joystick - Claw control](https://github.com/rwaldron/johnny-five/blob/master/docs/joystick-claw.md) diff --git a/docs/breadboard/proximity-hcsr04.fzz b/docs/breadboard/proximity-hcsr04.fzz new file mode 100644 index 000000000..f3959e5b1 Binary files /dev/null and b/docs/breadboard/proximity-hcsr04.fzz differ diff --git a/docs/breadboard/proximity-hcsr04.png b/docs/breadboard/proximity-hcsr04.png new file mode 100644 index 000000000..da5ca08d6 Binary files /dev/null and b/docs/breadboard/proximity-hcsr04.png differ diff --git a/docs/breadboard/proximity-mb1003.fzz b/docs/breadboard/proximity-mb1003.fzz new file mode 100644 index 000000000..6fe87f327 Binary files /dev/null and b/docs/breadboard/proximity-mb1003.fzz differ diff --git a/docs/breadboard/proximity-mb1003.png b/docs/breadboard/proximity-mb1003.png new file mode 100644 index 000000000..615924989 Binary files /dev/null and b/docs/breadboard/proximity-mb1003.png differ diff --git a/docs/breadboard/proximity-srf10.fzz b/docs/breadboard/proximity-srf10.fzz new file mode 100644 index 000000000..35bbadbec Binary files /dev/null and b/docs/breadboard/proximity-srf10.fzz differ diff --git a/docs/breadboard/proximity-srf10.png b/docs/breadboard/proximity-srf10.png new file mode 100644 index 000000000..90e53ba43 Binary files /dev/null and b/docs/breadboard/proximity-srf10.png differ diff --git a/docs/breadboard/proximity.fzz b/docs/breadboard/proximity.fzz new file mode 100644 index 000000000..03f1bb335 Binary files /dev/null and b/docs/breadboard/proximity.fzz differ diff --git a/docs/breadboard/proximity.png b/docs/breadboard/proximity.png new file mode 100644 index 000000000..9aa7ec7fa Binary files /dev/null and b/docs/breadboard/proximity.png differ diff --git a/docs/proximity-hcsr04.md b/docs/proximity-hcsr04.md new file mode 100644 index 000000000..89d06c0b5 --- /dev/null +++ b/docs/proximity-hcsr04.md @@ -0,0 +1,66 @@ + + +# Proximity - HC-SR04 + + +Basic ping Proximity example with HC-SR04 sensor. + + +Run with: +```bash +node eg/proximity-hcsr04.js +``` + + + +```javascript +var five = require("johnny-five"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "HCSR04", + pin: 7 + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); + +``` + + +## Illustrations / Photos + + +### Breadboard for "Proximity - HC-SR04" + + + +![docs/breadboard/proximity-hcsr04.png](breadboard/proximity-hcsr04.png)
+ +Fritzing diagram: [docs/breadboard/proximity-hcsr04.fzz](breadboard/proximity-hcsr04.fzz) + +  + + + + + +  + + + +## License +Copyright (c) 2012, 2013, 2014 Rick Waldron +Licensed under the MIT license. +Copyright (c) 2014, 2015 The Johnny-Five Contributors +Licensed under the MIT license. + + diff --git a/docs/proximity-mb1003.md b/docs/proximity-mb1003.md new file mode 100644 index 000000000..4b9313dbf --- /dev/null +++ b/docs/proximity-mb1003.md @@ -0,0 +1,66 @@ + + +# Proximity - MB1003 + + +Basic sonar Proximity example with MB1003 sensor. + + +Run with: +```bash +node eg/proximity-mb1003.js +``` + + + +```javascript +var five = require("johnny-five"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "MB1003", + pin: "A0" + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); + +``` + + +## Illustrations / Photos + + +### Breadboard for "Proximity - MB1003" + + + +![docs/breadboard/proximity-mb1003.png](breadboard/proximity-mb1003.png)
+ +Fritzing diagram: [docs/breadboard/proximity-mb1003.fzz](breadboard/proximity-mb1003.fzz) + +  + + + + + +  + + + +## License +Copyright (c) 2012, 2013, 2014 Rick Waldron +Licensed under the MIT license. +Copyright (c) 2014, 2015 The Johnny-Five Contributors +Licensed under the MIT license. + + diff --git a/docs/proximity-srf10.md b/docs/proximity-srf10.md new file mode 100644 index 000000000..17646571a --- /dev/null +++ b/docs/proximity-srf10.md @@ -0,0 +1,65 @@ + + +# Proximity - SRF10 + + +Basic sonar Proximity example with SRF10 sensor. + + +Run with: +```bash +node eg/proximity-srf10.js +``` + + + +```javascript +var five = require("johnny-five"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "SRF10" + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); + +``` + + +## Illustrations / Photos + + +### Breadboard for "Proximity - SRF10" + + + +![docs/breadboard/proximity-srf10.png](breadboard/proximity-srf10.png)
+ +Fritzing diagram: [docs/breadboard/proximity-srf10.fzz](breadboard/proximity-srf10.fzz) + +  + + + + + +  + + + +## License +Copyright (c) 2012, 2013, 2014 Rick Waldron +Licensed under the MIT license. +Copyright (c) 2014, 2015 The Johnny-Five Contributors +Licensed under the MIT license. + + diff --git a/docs/proximity.md b/docs/proximity.md new file mode 100644 index 000000000..d5ee7cfb9 --- /dev/null +++ b/docs/proximity.md @@ -0,0 +1,66 @@ + + +# Proximity + + +Basic infrared Proximity example + + +Run with: +```bash +node eg/proximity.js +``` + + + +```javascript +var five = require("johnny-five"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "GP2Y0A21YK", + pin: "A0" + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); + +``` + + +## Illustrations / Photos + + +### Breadboard for "Proximity" + + + +![docs/breadboard/proximity.png](breadboard/proximity.png)
+ +Fritzing diagram: [docs/breadboard/proximity.fzz](breadboard/proximity.fzz) + +  + + + + + +  + + + +## License +Copyright (c) 2012, 2013, 2014 Rick Waldron +Licensed under the MIT license. +Copyright (c) 2014, 2015 The Johnny-Five Contributors +Licensed under the MIT license. + + diff --git a/eg/proximity-hcsr04.js b/eg/proximity-hcsr04.js new file mode 100644 index 000000000..e8de84258 --- /dev/null +++ b/eg/proximity-hcsr04.js @@ -0,0 +1,18 @@ +var five = require("../lib/johnny-five.js"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "HCSR04", + pin: 7 + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); diff --git a/eg/proximity-mb1003.js b/eg/proximity-mb1003.js new file mode 100644 index 000000000..03e2ba5c3 --- /dev/null +++ b/eg/proximity-mb1003.js @@ -0,0 +1,18 @@ +var five = require("../lib/johnny-five.js"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "MB1003", + pin: "A0" + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); diff --git a/eg/proximity-srf10.js b/eg/proximity-srf10.js new file mode 100644 index 000000000..91cc26a7f --- /dev/null +++ b/eg/proximity-srf10.js @@ -0,0 +1,17 @@ +var five = require("../lib/johnny-five.js"); + +five.Board().on("ready", function() { + + var proximity = new five.Proximity({ + controller: "SRF10" + }); + + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); + }); + + proximity.on("change", function(data) { + console.log("The obstruction has moved."); + }); + +}); diff --git a/eg/proximity.js b/eg/proximity.js index 8344601bd..1afb648c7 100644 --- a/eg/proximity.js +++ b/eg/proximity.js @@ -1,51 +1,18 @@ -var five = require("../lib/johnny-five.js"), - prox, led; +var five = require("../lib/johnny-five.js"); five.Board().on("ready", function() { - // Create a new IR Proximity Sensor hardware instance. - // - // five.IR.Proximity(); - // - // (Alias of: - // new five.IR({ - // device: "GP2Y0D805Z0F", - // freq: 50 - // }); - // ) - // - - prox = new five.IR.Proximity(); - led = new five.Led(13); - - - - - - // Properties - - // prox.state - // - - // Proximity Event API - - // "motionstart" - // - // Fired motion is detected with 2" - // - + var proximity = new five.Proximity({ + controller: "GP2Y0A21YK", + pin: "A0" + }); - // "motionend" - // - // Fired following a "motionstart" event - // when no movement has occurred in X ms - // - prox.on("motionstart", function(err, timestamp) { - led.on(); + proximity.on("data", function(data) { + console.log(data.cm + "cm", data.in + "in"); }); - prox.on("motionend", function(err, timestamp) { - led.off(); + proximity.on("change", function(data) { + console.log("The obstruction has moved."); }); }); diff --git a/lib/distance.js b/lib/distance.js index f4ff8cfa7..ebd6ea98a 100644 --- a/lib/distance.js +++ b/lib/distance.js @@ -78,6 +78,8 @@ Controllers["0A02"] = Controllers.GP2Y0A02YK0F; /** * IR.Distance + * + * @deprecated * @constructor * * five.IR.Distance("A0"); @@ -114,7 +116,9 @@ function Distance(opts) { Object.defineProperties(this, controller); if (!this.toCm) { - this.toCm = opts.toCm || function(x) { return x; }; + this.toCm = opts.toCm || function(x) { + return x; + }; } Object.defineProperties(this, { @@ -129,7 +133,7 @@ function Distance(opts) { } }, cm: { - get: function () { + get: function() { return this.centimeters; } }, @@ -143,8 +147,8 @@ function Distance(opts) { return +(this.centimeters * 0.39).toFixed(2); } }, - in: { - get: function () { + in : { + get: function() { return this.inches; } }, diff --git a/lib/johnny-five.js b/lib/johnny-five.js index 909c815b1..e5a7dcd4a 100644 --- a/lib/johnny-five.js +++ b/lib/johnny-five.js @@ -26,6 +26,7 @@ module.exports = { Ping: require("./ping"), Pir: require("./pir"), Pin: require("./pin"), + Proximity: require("./proximity"), Relay: require("./relay"), Repl: require("./repl"), Sensor: require("./sensor"), @@ -66,8 +67,11 @@ module.exports.Digital = function(opts) { module.exports.Sensor.Analog = module.exports.Analog; module.exports.Sensor.Digital = module.exports.Digital; +/** + * @deprecated Will be deleted in version 0.9.0. Use Proximity instead. + */ module.exports.IR.Distance = function(opts) { - console.log("IR.Distance is deprecated. Use IR.Proximity instead"); + console.log("IR.Distance is deprecated. Use Proximity instead"); return new module.exports.Distance(opts); }; @@ -79,7 +83,11 @@ module.exports.IR.Motion = function(opt) { ); }; +/** + * @deprecated Will be deleted in version 0.9.0. Use Proximity instead. + */ module.exports.IR.Proximity = function(opts) { + console.log("IR.Proximity is deprecated. Use Proximity instead"); // Fix a naming mistake. if (module.exports.Distance.Controllers.includes(opts.controller)) { return new module.exports.Distance(opts); diff --git a/lib/proximity.js b/lib/proximity.js new file mode 100644 index 000000000..f41c7e66c --- /dev/null +++ b/lib/proximity.js @@ -0,0 +1,273 @@ +var Board = require("../lib/board.js"), + within = require("./mixins/within"), + __ = require("./fn"), + events = require("events"), + util = require("util"); + +function analogHandler(opts, dataHandler) { + + this.io.pinMode(this.pin, this.io.MODES.ANALOG); + + this.io.analogRead(this.pin, function(data) { + dataHandler.call(this, data); + }.bind(this)); + +} + +var Controllers = { + GP2Y0A21YK: { + // https://www.sparkfun.com/products/242 + initialize: { + value: analogHandler + }, + toCm: { + value: function(raw) { + return +(12343.85 * Math.pow(raw, -1.15)).toFixed(2); + } + } + }, + GP2D120XJ00F: { + // https://www.sparkfun.com/products/8959 + initialize: { + value: analogHandler + }, + toCm: { + value: function(raw) { + return +((2914 / (raw + 5)) - 1).toFixed(2); + } + } + }, + GP2Y0A02YK0F: { + // https://www.sparkfun.com/products/8958 + // 15cm - 150cm + initialize: { + value: analogHandler + }, + toCm: { + value: function(raw) { + return +(10650.08 * Math.pow(raw, -0.935) - 10).toFixed(2); + } + } + }, + GP2Y0A41SK0F: { + // https://www.sparkfun.com/products/12728 + // 4cm - 30cm + initialize: { + value: analogHandler + }, + toCm: { + value: function(raw) { + return +(2076 / (raw - 11)).toFixed(2); + } + } + }, + SRF10: { + initialize: { + value: function(opts, dataHandler) { + + var address = 0x70; + var delay = 65; + + // Set up I2C data connection + this.io.i2cConfig(0); + + // Startup parameter + this.io.i2cWrite(address, [0x01, 16]); + this.io.i2cWrite(address, [0x02, 255]); + + function read() { + this.io.i2cWrite(address, [0x02]); + this.io.i2cReadOnce(address, 2, function(data) { + dataHandler((data[0] << 8) | data[1]); + }.bind(this)); + + prime.call(this); + } + + function prime() { + // 0x51 result in cm (centimeters) + this.io.i2cWrite(address, [0x00, 0x51]); + + setTimeout(read.bind(this), delay); + } + + prime.call(this); + } + }, + toCm: { + value: function(raw) { + return raw; + } + } + }, + MB1003: { + initialize: { + value: analogHandler + }, + toCm: { + value: function(raw) { + // http://www.maxbotix.com/articles/032.htm + return raw / 2; + } + } + }, + HCSR04: { + initialize: { + value: function (opts, dataHandler) { + // Private settings object + var settings = { + pin: opts.pin, + value: this.io.HIGH, + pulseOut: 5 + }; + + setInterval(function() { + this.io.pulseIn(settings, function(microseconds) { + dataHandler(microseconds); + }); + }.bind(this), opts.freq || 25); + } + }, + toCm: { + value: function (raw) { + return +(raw / 29.1 / 2).toFixed(3); + } + } + } +}; + +// Sensor aliases +// IR +Controllers["2Y0A21"] = Controllers.GP2Y0A21YK; +Controllers["2D120X"] = Controllers.GP2D120XJ00F; +Controllers["2Y0A02"] = Controllers.GP2Y0A02YK0F; +Controllers["OA41SK"] = Controllers.GP2Y0A41SK0F; +Controllers["0A21"] = Controllers.GP2Y0A21YK; +Controllers["0A02"] = Controllers.GP2Y0A02YK0F; + +// Sonar +Controllers["HRLV-MaxSonar-EZ0"] = Controllers.MB1003; + +// Ping +Controllers["HC-SR04"] = Controllers.HCSR04; + +/** + * Proximity + * @constructor + * + * five.Proximity("A0"); + * + * five.Proximity({ + * controller: "GP2Y0A41SK0F", + * pin: "A0", + * freq: 100 + * }); + * + * + * @param {Object} opts [description] + * + */ + +function Proximity(opts) { + + if (!(this instanceof Proximity)) { + return new Proximity(opts); + } + + var controller; + var raw = 0; + var freq = opts.freq || 25; + var last = 0; + + Board.Device.call( + this, opts = Board.Options(opts) + ); + + if (typeof opts.controller === "string") { + controller = Controllers[opts.controller]; + } else { + controller = opts.controller || Controllers["GP2Y0A21YK"]; + } + + Object.defineProperties(this, controller); + + if (!this.toCm) { + this.toCm = opts.toCm || function(x) { + return x; + }; + } + + Object.defineProperties(this, { + /** + * [read-only] Calculated centimeter value + * @property centimeters + * @type Number + */ + centimeters: { + get: function() { + return this.toCm(raw); + } + }, + cm: { + get: function() { + return this.centimeters; + } + }, + /** + * [read-only] Calculated inch value + * @property inches + * @type Number + */ + inches: { + get: function() { + return +(this.centimeters * 0.39).toFixed(2); + } + }, + in: { + get: function() { + return this.inches; + } + }, + }); + + if (typeof this.initialize === "function") { + this.initialize(opts, function(data) { + raw = data; + }); + } + + setInterval(function() { + if (raw === undefined) { + return; + } + + var data = { + cm: this.cm, + centimeters: this.centimeters, + in : this.in, + inches: this.inches + }; + + this.emit("data", data); + + if (raw !== last) { + last = raw; + this.emit("change", data); + } + }.bind(this), freq); +} + +Proximity.Controllers = [ + "2Y0A21", "GP2Y0A21YK", + "2D120X", "GP2D120XJ00F", + "2Y0A02", "GP2Y0A02YK0F", + "OA41SK", "GP2Y0A41SK0F", + "0A21", "GP2Y0A21YK", + "0A02", "GP2Y0A02YK0F", +]; + +util.inherits(Proximity, events.EventEmitter); + +__.mixin(Proximity.prototype, within); + +module.exports = Proximity; diff --git a/test/proximity.js b/test/proximity.js index bb03b3691..546a64edc 100644 --- a/test/proximity.js +++ b/test/proximity.js @@ -3,15 +3,14 @@ var MockFirmata = require("./util/mock-firmata"), events = require("events"), sinon = require("sinon"), Board = five.Board, - Sensor = five.Sensor, - Proximity = five.IR.Proximity, + Proximity = five.Proximity, board = new Board({ io: new MockFirmata(), debug: false, repl: false }); -exports["IR.Proximity"] = { +exports["Proximity"] = { setUp: function(done) { this.clock = sinon.useFakeTimers(); this.analogRead = sinon.spy(board.io, "analogRead"); @@ -46,12 +45,6 @@ exports["IR.Proximity"] = { test.done(); }, - sensor: function(test) { - test.expect(1); - test.ok(this.distance instanceof Sensor); - test.done(); - }, - emitter: function(test) { test.expect(1); test.ok(this.distance instanceof events.EventEmitter); @@ -59,7 +52,7 @@ exports["IR.Proximity"] = { } }; -exports["IR.Proximity: GP2Y0A21YK"] = { +exports["Proximity: GP2Y0A21YK"] = { setUp: function(done) { this.clock = sinon.useFakeTimers(); this.analogRead = sinon.spy(board.io, "analogRead"); @@ -95,7 +88,7 @@ exports["IR.Proximity: GP2Y0A21YK"] = { } }; -exports["IR.Proximity: GP2D120XJ00F"] = { +exports["Proximity: GP2D120XJ00F"] = { setUp: function(done) { this.clock = sinon.useFakeTimers(); this.analogRead = sinon.spy(board.io, "analogRead"); @@ -130,7 +123,7 @@ exports["IR.Proximity: GP2D120XJ00F"] = { } }; -exports["IR.Proximity: GP2Y0A02YK0F"] = { +exports["Proximity: GP2Y0A02YK0F"] = { setUp: function(done) { this.clock = sinon.useFakeTimers(); this.analogRead = sinon.spy(board.io, "analogRead"); @@ -166,7 +159,7 @@ exports["IR.Proximity: GP2Y0A02YK0F"] = { } }; -exports["IR.Proximity: GP2Y0A41SK0F"] = { +exports["Proximity: GP2Y0A41SK0F"] = { setUp: function(done) { this.clock = sinon.useFakeTimers(); this.analogRead = sinon.spy(board.io, "analogRead"); @@ -202,6 +195,280 @@ exports["IR.Proximity: GP2Y0A41SK0F"] = { } }; +exports["Proximity: MB1003"] = { + setUp: function(done) { + this.clock = sinon.useFakeTimers(); + this.analogRead = sinon.spy(board.io, "analogRead"); + this.distance = new Proximity({ + controller: "MB1003", + pin: "A1", + board: board + }); + + done(); + }, + + tearDown: function(done) { + this.clock.restore(); + this.analogRead.restore(); + done(); + }, + + MB1003: function(test) { + var callback = this.analogRead.args[0][1]; + + test.expect(4); + + // 500 is an actual reading at ~250cm + callback(500); + + test.equals(Math.round(this.distance.centimeters), 250); + test.equals(Math.round(this.distance.cm), 250); + test.equals(Math.round(this.distance.inches), 98); + test.equals(Math.round(this.distance.in), 98); + + test.done(); + } +}; + + +exports["Proximity: SRF10"] = { + + setUp: function(done) { + + this.clock = sinon.useFakeTimers(); + this.i2cReadOnce = sinon.spy(board.io, "i2cReadOnce"); + this.i2cWrite = sinon.spy(board.io, "i2cWrite"); + this.i2cConfig = sinon.spy(board.io, "i2cConfig"); + + this.proximity = new Proximity({ + controller: "SRF10", + board: board + }); + + this.proto = [{ + name: "within" + }]; + + this.instance = [{ + name: "centimeters" + }, { + name: "cm" + },{ + name: "inches" + }, { + name: "in" + }]; + + done(); + }, + + tearDown: function(done) { + this.clock.restore(); + this.i2cReadOnce.restore(); + this.i2cWrite.restore(); + this.i2cConfig.restore(); + + done(); + }, + + shape: function(test) { + test.expect(this.proto.length + this.instance.length); + + this.proto.forEach(function(method) { + test.equal(typeof this.proximity[method.name], "function"); + }, this); + + this.instance.forEach(function(property) { + test.notEqual(typeof this.proximity[property.name], 0); + }, this); + + test.done(); + }, + + initialize: function(test) { + test.expect(5); + + test.ok(this.i2cConfig.called); + test.ok(this.i2cWrite.calledThrice); + + test.deepEqual(this.i2cConfig.args[0], [0]); + test.deepEqual( + this.i2cWrite.firstCall.args, [0x70, [0x01, 16]] + ); + test.deepEqual( + this.i2cWrite.secondCall.args, [0x70, [0x02, 255]] + ); + + test.done(); + }, + + data: function(test) { + test.expect(2); + + this.clock.tick(100); + + var callback = this.i2cReadOnce.args[0][2], + spy = sinon.spy(); + + test.equal(spy.callCount, 0); + + this.proximity.on("data", spy); + + callback([3, 225]); + callback([3, 255]); + + this.clock.tick(100); + + test.ok(spy.called); + test.done(); + }, + + change: function(test) { + this.clock.tick(100); + + var callback = this.i2cReadOnce.args[0][2], + spy = sinon.spy(); + + test.expect(1); + this.proximity.on("change", spy); + + this.clock.tick(100); + callback([3, 225]); + + this.clock.tick(100); + callback([3, 255]); + + this.clock.tick(100); + + test.ok(spy.called); + test.done(); + }, + + within_unit: function(test) { + this.clock.tick(65); + + var callback = this.i2cReadOnce.args[0][2]; + var called = false; + + test.expect(1); + + this.proximity.within([3, 6], "inches", function() { + if (!called) { + called = true; + test.equal(this.inches, 3.9); + test.done(); + } + }); + + callback([0, 10]); + this.clock.tick(100); + } +}; + +exports["Proximity: HCSR04"] = { + setUp: function(done) { + this.clock = sinon.useFakeTimers(); + this.pulseVal = 1000; + + sinon.stub(board.io, "pulseIn", function(settings, handler) { + handler(this.pulseVal); + }.bind(this)); + + this.ping = new Proximity({ + controller: "HCSR04", + pin: 7, + freq: 100, + board: board + }); + + this.proto = [{ + name: "within" + }]; + + this.instance = [{ + name: "centimeters" + }, { + name: "cm" + },{ + name: "inches" + }, { + name: "in" + }]; + + done(); + }, + + tearDown: function(done) { + board.io.pulseIn.restore(); + this.clock.restore(); + done(); + }, + + shape: function(test) { + test.expect(this.proto.length + this.instance.length); + + this.proto.forEach(function(method) { + test.equal(typeof this.ping[method.name], "function"); + }, this); + + this.instance.forEach(function(property) { + test.notEqual(typeof this.ping[property.name], 0); + }, this); + + test.done(); + }, + + data: function(test) { + var spy = sinon.spy(); + test.expect(1); + + // tick the clock forward to trigger the pulseIn handler + this.clock.tick(250); + + this.ping.on("data", spy); + this.clock.tick(100); + test.ok(spy.calledOnce); + test.done(); + }, + + change: function(test) { + var spy = sinon.spy(); + test.expect(1); + + this.pulseVal = 0; + + // tick the clock forward to trigger the pulseIn handler + this.clock.tick(250); + + this.pulseVal = 1000; + + this.ping.on("change", spy); + this.clock.tick(100); + test.ok(spy.calledOnce); + test.done(); + + }, + + within: function(test) { + var spy = sinon.spy(); + test.expect(2); + + // tick the clock forward to trigger the pulseIn handler + this.clock.tick(250); + + this.ping.within([0, 120], "inches", function() { + // The fake microseconds value is 1000, which + // calculates to 6.76 inches. + test.equal(this.inches, 6.7); + spy(); + }); + + this.clock.tick(100); + test.ok(spy.calledOnce); + test.done(); + } +}; // - GP2Y0A21YK // https://www.sparkfun.com/products/242 diff --git a/tpl/programs.json b/tpl/programs.json index d94fe2103..f024d8a09 100644 --- a/tpl/programs.json +++ b/tpl/programs.json @@ -421,6 +421,32 @@ } ] }, + { + "topic": "Proximity", + "classes": ["Proximity"], + "examples": [ + { + "file": "proximity.js", + "title": "Proximity", + "description": "Basic infrared Proximity example" + }, + { + "file": "proximity-srf10.js", + "title": "Proximity - SRF10", + "description": "Basic sonar Proximity example with SRF10 sensor." + }, + { + "file": "proximity-mb1003.js", + "title": "Proximity - MB1003", + "description": "Basic sonar Proximity example with MB1003 sensor." + }, + { + "file": "proximity-hcsr04.js", + "title": "Proximity - HC-SR04", + "description": "Basic ping Proximity example with HC-SR04 sensor." + } + ] + }, { "topic": "Joystick", "classes": ["Joystick"],