UNPKG

johnny-five

Version:

Firmata based Arduino Programming Framework.

219 lines (174 loc) 4.73 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; } /** * 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 pinAxis, initial, iranges, last, err; initial = {}; iranges = {}; last = { x: 0, y: 0, z: 0 }; err = null; // Initialize a Device instance on a Board Board.Device.call( this, opts = Board.options( opts ) ); this.mode = this.firmata.MODES.ANALOG; this.pins = opts.pins; // Accelerometer instance properties this.voltage = opts.voltage || 3.3; this.sensitivity = opts.sensitivity || 0.8; this.freq = opts.freq || 500; this.raw = { x: null, y: null, z: null }; this.axis = { x: null, y: null, z: null }; // Pin to Axis mapping pinAxis = {}; // 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 ) { pinAxis[ pin ] = Object.keys( this.axis ).slice( index, index + 1 )[0]; // Set the pin to input mode to ANALOG this.firmata.pinMode( pin, this.mode ); this.firmata.analogRead( pin, function( data ) { var paxis = pinAxis[ pin ]; if ( !initial[ paxis ] ) { initial[ paxis ] = data; // Define a reasonable noise range iranges[ paxis ] = Board.range( data - 5, data + 5 ); } this.raw[ paxis ] = data; this.axis[ paxis ] = acceleration( data, this.voltage, this.sensitivity ); }.bind(this)); }, this ); // Throttle event emitter setInterval(function() { var changed; if ( last.x !== this.raw.x || last.y !== this.raw.y || last.z !== this.raw.z ) { // TODO: Improve _NOISE_ filtering if ( iranges.x.indexOf(this.raw.x) === -1 && iranges.y.indexOf(this.raw.y) === -1 && iranges.z.indexOf(this.raw.z) === -1 ) { // TODO: this is sloppy, needs to be cleaned up and // and refactored for API consistency this.emit( "axischange", err, { now: this.raw, previous: last }); } last.x = this.raw.x; last.y = this.raw.y; last.z = this.raw.z; } this.emit( "acceleration", err, new Date() ); }.bind(this), this.freq ); /** * raw x, y, z data * @property raw * @type Object */ /** * acceleration calculated x, y, z data * @property axis * @type Object */ Object.defineProperties( this, { /** * [read-only] Calculated pitch value * @property pitch * @type Number */ pitch: { get: function() { return Math.abs( Math.atan( this.axis.x, Math.sqrt( Math.pow(this.axis.y, 2) + Math.pow(this.axis.z, 2) ) ) ); } }, /** * [read-only] Calculated roll value * @property roll * @type Number */ roll: { get: function() { return Math.abs( Math.atan( this.axis.y, Math.sqrt( Math.pow(this.axis.x, 2) + Math.pow(this.axis.z, 2) ) ) ); } } }); } util.inherits( Accelerometer, events.EventEmitter ); Object.defineProperty( Accelerometer, "G", { /** * [read-only] One g is the acceleration due to gravity at the Earth's surface and is the standard gravity (symbol: gn), defined as 9.80665 metres per second squared, or equivalently 9.80665 newtons of force per kilogram of mass. * * 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.robotshop.com/gorobotics/wp-content/uploads/2012/05/euler-angles1.jpg // http://www.instructables.com/image/F7NMMPEG4PBOJPY/The-Accelerometer.jpg