UNPKG

johnny-five

Version:

The JavaScript Arduino Programming Framework.

370 lines (305 loc) 8.92 kB
// var Board = require("../lib/board.js"), // events = require("events"), // util = require("util"), // __ = require("../lib/fn.js"); // function calculate(method, y, x) { // return Math[method](y, x) * 180 / Math.PI; // } // function acceleration(axis, vRange, sensitivity) { // var voltage; // // convert raw reading to voltage // // (read * vRange / 1024) - (vRange / 2) // voltage = (axis * vRange / 1024) - (vRange / 2); // // 800mV sensitivity // return voltage / sensitivity; // } // // Filter for change events // // Pass in data by type // // e.g. accel.get("smooth") // function axisChange(data, threshold) { // var changed, axes; // axes = Object.keys(data); // changed = axes.map(function(axis) { // var extent = data[axis].length - 1; // return data[axis][extent] - data[axis][extent - 1]; // }); // return changed.some(function(element) { // return Math.abs(element) > threshold; // }); // } // // relatively terse updating function // // vs. this.data.thing.axis.whatever = value // // queue is the array on whatever object we want to update // function update(queue, value, extent) { // queue.push(value); // if (queue.length > extent) { // queue.shift(); // } // return queue; // } // // build data based on types and axes passed in // // initialize at zero // function dataStr(types, axes) { // var container = {}; // types.forEach(function(type) { // container[type] = {}; // axes.forEach(function(axis) { // container[type][axis] = [0]; // }); // }); // return container; // } // /* Expects an options argument e.g. // { // accel: this.data.accel, // smooth: this.data.smooth, // alpha: this.alpha, // extent: this.extent // } // */ // function exponential(smopts) { // var smooth, accel; // smooth = smopts.smooth; // accel = smopts.accel; // this.axes.forEach(function(axis) { // var acper, smper, currsm; // // Exponential smoothing // // see http://people.duke.edu/~rnau/411avg.htm // acper = accel[axis]; // smper = smooth[axis]; // // bootstrap for initial state // if (smper.length < smopts.extent) { // smooth[axis] = update(smper, acper[0], smopts.extent); // } else { // // convolves past smoothed/nonsmooth readings // currsm = smper[0] + smopts.alpha * (acper[0] - smper[0]); // // update current smoothed values // smooth[axis] = update(smper, currsm, smopts.extent); // } // }); // return smooth; // } // /** // * Accelerometer // * @constructor // * // * five.Accelerometer([ x, y[, z] ]); // * // * five.Accelerometer({ // * pins: [ x, y[, z] ] // * freq: ms // * }); // * // * // * @param {Object} opts [description] // * // */ // function Accelerometer(opts) { // if (!(this instanceof Accelerometer)) { // return new Accelerometer(opts); // } // var err = null; // // Initialize a Device instance on a Board // Board.Device.call( // this, opts = Board.Options(opts) // ); // this.mode = this.io.MODES.ANALOG; // // Accelerometer instance properties // this.voltage = opts.voltage || 3.3; // this.sensitivity = opts.sensitivity || 0.8; // this.freq = opts.freq || 50; // // Threshold needs to be tested // this.threshold = opts.threshold || 0.5; // // axis keys // this.axes = opts.axes || ["x", "y", "z"]; // // types (not really important unless you need them) // this.types = opts.types || ["smooth", "accel", "trend"]; // // how many past values to store // this.extent = opts.extent || 2; // // some smoothing methods require bootstrapping // this.initial = opts.initial || true; // // build data based on types and axes passed in // // initialize at zero // this.data = dataStr(this.types, this.axes); // // Blending property for the smoother. // // Smaller is less filtering // this.alpha = opts.alpha || 0.2; // // default smoother is an exponential smoother // this.smoother = opts.smoother || exponential; // // Setup read listeners for each pin, update instance // // properties as they are received. Special values are // // calculated during the throttled event emit phase // this.pins.forEach(function(pin, index) { // // Set the pin to input mode to ANALOG // this.io.pinMode(pin, this.mode); // this.io.analogRead(pin, function(data) { // var paxis, accel, sink, magnitude; // paxis = this.axes[index]; // accel = acceleration(data, this.voltage, this.sensitivity); // sink = this.data.accel[paxis]; // // The output we're interested in most of the time // this.data.accel[paxis] = update(sink, accel, this.extent); // // this will trigger a [[Get]] which will // // process the the acceleration data and // // keep the magnitude value current. // magnitude = this.magnitude; // }.bind(this)); // }, this); // // Throttle event emitter // setInterval(function() { // this.data.smooth = this.smoother({ // accel: this.data.accel, // smooth: this.data.smooth, // alpha: this.alpha, // extent: this.extent // }); // var data = { // smooth: this.data.smooth, // rough: this.data.accel // }; // // Check each axis for change above some threshold // if (axisChange(this.data.accel, this.threshold)) { // ["axischange", "change"].forEach(function(type) { // this.emit(type, err, data); // }, this); // } // this.emit("acceleration", err, data); // this.emit("data", err, data); // }.bind(this), this.freq); // /** // * raw x, y, z data // * @property raw // * @type Object // */ // /** // * smooth x, y, z data // * @property smooth // * @type Object // */ // /** // * accel calculated x, y, z data // * @property axis // * @type Object // */ // var old = { // x: 0, // y: /** // * [read-only] Calculated pitch value // * @property pitch // * @type Number // */ // pitch: { // get: function() { // var x, y, z, z2, accel; // accel = this.data.accel; // x = accel.x[1]; // y = accel.y[1]; // z = this.axes.indexOf("z") > -1 ? accel.z[1] : 0; // z2 = z ? z * z : 0; // return Math.abs( // Math.atan2( // x, Math.sqrt((y * y) + z2) // ) // ); // } // }, // /** // * [read-only] Calculated roll value // * @property roll // * @type Number // */ // roll: { // get: function() { // var x, y, z, z2, accel; // accel = this.data.accel; // x = accel.x[1]; // y = accel.y[1]; // z = this.axes.indexOf("z") > -1 ? accel.z[1] : 0; // z2 = z ? z * z : 0; // return Math.abs( // Math.atan2( // y, Math.sqrt((x * x) + z2) // ) // ); // } // },0, // z: 0 // }; // Object.defineProperties(this, { // x: { // get: function() { // return state.x.value; // } // }, // y: { // get: function() { // return state.y.value; // } // }, // z: { // get: function() { // return state.z.value; // } // }, // /** // * [read-only] Calculated magnitude value // * @property magnitude // * @type Number // */ // magnitude: { // get: function() { // var accel, x, y, z, z2, deltax, deltay, deltaz; // accel = this.data.accel; // x = accel.x[1]; // y = accel.y[1]; // z = this.axes.indexOf("z") > -1 ? accel.z[1] : 0; // deltax = x - old.x; // deltay = y - old.y; // deltaz = z - old.z; // old.x = x; // old.y = y; // old.z = z; // z2 = deltaz ? deltaz * deltaz : 0; // return Math.sqrt( // (deltax * deltax) + // (deltay * deltay) + // z2 // ); // } // } // }); // } // util.inherits(Accelerometer, events.EventEmitter); // Object.defineProperty(Accelerometer, "G", { // /** // * [read-only] One g is the acceleration due to gravity at the Earth's surface // * // * meters/s ^ 2 // * // * @property G // * @type Number // */ // value: 9.81 // }); // /** // * Fires once every N ms, equal to value of `freq`. Defaults to 500ms // * // * @event // * @name acceleration // * @memberOf Accelerometer // */ // /** // * Fires only when X, Y or Z has changed // * // * @event // * @name axischange // * @memberOf Accelerometer // */ // module.exports = Accelerometer; // // References // // // // http://www.instructables.com/id/Accelerometer-Gyro-Tutorial/ // // // // Images // // // // http://www.instructables.com/image/F7NMMPEG4PBOJPY/The-Accelerometer.jpg