├── .gitignore ├── .travis.yml ├── examples ├── led.js ├── led-pulse.js ├── built-in-leds.js ├── button.js ├── led-button.js ├── led-brightness.js ├── temperature-tmp36.js ├── servo.js ├── i2c-thermometer.js ├── digital-write-performance.js └── i2c-accelerometer.js ├── lib ├── pinmux.js ├── analog-input.js ├── board-info.js ├── beaglebone.js ├── pwm-output.js ├── bbb-pins.js ├── bbgw-pins.js └── pocket-beagle-pins.js ├── test ├── not-implemented.js └── beaglebone.js ├── package.json ├── Gruntfile.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "14" 4 | - "12" 5 | - "10" 6 | - "8" 7 | before_script: 8 | - npm install -g grunt-cli 9 | env: 10 | - CXX=g++-6 11 | addons: 12 | apt: 13 | sources: 14 | - ubuntu-toolchain-r-test 15 | packages: 16 | - g++-6 17 | -------------------------------------------------------------------------------- /examples/led.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var led = new five.Led('P8_7'); 12 | led.blink(500); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /examples/led-pulse.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var led = new five.Led('P8_13'); 12 | led.pulse(1000); 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /lib/pinmux.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | 5 | var OCP_PATH = '/sys/devices/platform/ocp/', 6 | FS_OPTIONS = {encoding: 'utf8'}; 7 | 8 | module.exports.state = function (pinId, state) { 9 | fs.writeFileSync( 10 | OCP_PATH + 'ocp:' + pinId + '_pinmux/state', 11 | state, 12 | FS_OPTIONS 13 | ); 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /examples/built-in-leds.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var led2 = new five.Led('USR2'), 12 | led3 = new five.Led('USR3'); 13 | 14 | led2.blink(500); 15 | led3.blink(500); 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /examples/button.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var button = new five.Button('P8_8'); 12 | 13 | button.on('down', function() { 14 | console.log('down'); 15 | }); 16 | 17 | button.on('up', function() { 18 | console.log('up'); 19 | }); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /examples/led-button.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var led = new five.Led('P8_7'); 12 | var button = new five.Button('P8_8'); 13 | 14 | button.on('down', function() { 15 | led.on(); 16 | }); 17 | 18 | button.on('up', function() { 19 | led.off(); 20 | }); 21 | }); 22 | 23 | -------------------------------------------------------------------------------- /examples/led-brightness.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var led = new five.Led('P8_13'); 12 | 13 | (function next() { 14 | led.brightness(10); 15 | setTimeout(function () { 16 | led.brightness(255); 17 | setTimeout(next, 1000); 18 | }, 1000); 19 | }()); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /examples/temperature-tmp36.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var temperature = new five.Thermometer({ 12 | controller: "TMP36", 13 | pin: "A0" 14 | }); 15 | 16 | temperature.on("change", function() { 17 | console.log(this.celsius + "°C", this.fahrenheit + "°F"); 18 | }); 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /examples/servo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var servo = new five.Servo({ 12 | pin: 'P9_14' 13 | }); 14 | 15 | (function next() { 16 | servo.to(45); 17 | setTimeout(function () { 18 | servo.to(135); 19 | setTimeout(next, 2000); 20 | }, 2000); 21 | }()); 22 | }); 23 | 24 | -------------------------------------------------------------------------------- /examples/i2c-thermometer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var thermometer = new five.Thermometer({ 12 | controller: "MCP9808" 13 | }); 14 | 15 | thermometer.on("change", function() { 16 | console.log("celsius: %d", this.C); 17 | console.log("fahrenheit: %d", this.F); 18 | console.log("kelvin: %d", this.K); 19 | }); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /examples/digital-write-performance.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var pin = board.io.normalize('P8_7'), 12 | writesPerSecond, 13 | time, 14 | i; 15 | 16 | this.pinMode(pin, five.Pin.OUTPUT); 17 | 18 | time = process.hrtime(); 19 | 20 | for (i = 1; i <= 250000; i += 1) { 21 | this.digitalWrite(pin, i & 1); 22 | } 23 | 24 | time = process.hrtime(time); 25 | writesPerSecond = Math.floor(i / (time[0] + time[1] / 1E9)); 26 | 27 | console.log(writesPerSecond + ' digitalWrite calls per second'); 28 | }); 29 | 30 | -------------------------------------------------------------------------------- /lib/analog-input.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | 5 | var ADC_PATH = '/sys/bus/iio/devices/iio:device0/'; 6 | 7 | function AnalogInput(analogChannel) { 8 | var rawValueFile = ADC_PATH + 'in_voltage' + analogChannel + '_raw'; 9 | 10 | if (!(this instanceof AnalogInput)) { 11 | return new AnalogInput(analogChannel); 12 | } 13 | 14 | this._rawValueFd = fs.openSync(rawValueFile, 'r'); 15 | this._rawValueBuffer = new Buffer(5); 16 | } 17 | 18 | AnalogInput.prototype.rawValue = function () { 19 | var len = fs.readSync( 20 | this._rawValueFd, 21 | this._rawValueBuffer, 22 | 0, 23 | this._rawValueBuffer.length, 24 | 0 25 | ); 26 | 27 | return parseInt(this._rawValueBuffer.toString('utf8', 0, len - 1), 10); 28 | }; 29 | 30 | module.exports = AnalogInput; 31 | 32 | -------------------------------------------------------------------------------- /lib/board-info.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'), 4 | bbbPins = require('./bbb-pins'), 5 | pocketBeaglePins = require('./pocket-beagle-pins'), 6 | bbgwPins = require('./bbgw-pins'); 7 | 8 | var MODEL_FILE_PATH = '/proc/device-tree/model', 9 | FS_OPTIONS = {encoding: 'utf8'}; 10 | 11 | module.exports.pins = function () { 12 | var model; 13 | 14 | try { 15 | model = fs.readFileSync(MODEL_FILE_PATH, FS_OPTIONS); 16 | } catch (ignore) { 17 | } 18 | 19 | if (model === 'TI AM335x BeagleBone Black\u0000') { 20 | return bbbPins; 21 | } else if (model === 'TI AM335x PocketBeagle\u0000') { 22 | return pocketBeaglePins; 23 | } else if (model === 'TI AM335x BeagleBone Green Wireless\u0000') { 24 | return bbgwPins; 25 | } else { 26 | return bbbPins; 27 | } 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /test/not-implemented.js: -------------------------------------------------------------------------------- 1 | var BeagleBone = require("../lib/beaglebone"); 2 | var sinon = require("sinon"); 3 | var title = "Not Implemented"; 4 | 5 | exports[title] = {}; 6 | 7 | [ 8 | "pulseIn", 9 | "pulseOut", 10 | "queryPinState", 11 | "_sendOneWireRequest", 12 | "_sendOneWireSearch", 13 | "sendOneWireWriteAndRead", 14 | "sendOneWireDelay", 15 | "sendOneWireDelay", 16 | "sendOneWireReset", 17 | "sendOneWireRead", 18 | "sendOneWireSearch", 19 | "sendOneWireAlarmsSearch", 20 | "sendOneWireConfig", 21 | "stepperConfig", 22 | "stepperStep" 23 | ].forEach(function(method) { 24 | exports[title][method] = function(test) { 25 | test.expect(2); 26 | test.ok(BeagleBone.prototype[method]); 27 | test.throws(function() { 28 | BeagleBone.prototype[method].call({}); 29 | }); 30 | test.done(); 31 | }; 32 | }); 33 | -------------------------------------------------------------------------------- /examples/i2c-accelerometer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var five = require('johnny-five'); 4 | var BeagleBone = require('..'); 5 | 6 | var board = new five.Board({ 7 | io: new BeagleBone() 8 | }); 9 | 10 | board.on('ready', function() { 11 | var accelerometer = new five.Accelerometer({ 12 | controller: "ADXL345" 13 | }); 14 | 15 | accelerometer.on("change", function() { 16 | console.log("accelerometer"); 17 | console.log(" x : ", this.x); 18 | console.log(" y : ", this.y); 19 | console.log(" z : ", this.z); 20 | console.log(" pitch : ", this.pitch); 21 | console.log(" roll : ", this.roll); 22 | console.log(" acceleration : ", this.acceleration); 23 | console.log(" inclination : ", this.inclination); 24 | console.log(" orientation : ", this.orientation); 25 | console.log("--------------------------------------"); 26 | }); 27 | }); 28 | 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beaglebone-io", 3 | "version": "4.1.0", 4 | "description": "BeagleBone Black IO Plugin for Johnny-Five", 5 | "main": "lib/beaglebone", 6 | "scripts": { 7 | "test": "grunt" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/julianduque/beaglebone-io" 12 | }, 13 | "engines": { 14 | "node": ">=8.0.0" 15 | }, 16 | "keywords": [ 17 | "firmata", 18 | "beaglebone", 19 | "johnny-five" 20 | ], 21 | "author": "Julian Duque ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/julianduque/beaglebone-io/issues" 25 | }, 26 | "homepage": "https://github.com/julianduque/beaglebone-io", 27 | "devDependencies": { 28 | "grunt": "^1.1.0", 29 | "grunt-contrib-jshint": "^2.1.0", 30 | "grunt-contrib-nodeunit": "^2.1.0", 31 | "grunt-contrib-watch": "^1.1.0", 32 | "grunt-jsbeautifier": "^0.2.13", 33 | "nodeunit": "^0.11.3", 34 | "rewire": "^5.0.0", 35 | "sinon": "^9.0.2" 36 | }, 37 | "dependencies": { 38 | "linux-io": "^1.1.0", 39 | "glob": "^7.1.6" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | var task = grunt.task; 4 | var file = grunt.file; 5 | var log = grunt.log; 6 | var verbose = grunt.verbose; 7 | var fail = grunt.fail; 8 | var option = grunt.option; 9 | var config = grunt.config; 10 | var template = grunt.template; 11 | var _ = grunt.util._; 12 | 13 | 14 | 15 | // Project configuration. 16 | grunt.initConfig({ 17 | pkg: grunt.file.readJSON("package.json"), 18 | nodeunit: { 19 | tests: [ 20 | "test/beaglebone.js" 21 | ] 22 | }, 23 | jshint: { 24 | options: { 25 | reporterOutput: "", 26 | latedef: false, 27 | curly: true, 28 | eqeqeq: true, 29 | immed: true, 30 | newcap: false, 31 | noarg: true, 32 | sub: true, 33 | undef: true, 34 | boss: true, 35 | eqnull: true, 36 | node: true, 37 | strict: false, 38 | esnext: true, 39 | globals: { 40 | rewire: true, 41 | exports: true, 42 | document: true, 43 | WeakMap: true, 44 | Map: true, 45 | window: true 46 | } 47 | }, 48 | files: { 49 | src: [ 50 | "Gruntfile.js", 51 | "lib/**/*.js", 52 | "test/**/*.js", 53 | "examples/**/*.js" 54 | ] 55 | } 56 | }, 57 | 58 | jsbeautifier: { 59 | files: ["lib/**/*.js", "examples/**/*.js", "test/**/*.js"], 60 | options: { 61 | js: { 62 | braceStyle: "collapse", 63 | breakChainedMethods: false, 64 | e4x: false, 65 | evalCode: false, 66 | indentChar: " ", 67 | indentLevel: 0, 68 | indentSize: 2, 69 | indentWithTabs: false, 70 | jslintHappy: false, 71 | keepArrayIndentation: false, 72 | keepFunctionIndentation: false, 73 | maxPreserveNewlines: 10, 74 | preserveNewlines: true, 75 | spaceBeforeConditional: true, 76 | spaceInParen: false, 77 | unescapeStrings: false, 78 | wrapLineLength: 0 79 | } 80 | } 81 | }, 82 | watch: { 83 | src: { 84 | files: [ 85 | "Gruntfile.js", 86 | "lib/**/!(johnny-five)*.js", 87 | "test/**/*.js", 88 | "examples/**/*.js" 89 | ], 90 | tasks: ["default"], 91 | options: { 92 | interrupt: true, 93 | }, 94 | } 95 | } 96 | }); 97 | 98 | grunt.loadNpmTasks("grunt-contrib-watch"); 99 | grunt.loadNpmTasks("grunt-contrib-nodeunit"); 100 | grunt.loadNpmTasks("grunt-contrib-jshint"); 101 | grunt.loadNpmTasks("grunt-jsbeautifier"); 102 | 103 | grunt.registerTask("default", ["jshint", "nodeunit"]); 104 | }; 105 | -------------------------------------------------------------------------------- /lib/beaglebone.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LinuxIO = require('linux-io'), 4 | util = require('util'), 5 | boardInfo = require('./board-info'), 6 | AnalogInput = require('./analog-input'), 7 | PwmOutput = require('./pwm-output'), 8 | pinmux = require('./pinmux'); 9 | 10 | var PWM_PERIOD = 1e9 / 2000, // 2000Hz 11 | SERVO_PERIOD = 1e9 / 50, // 50Hz 12 | PULSES_PER_MICROSEC = 1e9 / 1e6; 13 | 14 | function BeagleBone() { 15 | var pins = boardInfo.pins(); 16 | 17 | LinuxIO.call(this, { 18 | name: 'BeagleBone-IO', 19 | pins: pins, 20 | defaultI2cBus: 2, 21 | defaultLed: 'USR3', 22 | aref: 1.8, 23 | vref: 3.3 24 | }); 25 | 26 | setImmediate(function () { 27 | this.emit('connect'); 28 | this.emit('ready'); 29 | }.bind(this)); 30 | } 31 | util.inherits(BeagleBone, LinuxIO); 32 | 33 | BeagleBone.prototype._pinModeInput = function(pinData) { 34 | pinmux.state(pinData.custom.id, 'gpio'); 35 | BeagleBone.super_.prototype._pinModeInput.call(this, pinData); 36 | }; 37 | 38 | BeagleBone.prototype._pinModeOutput = function(pinData) { 39 | pinmux.state(pinData.custom.id, 'gpio'); 40 | BeagleBone.super_.prototype._pinModeOutput.call(this, pinData); 41 | }; 42 | 43 | BeagleBone.prototype._pinModeAnalog = function(pinData) { 44 | pinData.custom.analogInput = new AnalogInput(pinData.analogChannel); 45 | }; 46 | 47 | BeagleBone.prototype._pinModePwm = function(pinData) { 48 | pinData.custom.pwmOutput = new PwmOutput(pinData, PWM_PERIOD); 49 | }; 50 | 51 | BeagleBone.prototype._pinModeServo = function(pinData) { 52 | pinData.custom.pwmOutput = new PwmOutput(pinData, SERVO_PERIOD); 53 | 54 | pinData.servoConfig = { 55 | min: 600, // min must be >= 544 56 | max: 2400 57 | }; 58 | }; 59 | 60 | BeagleBone.prototype._analogRead = function(pinData, callback) { 61 | setImmediate(function () { 62 | try { 63 | // Raw value is 0 to 4095 but J5 expects 0 to 1023. 64 | callback(null, pinData.custom.analogInput.rawValue() >> 2); 65 | } catch (err) { 66 | callback(err); 67 | } 68 | }); 69 | }; 70 | 71 | BeagleBone.prototype._pwmWriteSync = function(pinData, value) { 72 | var dutyCycle = Math.round(value / 255 * PWM_PERIOD); 73 | 74 | pinData.custom.pwmOutput.pwmWrite(dutyCycle); 75 | }; 76 | 77 | BeagleBone.prototype._servoWriteSync = function(pinData, value) { 78 | var min = pinData.servoConfig.min, 79 | max = pinData.servoConfig.max, 80 | dutyCycle; 81 | 82 | // By the time flow of control reaches this point of execution one of the 83 | // following is true. 84 | // For degrees: 85 | // 0 <= value && value <= 180 86 | // For microseconds: 87 | // pinData.servoConfig.min <= value && value <= pinData.servoConfig.max 88 | 89 | // value < 544 implies degrees 90 | // value >= 544 implies microseconds 91 | // 544 is a magic number from the arduino servo library 92 | if (value < 544) { 93 | dutyCycle = (min + (value / 180) * (max - min)) * PULSES_PER_MICROSEC; 94 | } else { 95 | dutyCycle = value * PULSES_PER_MICROSEC; 96 | } 97 | 98 | pinData.custom.pwmOutput.pwmWrite(Math.round(dutyCycle)); 99 | }; 100 | 101 | module.exports = BeagleBone; 102 | 103 | -------------------------------------------------------------------------------- /lib/pwm-output.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'), 4 | glob = require('glob'), 5 | pinmux = require('./pinmux'); 6 | 7 | var OCP_PATH = '/sys/devices/platform/ocp/', 8 | FS_OPTIONS = {encoding: 'utf8'}; 9 | 10 | function pwmChipPattern(pinData) { 11 | return OCP_PATH + 12 | pinData.custom.pwm.module.subSystem.addr.toString(16) + 13 | '.epwmss/' + 14 | pinData.custom.pwm.module.addr.toString(16) + 15 | '.' + 16 | pinData.custom.pwm.module.suffix + 17 | '/pwm/pwmchip*'; 18 | } 19 | 20 | function waitForAccessPermission(paths) { 21 | // This is a bit of a hack but it works and it's not as bad as it initially 22 | // looks. When a pwm is exported with kernel v4.11+ udev will set the 23 | // permissions on the files used to control pwm to allow these files to be 24 | // accessed without root privileges. It takes udev a while to set the 25 | // permissions and we need to wait for it to complete its work to avoid 26 | // EACCES errors. To determine when udev has finished its work we 27 | // continuously try to access the appropriate files until they are 28 | // successfully accessed. We stop after 10000 tries. Under normal conditions 29 | // approximately 200 tries are needed to successfully access the first path 30 | // in the paths array. The remaining paths can typically be accessed 31 | // successfully on the first try. On kernels prior to v4.11 the code will 32 | // actually attempt to access the file 10000 times if Node.js was started 33 | // without root privileges. The 10000 attemps take approximately 2 seconds 34 | // to complete and in the end an EACCES is thrown. 35 | 36 | paths.forEach(function (path) { 37 | var tries = 0, 38 | fd; 39 | 40 | while (true) { 41 | try { 42 | tries += 1; 43 | fd = fs.openSync(path, 'r+'); 44 | fs.closeSync(fd); 45 | break; 46 | } catch (e) { 47 | if (tries === 10000) { 48 | throw e; 49 | } 50 | } 51 | } 52 | }); 53 | } 54 | 55 | function PwmOutput(pinData, period) { 56 | var matches, 57 | pwmChipPath, 58 | pwmChannelPattern, 59 | pwmChannelPath, 60 | channel; 61 | 62 | if (!(this instanceof PwmOutput)) { 63 | return new PwmOutput(pinData, period); 64 | } 65 | 66 | // The paths for PWM files vary from kernel to kernel. 67 | // On kernel v4.4 and v4.9 they will look something like this: 68 | // /sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/pwmchip*/pwm0/duty_cycle 69 | // On kernel v4.11+ they will look something like this: 70 | // /sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/pwmchip*/pwm-*:0/duty_cycle 71 | 72 | matches = glob.sync(pwmChipPattern(pinData)); 73 | if (matches.length !== 1) { 74 | throw new Error( 75 | 'Can\'t find unique directory macthing "' + pwmChipPattern(pinData) + '"' 76 | ); 77 | } 78 | 79 | pwmChipPath = matches[0]; 80 | channel = pinData.custom.pwm.channel; 81 | pwmChannelPattern = pwmChipPath + '/pwm*' + channel; 82 | 83 | matches = glob.sync(pwmChannelPattern); 84 | if (matches.length === 0) { 85 | // The pwm channel hasn't been exported yet, so export it. 86 | fs.writeFileSync(pwmChipPath + '/export', '' + channel, FS_OPTIONS); 87 | matches = glob.sync(pwmChannelPattern); 88 | } 89 | 90 | if (matches.length !== 1) { 91 | throw new Error( 92 | 'Can\'t find unique directory macthing "' + pwmChannelPattern + '"' 93 | ); 94 | } 95 | 96 | pwmChannelPath = matches[0]; 97 | 98 | // On kernel v4.11+ we wait for udev to set the permissions on the files 99 | // used to control pwm enabling the files to be accessed without root 100 | // privileges. 101 | waitForAccessPermission([ 102 | pwmChannelPath + '/period', 103 | pwmChannelPath + '/enable', 104 | pwmChannelPath + '/duty_cycle' 105 | ]); 106 | 107 | this.period = period; 108 | fs.writeFileSync(pwmChannelPath + '/period', '' + period, FS_OPTIONS); 109 | 110 | this.enableFd = fs.openSync(pwmChannelPath + '/enable', 'r+'); 111 | fs.writeSync(this.enableFd, '1', FS_OPTIONS); 112 | 113 | this.dutyCycleFd = fs.openSync(pwmChannelPath + '/duty_cycle', 'r+'); 114 | 115 | pinmux.state(pinData.custom.id, 'pwm'); 116 | } 117 | 118 | PwmOutput.prototype.pwmWrite = function (dutyCycle) { 119 | // There are glitches if an attempt is made to set the duty cycle to a value 120 | // less that 10. This is very visible when pulsing an LED. Setting the duty 121 | // cycle to a value less than 10 should make the LED very very dim, however, 122 | // it results in the LED becoming very bright for a fraction of a second. 123 | // Disabling PWM while setting the duty cycle appears to work around the 124 | // issue. 125 | 126 | if (dutyCycle < 10) { 127 | fs.writeSync(this.enableFd, '0', FS_OPTIONS); 128 | } 129 | 130 | fs.writeSync(this.dutyCycleFd, '' + dutyCycle, FS_OPTIONS); 131 | 132 | if (dutyCycle < 10) { 133 | fs.writeSync(this.enableFd, '1', FS_OPTIONS); 134 | } 135 | }; 136 | 137 | module.exports = PwmOutput; 138 | 139 | -------------------------------------------------------------------------------- /lib/bbb-pins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var pwmSubSystems = { 4 | subSystem0: { addr: 0x48300000 }, 5 | subSystem1: { addr: 0x48302000 }, 6 | subSystem2: { addr: 0x48304000 } 7 | }; 8 | 9 | var pwmModules = { 10 | ecap0: { subSystem: pwmSubSystems.subSystem0, addr: 0x48300100, suffix: 'ecap' }, 11 | ehrpwm0: { subSystem: pwmSubSystems.subSystem0, addr: 0x48300200, suffix: 'pwm' }, 12 | ehrpwm1: { subSystem: pwmSubSystems.subSystem1, addr: 0x48302200, suffix: 'pwm' }, 13 | ehrpwm2: { subSystem: pwmSubSystems.subSystem2, addr: 0x48304200, suffix: 'pwm' } 14 | }; 15 | 16 | var pwmPins = { 17 | p8_13: { module: pwmModules.ehrpwm2, channel: 1 }, 18 | p8_19: { module: pwmModules.ehrpwm2, channel: 0 }, 19 | p9_14: { module: pwmModules.ehrpwm1, channel: 0 }, 20 | p9_16: { module: pwmModules.ehrpwm1, channel: 1 }, 21 | p9_21: { module: pwmModules.ehrpwm0, channel: 1 }, 22 | p9_22: { module: pwmModules.ehrpwm0, channel: 0 }, 23 | p9_42: { module: pwmModules.ecap0, channel: 0 } 24 | }; 25 | 26 | module.exports = [ 27 | /* P8_1 - P8_2: DGND */ 28 | /* P8_3 - P8_6: EMCC */ 29 | { ids: ['P8_7', 'GPIO66'], gpioNo: 66, modes: [0, 1], custom: { id: 'P8_07' } }, 30 | { ids: ['P8_8', 'GPIO67'], gpioNo: 67, modes: [0, 1], custom: { id: 'P8_08' } }, 31 | { ids: ['P8_9', 'GPIO69'], gpioNo: 69, modes: [0, 1], custom: { id: 'P8_09' } }, 32 | { ids: ['P8_10', 'GPIO68'], gpioNo: 68, modes: [0, 1], custom: { id: 'P8_10' } }, 33 | { ids: ['P8_11', 'GPIO45'], gpioNo: 45, modes: [0, 1], custom: { id: 'P8_11' } }, 34 | { ids: ['P8_12', 'GPIO44'], gpioNo: 44, modes: [0, 1], custom: { id: 'P8_12' } }, 35 | { ids: ['P8_13', 'GPIO23'], gpioNo: 23, modes: [0, 1, 3, 4], custom: { id: 'P8_13', pwm: pwmPins.p8_13 } }, 36 | { ids: ['P8_14', 'GPIO26'], gpioNo: 26, modes: [0, 1], custom: { id: 'P8_14' } }, 37 | { ids: ['P8_15', 'GPIO47'], gpioNo: 47, modes: [0, 1], custom: { id: 'P8_15' } }, 38 | { ids: ['P8_16', 'GPIO46'], gpioNo: 46, modes: [0, 1], custom: { id: 'P8_16' } }, 39 | { ids: ['P8_17', 'GPIO27'], gpioNo: 27, modes: [0, 1], custom: { id: 'P8_17' } }, 40 | { ids: ['P8_18', 'GPIO65'], gpioNo: 65, modes: [0, 1], custom: { id: 'P8_18' } }, 41 | { ids: ['P8_19', 'GPIO22'], gpioNo: 22, modes: [0, 1, 3, 4], custom: { id: 'P8_19', pwm: pwmPins.p8_19 } }, 42 | /* P8_20 - P8_25: EMCC */ 43 | { ids: ['P8_26', 'GPIO61'], gpioNo: 61, modes: [0, 1], custom: { id: 'P8_26' } }, 44 | /* P8_27 - P8_46: HDMI */ 45 | 46 | /* P9_1 - P9_2: DGND */ 47 | /* P9_3 - P9_4: VDD_3V3 */ 48 | /* P9_5 - P9_6: VDD_5V */ 49 | /* P9_7 - P9_8: SYS_5V */ 50 | /* P9_9: PWR_BUT */ 51 | /* P9_10: SYS_RESETn */ 52 | { ids: ['P9_11', 'GPIO30'], gpioNo: 30, modes: [0, 1], custom: { id: 'P9_11' } }, 53 | { ids: ['P9_12', 'GPIO60'], gpioNo: 60, modes: [0, 1], custom: { id: 'P9_12' } }, 54 | { ids: ['P9_13', 'GPIO31'], gpioNo: 31, modes: [0, 1], custom: { id: 'P9_13' } }, 55 | { ids: ['P9_14', 'GPIO50'], gpioNo: 50, modes: [0, 1, 3, 4], custom: { id: 'P9_14', pwm: pwmPins.p9_14 } }, 56 | { ids: ['P9_15', 'GPIO48'], gpioNo: 48, modes: [0, 1], custom: { id: 'P9_15' } }, 57 | { ids: ['P9_16', 'GPIO51'], gpioNo: 51, modes: [0, 1, 3, 4], custom: { id: 'P9_16', pwm: pwmPins.p9_16 } }, 58 | { ids: ['P9_17', 'GPIO5'], gpioNo: 5, modes: [0, 1], custom: { id: 'P9_17' } }, 59 | { ids: ['P9_18', 'GPIO4'], gpioNo: 4, modes: [0, 1], custom: { id: 'P9_18' } }, 60 | /* P9_19: I2C2 SCL */ 61 | /* P9_20: I2C2 SDA */ 62 | { ids: ['P9_21', 'GPIO3'], gpioNo: 3, modes: [0, 1, 3, 4], custom: { id: 'P9_21', pwm: pwmPins.p9_21 } }, 63 | { ids: ['P9_22', 'GPIO2'], gpioNo: 2, modes: [0, 1, 3, 4], custom: { id: 'P9_22', pwm: pwmPins.p9_22 } }, 64 | { ids: ['P9_23', 'GPIO49'], gpioNo: 49, modes: [0, 1], custom: { id: 'P9_23' } }, 65 | { ids: ['P9_24', 'GPIO15'], gpioNo: 15, modes: [0, 1], custom: { id: 'P9_24' } }, 66 | /* P9_25: AUDIO */ 67 | { ids: ['P9_26', 'GPIO14'], gpioNo: 14, modes: [0, 1], custom: { id: 'P9_26' } }, 68 | { ids: ['P9_27', 'GPIO115'], gpioNo: 115, modes: [0, 1], custom: { id: 'P9_27' } }, 69 | /* P9_28 - P9_29: AUDIO */ 70 | { ids: ['P9_30', 'GPIO112'], gpioNo: 112, modes: [0, 1], custom: { id: 'P9_30' } }, 71 | /* P9_31: AUDIO */ 72 | /* P9_32: VDD_ADC */ 73 | { ids: ['P9_33', 'A4'], analogChannel: 4, modes: [2], custom: { id: 'P9_33' } }, 74 | /* P9_34 - GNDA_ADC */ 75 | { ids: ['P9_35', 'A6'], analogChannel: 6, modes: [2], custom: { id: 'P9_35' } }, 76 | { ids: ['P9_36', 'A5'], analogChannel: 5, modes: [2], custom: { id: 'P9_36' } }, 77 | { ids: ['P9_37', 'A2'], analogChannel: 2, modes: [2], custom: { id: 'P9_37' } }, 78 | { ids: ['P9_38', 'A3'], analogChannel: 3, modes: [2], custom: { id: 'P9_38' } }, 79 | { ids: ['P9_39', 'A0'], analogChannel: 0, modes: [2], custom: { id: 'P9_39' } }, 80 | { ids: ['P9_40', 'A1'], analogChannel: 1, modes: [2], custom: { id: 'P9_40' } }, 81 | { ids: ['P9_41', 'GPIO20'], gpioNo: 20, modes: [0, 1], custom: { id: 'P9_41' } }, 82 | { ids: ['P9_42', 'GPIO7'], gpioNo: 7, modes: [0, 1, 3, 4], custom: { id: 'P9_42', pwm: pwmPins.p9_42 } }, 83 | /* P9_43 - P9_46: DGND */ 84 | 85 | { ids: ['USR0'], ledPath: '/sys/class/leds/beaglebone:green:usr0', modes: [1] }, 86 | { ids: ['USR1'], ledPath: '/sys/class/leds/beaglebone:green:usr1', modes: [1] }, 87 | { ids: ['USR2'], ledPath: '/sys/class/leds/beaglebone:green:usr2', modes: [1] }, 88 | { ids: ['USR3'], ledPath: '/sys/class/leds/beaglebone:green:usr3', modes: [1] } 89 | ]; 90 | 91 | -------------------------------------------------------------------------------- /lib/bbgw-pins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var pwmSubSystems = { 4 | subSystem0: { addr: 0x48300000 }, 5 | subSystem1: { addr: 0x48302000 }, 6 | subSystem2: { addr: 0x48304000 } 7 | }; 8 | 9 | var pwmModules = { 10 | ecap0: { subSystem: pwmSubSystems.subSystem0, addr: 0x48300100, suffix: 'ecap' }, 11 | ehrpwm0: { subSystem: pwmSubSystems.subSystem0, addr: 0x48300200, suffix: 'pwm' }, 12 | ehrpwm1: { subSystem: pwmSubSystems.subSystem1, addr: 0x48302200, suffix: 'pwm' }, 13 | ehrpwm2: { subSystem: pwmSubSystems.subSystem2, addr: 0x48304200, suffix: 'pwm' } 14 | }; 15 | 16 | var pwmPins = { 17 | p8_13: { module: pwmModules.ehrpwm2, channel: 1 }, 18 | p8_19: { module: pwmModules.ehrpwm2, channel: 0 }, 19 | p9_14: { module: pwmModules.ehrpwm1, channel: 0 }, 20 | p9_16: { module: pwmModules.ehrpwm1, channel: 1 }, 21 | p9_21: { module: pwmModules.ehrpwm0, channel: 1 }, 22 | p9_22: { module: pwmModules.ehrpwm0, channel: 0 }, 23 | p9_42: { module: pwmModules.ecap0, channel: 0 } 24 | }; 25 | 26 | module.exports = [ 27 | /* P8_1 - P8_2: DGND */ 28 | /* P8_3 - P8_6: EMCC */ 29 | { ids: ['P8_7', 'GPIO66'], gpioNo: 66, modes: [0, 1], custom: { id: 'P8_07' } }, 30 | { ids: ['P8_8', 'GPIO67'], gpioNo: 67, modes: [0, 1], custom: { id: 'P8_08' } }, 31 | { ids: ['P8_9', 'GPIO69'], gpioNo: 69, modes: [0, 1], custom: { id: 'P8_09' } }, 32 | { ids: ['P8_10', 'GPIO68'], gpioNo: 68, modes: [0, 1], custom: { id: 'P8_10' } }, 33 | /* P8_11 - P8_12: Wireless */ 34 | { ids: ['P8_13', 'GPIO23'], gpioNo: 23, modes: [0, 1, 3, 4], custom: { id: 'P8_13', pwm: pwmPins.p8_13 } }, 35 | /* P8_14 - P8_18: Wireless */ 36 | { ids: ['P8_19', 'GPIO22'], gpioNo: 22, modes: [0, 1, 3, 4], custom: { id: 'P8_19', pwm: pwmPins.p8_19 } }, 37 | /* P8_20 - P8_25: EMCC */ 38 | /* P8_26: Wireless */ 39 | { ids: ['P8_27', 'GPIO86'], gpioNo: 86, modes: [0, 1], custom: { id: 'P8_27' } }, 40 | { ids: ['P8_28', 'GPIO88'], gpioNo: 88, modes: [0, 1], custom: { id: 'P8_28' } }, 41 | { ids: ['P8_29', 'GPIO87'], gpioNo: 87, modes: [0, 1], custom: { id: 'P8_29' } }, 42 | { ids: ['P8_30', 'GPIO89'], gpioNo: 89, modes: [0, 1], custom: { id: 'P8_30' } }, 43 | { ids: ['P8_31', 'GPIO10'], gpioNo: 10, modes: [0, 1], custom: { id: 'P8_31' } }, 44 | { ids: ['P8_32', 'GPIO11'], gpioNo: 11, modes: [0, 1], custom: { id: 'P8_32' } }, 45 | { ids: ['P8_33', 'GPIO9'], gpioNo: 9, modes: [0, 1], custom: { id: 'P8_33' } }, 46 | { ids: ['P8_34', 'GPIO81'], gpioNo: 81, modes: [0, 1], custom: { id: 'P8_34' } }, 47 | { ids: ['P8_35', 'GPIO8'], gpioNo: 8, modes: [0, 1], custom: { id: 'P8_35' } }, 48 | { ids: ['P8_36', 'GPIO80'], gpioNo: 80, modes: [0, 1], custom: { id: 'P8_36' } }, 49 | { ids: ['P8_37', 'GPIO78'], gpioNo: 78, modes: [0, 1], custom: { id: 'P8_37' } }, 50 | { ids: ['P8_38', 'GPIO79'], gpioNo: 79, modes: [0, 1], custom: { id: 'P8_38' } }, 51 | { ids: ['P8_39', 'GPIO76'], gpioNo: 76, modes: [0, 1], custom: { id: 'P8_39' } }, 52 | { ids: ['P8_40', 'GPIO77'], gpioNo: 77, modes: [0, 1], custom: { id: 'P8_40' } }, 53 | { ids: ['P8_41', 'GPIO74'], gpioNo: 74, modes: [0, 1], custom: { id: 'P8_41' } }, 54 | { ids: ['P8_42', 'GPIO75'], gpioNo: 75, modes: [0, 1], custom: { id: 'P8_42' } }, 55 | { ids: ['P8_43', 'GPIO72'], gpioNo: 72, modes: [0, 1], custom: { id: 'P8_43' } }, 56 | { ids: ['P8_44', 'GPIO73'], gpioNo: 73, modes: [0, 1], custom: { id: 'P8_44' } }, 57 | { ids: ['P8_45', 'GPIO70'], gpioNo: 70, modes: [0, 1], custom: { id: 'P8_45' } }, 58 | { ids: ['P8_46', 'GPIO71'], gpioNo: 71, modes: [0, 1], custom: { id: 'P8_46' } }, 59 | 60 | /* P9_1 - P9_2: DGND */ 61 | /* P9_3 - P9_4: VDD_3V3 */ 62 | /* P9_5 - P9_6: VDD_5V */ 63 | /* P9_7 - P9_8: SYS_5V */ 64 | /* P9_9: PWR_BUT */ 65 | /* P9_10: SYS_RESETn */ 66 | { ids: ['P9_11', 'GPIO30'], gpioNo: 30, modes: [0, 1], custom: { id: 'P9_11' } }, 67 | /* P9_12: Wireless */ 68 | { ids: ['P9_13', 'GPIO31'], gpioNo: 31, modes: [0, 1], custom: { id: 'P9_13' } }, 69 | { ids: ['P9_14', 'GPIO50'], gpioNo: 50, modes: [0, 1, 3, 4], custom: { id: 'P9_14', pwm: pwmPins.p9_14 } }, 70 | { ids: ['P9_15', 'GPIO48'], gpioNo: 48, modes: [0, 1], custom: { id: 'P9_15' } }, 71 | { ids: ['P9_16', 'GPIO51'], gpioNo: 51, modes: [0, 1, 3, 4], custom: { id: 'P9_16', pwm: pwmPins.p9_16 } }, 72 | { ids: ['P9_17', 'GPIO5'], gpioNo: 5, modes: [0, 1], custom: { id: 'P9_17' } }, 73 | { ids: ['P9_18', 'GPIO4'], gpioNo: 4, modes: [0, 1], custom: { id: 'P9_18' } }, 74 | { ids: ['P9_19', 'GPIO13'], gpioNo: 13, modes: [0, 1], custom: { id: 'P9_19' } },/* optionally for I2C2 SCL */ 75 | { ids: ['P9_20', 'GPIO12'], gpioNo: 12, modes: [0, 1], custom: { id: 'P9_20' } }, /* optionally for I2C2 SDA */ 76 | { ids: ['P9_21', 'GPIO3'], gpioNo: 3, modes: [0, 1, 3, 4], custom: { id: 'P9_21', pwm: pwmPins.p9_21 } }, 77 | { ids: ['P9_22', 'GPIO2'], gpioNo: 2, modes: [0, 1, 3, 4], custom: { id: 'P9_22', pwm: pwmPins.p9_22 } }, 78 | { ids: ['P9_23', 'GPIO49'], gpioNo: 49, modes: [0, 1], custom: { id: 'P9_23' } }, 79 | { ids: ['P9_24', 'GPIO15'], gpioNo: 15, modes: [0, 1], custom: { id: 'P9_24' } }, 80 | { ids: ['P9_25', 'GPIO117'], gpioNo: 117, modes: [0, 1], custom: { id: 'P9_25' } }, 81 | { ids: ['P9_26', 'GPIO14'], gpioNo: 14, modes: [0, 1], custom: { id: 'P9_26' } }, 82 | { ids: ['P9_27', 'GPIO115'], gpioNo: 115, modes: [0, 1], custom: { id: 'P9_27' } }, 83 | /* P9_28 - P9_31: Wireless */ 84 | /* P9_32: VDD_ADC */ 85 | { ids: ['P9_33', 'A4'], analogChannel: 4, modes: [2], custom: { id: 'P9_33' } }, 86 | /* P9_34 - GNDA_ADC */ 87 | { ids: ['P9_35', 'A6'], analogChannel: 6, modes: [2], custom: { id: 'P9_35' } }, 88 | { ids: ['P9_36', 'A5'], analogChannel: 5, modes: [2], custom: { id: 'P9_36' } }, 89 | { ids: ['P9_37', 'A2'], analogChannel: 2, modes: [2], custom: { id: 'P9_37' } }, 90 | { ids: ['P9_38', 'A3'], analogChannel: 3, modes: [2], custom: { id: 'P9_38' } }, 91 | { ids: ['P9_39', 'A0'], analogChannel: 0, modes: [2], custom: { id: 'P9_39' } }, 92 | { ids: ['P9_40', 'A1'], analogChannel: 1, modes: [2], custom: { id: 'P9_40' } }, 93 | { ids: ['P9_41', 'GPIO20'], gpioNo: 20, modes: [0, 1], custom: { id: 'P9_41' } }, 94 | { ids: ['P9_42', 'GPIO7'], gpioNo: 7, modes: [0, 1, 3, 4], custom: { id: 'P9_42', pwm: pwmPins.p9_42 } }, 95 | /* P9_43 - P9_46: DGND */ 96 | 97 | { ids: ['USR0'], ledPath: '/sys/class/leds/beaglebone:green:usr0', modes: [1] }, 98 | { ids: ['USR1'], ledPath: '/sys/class/leds/beaglebone:green:usr1', modes: [1] }, 99 | { ids: ['USR2'], ledPath: '/sys/class/leds/beaglebone:green:usr2', modes: [1] }, 100 | { ids: ['USR3'], ledPath: '/sys/class/leds/beaglebone:green:usr3', modes: [1] } 101 | ]; 102 | 103 | -------------------------------------------------------------------------------- /lib/pocket-beagle-pins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | * erhpwm0 channel 1 can be configured for output on P1_10 and/or P1_33. 5 | * If both P1_10 and P1_33 are defined to support PWM, Johnny-Five will 6 | * assume that it has two independent PWM channels but in reality there is 7 | * only one channel. To avoid issues here P1_33 is defined to support PWM 8 | * but P1_10 is not. The same applies to P1_8 and/or P1_36. 9 | */ 10 | 11 | var pwmSubSystems = { 12 | subSystem0: { addr: 0x48300000 }, 13 | subSystem1: { addr: 0x48302000 }, 14 | subSystem2: { addr: 0x48304000 } 15 | }; 16 | 17 | var pwmModules = { 18 | ehrpwm0: { subSystem: pwmSubSystems.subSystem0, addr: 0x48300200, suffix: 'pwm' }, 19 | ehrpwm1: { subSystem: pwmSubSystems.subSystem1, addr: 0x48302200, suffix: 'pwm' }, 20 | ehrpwm2: { subSystem: pwmSubSystems.subSystem2, addr: 0x48304200, suffix: 'pwm' } 21 | }; 22 | 23 | var pwmPins = { 24 | p1_33: { module: pwmModules.ehrpwm0, channel: 1 }, 25 | p1_36: { module: pwmModules.ehrpwm0, channel: 0 }, 26 | p2_1: { module: pwmModules.ehrpwm1, channel: 0 }, 27 | p2_3: { module: pwmModules.ehrpwm2, channel: 1 } 28 | }; 29 | 30 | module.exports = [ 31 | /* P1_1: VIN */ 32 | { ids: ['P1_2', 'GPIO87'], gpioNo: 87, modes: [0, 1], custom: { id: 'P1_02' } }, 33 | /* P1_3: USB1-V_EN */ 34 | { ids: ['P1_4', 'GPIO89'], gpioNo: 89, modes: [0, 1], custom: { id: 'P1_04' } }, 35 | /* P1_5: USB1-VBUS */ 36 | { ids: ['P1_6', 'GPIO5'], gpioNo: 5, modes: [0, 1], custom: { id: 'P1_06' } }, 37 | /* P1_7: USB1-VIN */ 38 | { ids: ['P1_8', 'GPIO2'], gpioNo: 2, modes: [0, 1], custom: { id: 'P1_08' } }, 39 | /* P1_9: USB1-DN */ 40 | { ids: ['P1_10', 'GPIO3'], gpioNo: 3, modes: [0, 1], custom: { id: 'P1_10' } }, 41 | /* P1_11: USB1-DP */ 42 | { ids: ['P1_12', 'GPIO4'], gpioNo: 4, modes: [0, 1], custom: { id: 'P1_12' } }, 43 | /* P1_13: USB1-ID */ 44 | /* P1_14: 3.3V */ 45 | /* P1_15: USB1-GND*/ 46 | /* P1_16: GND */ 47 | /* P1_17: AIN-VREF- */ 48 | /* P1_18: AIN-VREF+ */ 49 | { ids: ['P1_19', 'A0'], analogChannel: 0, modes: [2], custom: { id: 'P1_19' } }, 50 | { ids: ['P1_20', 'GPIO20'], gpioNo: 20, modes: [0, 1], custom: { id: 'P1_20' } }, 51 | { ids: ['P1_21', 'A1'], analogChannel: 1, modes: [2], custom: { id: 'P1_21' } }, 52 | /* P1_22: GND */ 53 | { ids: ['P1_23', 'A2'], analogChannel: 2, modes: [2], custom: { id: 'P1_23' } }, 54 | /* P1_24: VOUT-5V */ 55 | { ids: ['P1_25', 'A3'], analogChannel: 3, modes: [2], custom: { id: 'P1_25' } }, 56 | { ids: ['P1_26', 'GPIO12'], gpioNo: 12, modes: [0, 1], custom: { id: 'P1_26' } }, 57 | { ids: ['P1_27', 'A4'], analogChannel: 4, modes: [2], custom: { id: 'P1_27' } }, 58 | { ids: ['P1_28', 'GPIO13'], gpioNo: 13, modes: [0, 1], custom: { id: 'P1_28' } }, 59 | { ids: ['P1_29', 'GPIO117'], gpioNo: 117, modes: [0, 1], custom: { id: 'P1_29' } }, 60 | { ids: ['P1_30', 'GPIO43'], gpioNo: 43, modes: [0, 1], custom: { id: 'P1_30' } }, 61 | { ids: ['P1_31', 'GPIO114'], gpioNo: 114, modes: [0, 1], custom: { id: 'P1_31' } }, 62 | { ids: ['P1_32', 'GPIO42'], gpioNo: 42, modes: [0, 1], custom: { id: 'P1_32' } }, 63 | { ids: ['P1_33', 'GPIO111'], gpioNo: 111, modes: [0, 1, 3, 4], custom: { id: 'P1_33', pwm: pwmPins.p1_33 } }, 64 | { ids: ['P1_34', 'GPIO26'], gpioNo: 26, modes: [0, 1], custom: { id: 'P1_34' } }, 65 | { ids: ['P1_35', 'GPIO88'], gpioNo: 88, modes: [0, 1], custom: { id: 'P1_35' } }, 66 | { ids: ['P1_36', 'GPIO110'], gpioNo: 110, modes: [0, 1, 3, 4], custom: { id: 'P1_36', pwm: pwmPins.p1_36 } }, 67 | 68 | { ids: ['P2_1', 'GPIO50'], gpioNo: 50, modes: [0, 1, 3, 4], custom: { id: 'P2_01', pwm: pwmPins.p2_1 } }, 69 | { ids: ['P2_2', 'GPIO59'], gpioNo: 59, modes: [0, 1], custom: { id: 'P2_02' } }, 70 | { ids: ['P2_3', 'GPIO23'], gpioNo: 23, modes: [0, 1, 3, 4], custom: { id: 'P2_03', pwm: pwmPins.p2_3 } }, 71 | { ids: ['P2_4', 'GPIO58'], gpioNo: 58, modes: [0, 1], custom: { id: 'P2_04' } }, 72 | { ids: ['P2_5', 'GPIO30'], gpioNo: 30, modes: [0, 1], custom: { id: 'P2_05' } }, 73 | { ids: ['P2_6', 'GPIO57'], gpioNo: 57, modes: [0, 1], custom: { id: 'P2_06' } }, 74 | { ids: ['P2_7', 'GPIO31'], gpioNo: 31, modes: [0, 1], custom: { id: 'P2_07' } }, 75 | { ids: ['P2_8', 'GPIO60'], gpioNo: 60, modes: [0, 1], custom: { id: 'P2_08' } }, 76 | { ids: ['P2_9', 'GPIO15'], gpioNo: 15, modes: [0, 1], custom: { id: 'P2_09' } }, 77 | { ids: ['P2_10', 'GPIO52'], gpioNo: 52, modes: [0, 1], custom: { id: 'P2_10' } }, 78 | { ids: ['P2_11', 'GPIO14'], gpioNo: 14, modes: [0, 1], custom: { id: 'P2_11' } }, 79 | /* P2_12: PWR-BTN */ 80 | /* P2_13: VOUT */ 81 | /* P2_14: BAT-VIN */ 82 | /* P2_15: GND */ 83 | /* P2_16: BAT-TEMP */ 84 | { ids: ['P2_17', 'GPIO65'], gpioNo: 65, modes: [0, 1], custom: { id: 'P2_17' } }, 85 | { ids: ['P2_18', 'GPIO47'], gpioNo: 47, modes: [0, 1], custom: { id: 'P2_18' } }, 86 | { ids: ['P2_19', 'GPIO27'], gpioNo: 27, modes: [0, 1], custom: { id: 'P2_19' } }, 87 | { ids: ['P2_20', 'GPIO64'], gpioNo: 64, modes: [0, 1], custom: { id: 'P2_20' } }, 88 | /* P2_21: GND */ 89 | { ids: ['P2_22', 'GPIO46'], gpioNo: 46, modes: [0, 1], custom: { id: 'P2_22' } }, 90 | /* P2_23: 3.3V */ 91 | { ids: ['P2_24', 'GPIO44'], gpioNo: 44, modes: [0, 1], custom: { id: 'P2_24' } }, 92 | { ids: ['P2_25', 'GPIO41'], gpioNo: 41, modes: [0, 1], custom: { id: 'P2_25' } }, 93 | /* P2_26: NRST */ 94 | { ids: ['P2_27', 'GPIO40'], gpioNo: 40, modes: [0, 1], custom: { id: 'P2_27' } }, 95 | { ids: ['P2_28', 'GPIO116'], gpioNo: 116, modes: [0, 1], custom: { id: 'P2_28' } }, 96 | { ids: ['P2_29', 'GPIO7'], gpioNo: 7, modes: [0, 1], custom: { id: 'P2_29' } }, 97 | { ids: ['P2_30', 'GPIO113'], gpioNo: 113, modes: [0, 1], custom: { id: 'P2_30' } }, 98 | { ids: ['P2_31', 'GPIO19'], gpioNo: 19, modes: [0, 1], custom: { id: 'P2_31' } }, 99 | { ids: ['P2_32', 'GPIO112'], gpioNo: 112, modes: [0, 1], custom: { id: 'P2_32' } }, 100 | { ids: ['P2_33', 'GPIO45'], gpioNo: 45, modes: [0, 1], custom: { id: 'P2_33' } }, 101 | { ids: ['P2_34', 'GPIO115'], gpioNo: 115, modes: [0, 1], custom: { id: 'P2_34' } }, 102 | { ids: ['P2_35', 'GPIO86'], gpioNo: 86, modes: [0, 1], custom: { id: 'P2_35' } }, 103 | //{ ids: ['P2_36', 'A7'], analogChannel: 7, modes: [2], custom: { id: 'P2_36' } }, // Doesn't appear to work 104 | 105 | { ids: ['USR0'], ledPath: '/sys/class/leds/beaglebone:green:usr0', modes: [1] }, 106 | { ids: ['USR1'], ledPath: '/sys/class/leds/beaglebone:green:usr1', modes: [1] }, 107 | { ids: ['USR2'], ledPath: '/sys/class/leds/beaglebone:green:usr2', modes: [1] }, 108 | { ids: ['USR3'], ledPath: '/sys/class/leds/beaglebone:green:usr3', modes: [1] } 109 | ]; 110 | 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BeagleBone-IO 2 | [Johnny-Five](http://johnny-five.io) IO Plugin for the BeagleBone Black, 3 | BeagleBone Green Wireless and PocketBeagle. 4 | 5 | BeagleBone-IO supports Node.js versions 8, 10, 12 and 14. 6 | 7 | ## Contents 8 | 9 | * [News & Updates](#news--updates) 10 | * [Installation](#installation) 11 | * [Usage](#usage) 12 | * [Standalone Usage of BeagleBone-IO](#standalone-usage-of-beaglebone-io) 13 | * [Using BeagleBone-IO with Johnny-Five](#using-beaglebone-io-with-johnny-five) 14 | * [Johnny-Five Features Supported](#johnny-five-features-supported) 15 | * [Supported Pins on the BeagleBone Black](#supported-pins-on-the-beaglebone-black) 16 | * [Supported Pins on the PocketBeagle](#supported-pins-on-the-pocketbeagle) 17 | * [Supported Pins on the BeagleBone Green Wireless](#supported-pins-on-the-beaglebone-green-wireless) 18 | * [Working Without Sudo/Root Privileges](#working-without-sudoroot-privileges) 19 | * [License](#the-mit-license-mit) 20 | 21 | ## News & Updates 22 | 23 | ### May-2020: BeagleBone-IO v4.1.0 24 | 25 | * Support for Node.js 6 removed 26 | * Support for Node.js 14 added 27 | 28 | ## Installation 29 | 30 | ``` 31 | npm install beaglebone-io 32 | ``` 33 | 34 | For the best user experience with BeagleBone-IO the recommended Operating 35 | System is [Debian](http://beagleboard.org/latest-images). 36 | 37 | ## Usage 38 | 39 | #### Standalone Usage of BeagleBone-IO 40 | 41 | The BeagleBone Black, BeagleBone Green Wireless and PocketBeagle have four 42 | built-in blue user LEDs mounted on the board itself. The IDs for these LEDs 43 | are USR0, USR1, USR2 and USR3. All three boards also have an analog input with 44 | the ID A0. The program below turns on LED USR3 and logs the value of analog 45 | input A0 to the console each time it changes. It's possible to try this 46 | program without connecting any additional hardware to the board. 47 | 48 | ``` js 49 | var BeagleBone = require('beaglebone-io'); 50 | var board = new BeagleBone(); 51 | 52 | board.on('ready', function () { 53 | this.pinMode('USR3', this.MODES.OUTPUT); 54 | this.digitalWrite('USR3', this.HIGH); 55 | 56 | this.pinMode('A0', this.MODES.ANALOG); 57 | this.analogRead('A0', function (value) { 58 | console.log(value); 59 | }); 60 | }); 61 | ``` 62 | 63 | Calling `analogRead`, `digitalRead` or `i2cRead` initiates a new 64 | **continuous** data reading process for a pin not a single read. Further 65 | details can be seen at the Johnny-Five 66 | [IO Plugins Specification](https://github.com/rwaldron/io-plugins#reading). 67 | 68 | Analog inputs will be disabled by default on some systems and must be enabled 69 | before usage. To enable analog inputs remove or comment out the 70 | following line in `/boot/uEnv.txt` 71 | ``` 72 | disable_uboot_overlay_adc=1 73 | ``` 74 | Attempting to use analog inputs that are not enabled will typically result in 75 | ENOENT error messages: 76 | ``` 77 | Error: ENOENT: no such file or directory, open '/sys/bus/iio/devices/iio:device0/in_voltage0_raw' 78 | ``` 79 | 80 | #### Using BeagleBone-IO with Johnny-Five 81 | 82 | To use BeagleBone-IO with Johnny-Five the beaglebone-io and the johnny-five 83 | packages need to be installed. 84 | 85 | ``` 86 | npm install johnny-five beaglebone-io 87 | ``` 88 | 89 | The next example blinks the default LED with Johnny-Five. The built-in LED 90 | with ID USR3 is the default LED on the BeagleBone Black, BeagleBone Green 91 | Wireless and PocketBeagle. It's possible to try this program on any of these 92 | boards without connecting any additional hardware to the board. Note how 93 | the `Led` constructor is called without any arguments. If no arguments are 94 | passed to the `Led` constructor Johnny-Five assumes that the default LED 95 | should be used. 96 | 97 | ``` js 98 | var five = require('johnny-five'); 99 | var BeagleBone = require('beaglebone-io'); 100 | 101 | var board = new five.Board({ 102 | io: new BeagleBone() 103 | }); 104 | 105 | board.on('ready', function () { 106 | var led = new five.Led(); 107 | led.blink(); 108 | }); 109 | ``` 110 | 111 | Pulse an LED connected to P8_13 on a BeagleBone Black or BeagleBone Green 112 | Wireless with Johnny-Five. Note that pin ID P8_13 is specific to the 113 | BeagleBone Black and BeagleBone Green Wireless so this program can't be run on 114 | a PocketBeagle. 115 | 116 | ``` js 117 | var five = require('johnny-five'); 118 | var BeagleBone = require('beaglebone-io'); 119 | 120 | var board = new five.Board({ 121 | io: new BeagleBone() 122 | }); 123 | 124 | board.on('ready', function() { 125 | var led = new five.Led('P8_13'); 126 | led.pulse(1000); 127 | }); 128 | ``` 129 | 130 | Pulse an LED connected to P2_1 on a PocketBeagle with Johnny-Five. Note that 131 | pin ID P2_1 is specific to the PocketBeagle so this program can't be run on a 132 | BeagleBone Black or BeagleBone Green Wireless. 133 | 134 | ``` js 135 | var five = require('johnny-five'); 136 | var BeagleBone = require('beaglebone-io'); 137 | 138 | var board = new five.Board({ 139 | io: new BeagleBone() 140 | }); 141 | 142 | board.on('ready', function() { 143 | var led = new five.Led('P2_1'); 144 | led.pulse(1000); 145 | }); 146 | ``` 147 | 148 | ## Johnny-Five Features Supported 149 | 150 | Feature | Support 151 | :--- | :--- 152 | Analog Read | yes 153 | Digital Read | yes 154 | Digital Write | yes 155 | PWM | yes 156 | Servo | yes 157 | I2C | yes 158 | One Wire | no 159 | Stepper | no 160 | Serial/UART | no 161 | DAC | no 162 | Ping | no 163 | 164 | ## Supported Pins on the BeagleBone Black 165 | 166 | | Pin ID | Supported Modes | Comments | 167 | |:----|:-----|:----| 168 | | P8_7 or GPIO66 | INPUT, OUTPUT | | 169 | | P8_8 or GPIO67 | INPUT, OUTPUT | | 170 | | P8_9 or GPIO69 | INPUT, OUTPUT | | 171 | | P8_10 or GPIO68 | INPUT, OUTPUT | | 172 | | P8_11 or GPIO45 | INPUT, OUTPUT | | 173 | | P8_12 or GPIO44 | INPUT, OUTPUT | | 174 | | P8_13 or GPIO23 | INPUT, OUTPUT, SERVO, PWM | | 175 | | P8_14 or GPIO26 | INPUT, OUTPUT | | 176 | | P8_15 or GPIO47 | INPUT, OUTPUT | | 177 | | P8_16 or GPIO46 | INPUT, OUTPUT | | 178 | | P8_17 or GPIO27 | INPUT, OUTPUT | | 179 | | P8_18 or GPIO65 | INPUT, OUTPUT | | 180 | | P8_19 or GPIO22 | INPUT, OUTPUT, SERVO, PWM | | 181 | | P8_26 or GPIO61 | INPUT, OUTPUT | | 182 | | | | 183 | | P9_11 or GPIO30 | INPUT, OUTPUT | | 184 | | P9_12 or GPIO60 | INPUT, OUTPUT | | 185 | | P9_13 or GPIO31 | INPUT, OUTPUT | | 186 | | P9_14 or GPIO50 | INPUT, OUTPUT, SERVO, PWM | | 187 | | P9_15 or GPIO48 | INPUT, OUTPUT | | 188 | | P9_16 or GPIO51 | INPUT, OUTPUT, SERVO, PWM | | 189 | | P9_17 or GPIO5 | INPUT, OUTPUT | | 190 | | P9_18 or GPIO4 | INPUT, OUTPUT | | 191 | | P9_19 | I2C2 SCL | Reserved for I2C | 192 | | P9_20 | I2C2 SDA | Reserved for I2C | 193 | | P9_21 or GPIO3 | INPUT, OUTPUT, SERVO, PWM | | 194 | | P9_22 or GPIO2 | INPUT, OUTPUT, SERVO, PWM | | 195 | | P9_23 or GPIO49 | INPUT, OUTPUT | | 196 | | P9_24 or GPIO15 | INPUT, OUTPUT | | 197 | | P9_26 or GPIO14 | INPUT, OUTPUT | | 198 | | P9_27 or GPIO115 | INPUT, OUTPUT | | 199 | | P9_30 or GPIO112 | INPUT, OUTPUT | | 200 | | P9_33 or A4 | ANALOG | Don't input more than 1.8V | 201 | | P9_35 or A6 | ANALOG | Don't input more than 1.8V | 202 | | P9_36 or A5 | ANALOG | Don't input more than 1.8V | 203 | | P9_37 or A2 | ANALOG | Don't input more than 1.8V | 204 | | P9_38 or A3 | ANALOG | Don't input more than 1.8V | 205 | | P9_39 or A0 | ANALOG | Don't input more than 1.8V | 206 | | P9_40 or A1 | ANALOG | Don't input more than 1.8V | 207 | | P9_41 or GPIO20 | INPUT, OUTPUT | | 208 | | P9_42 or GPIO7 | INPUT, OUTPUT, SERVO, PWM | | 209 | | | | 210 | | USR0 | OUTPUT | Built-in user LED 0 | 211 | | USR1 | OUTPUT | Built-in user LED 1 | 212 | | USR2 | OUTPUT | Built-in user LED 2 | 213 | | USR3 | OUTPUT | Built-in user LED 3 / Default LED | 214 | 215 | Below are two images of the BeagleBone Black expansion headers from the 216 | [BeagleBone 101](http://beagleboard.org/Support/bone101/). 217 | 218 | The header pins that are colored orange in the first image are reserved for 219 | the on-board eMMC storage and HDMI and can't be used with BeagleBone-IO. 220 | Although P9_25 isn't colored orange it's also reserved and can't be used by 221 | BeagleBone-IO. 222 | 223 | 224 | 225 | The following image of the expansion headers shows the GPIO numbers for the 226 | header pins. 227 | 228 | 229 | 230 | ## Supported Pins on the PocketBeagle 231 | 232 | | Pin ID | Supported Modes | Comments | 233 | |:----|:-----|:----| 234 | | P1_2 or GPIO87 | INPUT, OUTPUT | | 235 | | P1_4 or GPIO89 | INPUT, OUTPUT | | 236 | | P1_6 or GPIO5 | INPUT, OUTPUT | | 237 | | P1_8 or GPIO2 | INPUT, OUTPUT | | 238 | | P1_10 or GPIO3 | INPUT, OUTPUT | | 239 | | P1_12 or GPIO4 | INPUT, OUTPUT | | 240 | | P1_19 or A0 | ANALOG | Don't input more than 1.8V | 241 | | P1_20 or GPIO20 | INPUT, OUTPUT | | 242 | | P1_21 or A1 | ANALOG | Don't input more than 1.8V | 243 | | P1_23 or A2 | ANALOG | Don't input more than 1.8V | 244 | | P1_25 or A3 | ANALOG | Don't input more than 1.8V | 245 | | P1_26 or GPIO12 | INPUT, OUTPUT | Optionally for I2C data | 246 | | P1_27 or A4 | ANALOG | Don't input more than 1.8V | 247 | | P1_28 or GPIO13 | INPUT, OUTPUT | Optionally for I2C clock | 248 | | P1_29 or GPIO117 | INPUT, OUTPUT | | 249 | | P1_30 or GPIO43 | INPUT, OUTPUT | | 250 | | P1_31 or GPIO114 | INPUT, OUTPUT | | 251 | | P1_32 or GPIO42 | INPUT, OUTPUT | | 252 | | P1_33 or GPIO111 | INPUT, OUTPUT, SERVO, PWM | | 253 | | P1_34 or GPIO26 | INPUT, OUTPUT | | 254 | | P1_35 or GPIO88 | INPUT, OUTPUT | | 255 | | P1_36 or GPIO110 | INPUT, OUTPUT, SERVO, PWM | | 256 | | | | 257 | | P2_1 or GPIO50 | INPUT, OUTPUT, SERVO, PWM | | 258 | | P2_2 or GPIO59 | INPUT, OUTPUT | | 259 | | P2_3 or GPIO23 | INPUT, OUTPUT, SERVO, PWM | | 260 | | P2_4 or GPIO58 | INPUT, OUTPUT | | 261 | | P2_5 or GPIO30 | INPUT, OUTPUT | | 262 | | P2_6 or GPIO57 | INPUT, OUTPUT | | 263 | | P2_7 or GPIO31 | INPUT, OUTPUT | | 264 | | P2_8 or GPIO60 | INPUT, OUTPUT | | 265 | | P2_9 or GPIO15 | INPUT, OUTPUT | | 266 | | P2_10 or GPIO52 | INPUT, OUTPUT | | 267 | | P2_11 or GPIO14 | INPUT, OUTPUT | | 268 | | P2_17 or GPIO65 | INPUT, OUTPUT | | 269 | | P2_18 or GPIO47 | INPUT, OUTPUT | | 270 | | P2_19 or GPIO27 | INPUT, OUTPUT | | 271 | | P2_20 or GPIO64 | INPUT, OUTPUT | | 272 | | P2_22 or GPIO46 | INPUT, OUTPUT | | 273 | | P2_24 or GPIO44 | INPUT, OUTPUT | | 274 | | P2_25 or GPIO41 | INPUT, OUTPUT | | 275 | | P2_27 or GPIO40 | INPUT, OUTPUT | | 276 | | P2_28 or GPIO116 | INPUT, OUTPUT | | 277 | | P2_29 or GPIO7 | INPUT, OUTPUT | | 278 | | P2_30 or GPIO113 | INPUT, OUTPUT | | 279 | | P2_31 or GPIO19 | INPUT, OUTPUT | | 280 | | P2_32 or GPIO112 | INPUT, OUTPUT | | 281 | | P2_33 or GPIO45 | INPUT, OUTPUT | | 282 | | P2_34 or GPIO115 | INPUT, OUTPUT | | 283 | | P2_35 or GPIO86 | INPUT, OUTPUT | | 284 | | | | 285 | | USR0 | OUTPUT | Built-in user LED 0 | 286 | | USR1 | OUTPUT | Built-in user LED 1 | 287 | | USR2 | OUTPUT | Built-in user LED 2 | 288 | | USR3 | OUTPUT | Built-in user LED 3 / Default LED | 289 | 290 | Below is an image of the PocketBeagle expansion headers from the 291 | [PocketBeagle repository on GitHub](https://github.com/beagleboard/pocketbeagle). 292 | 293 | Note that although the image indicates that GPIO109 is available on P1_3 this 294 | isn't the case as P1_3 is reserved for USB1-V_EN. In addition, the analog mode 295 | capabilities of P1_2, P2_35 and P2_36 are not supported by BeagleBone-IO. 296 | 297 | 298 | 299 | ## Supported Pins on the BeagleBone Green Wireless 300 | 301 | | Pin ID | Supported Modes | Comments | 302 | |:----|:-----|:----| 303 | | P8_7 or GPIO66 | INPUT, OUTPUT | | 304 | | P8_8 or GPIO67 | INPUT, OUTPUT | | 305 | | P8_9 or GPIO69 | INPUT, OUTPUT | | 306 | | P8_10 or GPIO68 | INPUT, OUTPUT | | 307 | | P8_13 or GPIO23 | INPUT, OUTPUT, SERVO, PWM | | 308 | | P8_19 or GPIO22 | INPUT, OUTPUT, SERVO, PWM | | 309 | | P8_27 or GPIO86 | INPUT, OUTPUT | | 310 | | P8_28 or GPIO88 | INPUT, OUTPUT | | 311 | | P8_29 or GPIO87 | INPUT, OUTPUT | | 312 | | P8_30 or GPIO89 | INPUT, OUTPUT | | 313 | | P8_31 or GPIO10 | INPUT, OUTPUT | | 314 | | P8_32 or GPIO11 | INPUT, OUTPUT | | 315 | | P8_33 or GPIO9 | INPUT, OUTPUT | | 316 | | P8_34 or GPIO81 | INPUT, OUTPUT | | 317 | | P8_35 or GPIO8 | INPUT, OUTPUT | | 318 | | P8_36 or GPIO80 | INPUT, OUTPUT | | 319 | | P8_37 or GPIO78 | INPUT, OUTPUT | | 320 | | P8_38 or GPIO79 | INPUT, OUTPUT | | 321 | | P8_39 or GPIO76 | INPUT, OUTPUT | | 322 | | P8_40 or GPIO77 | INPUT, OUTPUT | | 323 | | P8_41 or GPIO74 | INPUT, OUTPUT | | 324 | | P8_42 or GPIO75 | INPUT, OUTPUT | | 325 | | P8_43 or GPIO72 | INPUT, OUTPUT | | 326 | | P8_44 or GPIO73 | INPUT, OUTPUT | | 327 | | P8_45 or GPIO70 | INPUT, OUTPUT | | 328 | | P8_46 or GPIO71 | INPUT, OUTPUT | | 329 | | | | 330 | | P9_11 or GPIO30 | INPUT, OUTPUT | | 331 | | P9_13 or GPIO31 | INPUT, OUTPUT | | 332 | | P9_14 or GPIO50 | INPUT, OUTPUT, SERVO, PWM | | 333 | | P9_15 or GPIO48 | INPUT, OUTPUT | | 334 | | P9_16 or GPIO51 | INPUT, OUTPUT, SERVO, PWM | | 335 | | P9_17 or GPIO5 | INPUT, OUTPUT | | 336 | | P9_18 or GPIO4 | INPUT, OUTPUT | | 337 | | P9_19 or GPIO13 | INPUT, OUTPUT | Optionally for I2C clock | 338 | | P9_20 or GPIO12 | INPUT, OUTPUT | Optionally for I2C data | 339 | | P9_21 or GPIO3 | INPUT, OUTPUT, SERVO, PWM | | 340 | | P9_22 or GPIO2 | INPUT, OUTPUT, SERVO, PWM | | 341 | | P9_23 or GPIO49 | INPUT, OUTPUT | | 342 | | P9_24 or GPIO15 | INPUT, OUTPUT | | 343 | | P9_25 or GPIO117 | INPUT, OUTPUT | | 344 | | P9_26 or GPIO14 | INPUT, OUTPUT | | 345 | | P9_27 or GPIO115 | INPUT, OUTPUT | | 346 | | P9_33 or A4 | ANALOG | Don't input more than 1.8V | 347 | | P9_35 or A6 | ANALOG | Don't input more than 1.8V | 348 | | P9_36 or A5 | ANALOG | Don't input more than 1.8V | 349 | | P9_37 or A2 | ANALOG | Don't input more than 1.8V | 350 | | P9_38 or A3 | ANALOG | Don't input more than 1.8V | 351 | | P9_39 or A0 | ANALOG | Don't input more than 1.8V | 352 | | P9_40 or A1 | ANALOG | Don't input more than 1.8V | 353 | | P9_41 or GPIO20 | INPUT, OUTPUT | | 354 | | P9_42 or GPIO7 | INPUT, OUTPUT, SERVO, PWM | | 355 | | | | 356 | | USR0 | OUTPUT | Built-in user LED 0 | 357 | | USR1 | OUTPUT | Built-in user LED 1 | 358 | | USR2 | OUTPUT | Built-in user LED 2 | 359 | | USR3 | OUTPUT | Built-in user LED 3 / Default LED | 360 | 361 | ## Working Without Sudo/Root Privileges 362 | 363 | BeagleBone-IO v3.0.0 can be used without sudo/root privileges if an 364 | appropriate Debian image and v4.11 or higher of the Linux Kernel has been 365 | installed. 366 | 367 | The latest recommended Debian image for the BeagleBone that is available today 368 | at [BeagleBoard.org](https://beagleboard.org/latest-images) is 369 | `Debian 9.2 2017-10-10 4GB SD IoT`. This image comes with v4.4.91 of the Linux 370 | Kernel. The command `uname -r` can be used to determine which version of the 371 | Linux Kernel is installed. 372 | 373 | Assuming that `Debian 9.2 2017-10-10 4GB SD IoT` has has already been 374 | installed the following commands can be used to update to Linux Kernel v4.14. 375 | 376 | ``` 377 | sudo apt-get update 378 | cd /opt/scripts/tools 379 | git pull 380 | sudo ./update_kernel.sh --lts-4_14 381 | ``` 382 | 383 | After Linux Kernel v4.14 has been installed it should be possible to use 384 | BeagleBone-IO without sudo/root privileges. 385 | 386 | ## The MIT License (MIT) 387 | 388 | Copyright (c) Julian Duque, Alan Yorinks, Brian Cooke 2017 389 | 390 | Permission is hereby granted, free of charge, to any person obtaining a copy 391 | of this software and associated documentation files (the "Software"), to deal 392 | in the Software without restriction, including without limitation the rights 393 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 394 | copies of the Software, and to permit persons to whom the Software is 395 | furnished to do so, subject to the following conditions: 396 | 397 | The above copyright notice and this permission notice shall be included in 398 | all copies or substantial portions of the Software. 399 | 400 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 401 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 402 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 403 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 404 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 405 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 406 | THE SOFTWARE. 407 | -------------------------------------------------------------------------------- /test/beaglebone.js: -------------------------------------------------------------------------------- 1 | var rewire = require("rewire"); 2 | var BeagleBone = rewire("../lib/beaglebone"); 3 | var Emitter = require("events").EventEmitter; 4 | var sinon = require("sinon"); 5 | 6 | function restore(target) { 7 | for (var prop in target) { 8 | if (typeof target[prop].restore === "function") { 9 | target[prop].restore(); 10 | } 11 | } 12 | } 13 | 14 | exports["BeagleBone"] = { 15 | setUp: function(done) { 16 | this.clock = sinon.useFakeTimers(); 17 | this.beaglebone = new BeagleBone(); 18 | this.proto = {}; 19 | 20 | this.proto.functions = [{ 21 | name: "analogRead" 22 | }, { 23 | name: "analogWrite" 24 | }, { 25 | name: "pwmWrite" 26 | }, { 27 | name: "digitalRead" 28 | }, { 29 | name: "digitalWrite" 30 | }, { 31 | name: "servoWrite" 32 | }, { 33 | name: "i2cConfig" 34 | }, { 35 | name: "i2cWrite" 36 | }, { 37 | name: "i2cWriteReg" 38 | }, { 39 | name: "i2cRead" 40 | }, { 41 | name: "i2cReadOnce" 42 | }, { 43 | name: "sendI2CWriteRequest" 44 | }, { 45 | name: "sendI2CConfig" 46 | }, { 47 | name: "sendI2CReadRequest" 48 | }]; 49 | 50 | this.proto.objects = [{ 51 | name: "MODES" 52 | }]; 53 | 54 | this.proto.numbers = [{ 55 | name: "HIGH" 56 | }, { 57 | name: "LOW" 58 | }]; 59 | 60 | this.instance = [{ 61 | name: "pins" 62 | }, { 63 | name: "analogPins" 64 | }]; 65 | 66 | done(); 67 | }, 68 | 69 | tearDown: function(done) { 70 | restore(this); 71 | 72 | done(); 73 | }, 74 | 75 | shape: function(test) { 76 | test.expect( 77 | this.proto.functions.length + 78 | this.proto.objects.length + 79 | this.proto.numbers.length + 80 | this.instance.length 81 | ); 82 | 83 | this.proto.functions.forEach(function(method) { 84 | test.equal(typeof this.beaglebone[method.name], "function"); 85 | }, this); 86 | 87 | this.proto.objects.forEach(function(method) { 88 | test.equal(typeof this.beaglebone[method.name], "object"); 89 | }, this); 90 | 91 | this.proto.numbers.forEach(function(method) { 92 | test.equal(typeof this.beaglebone[method.name], "number"); 93 | }, this); 94 | 95 | this.instance.forEach(function(property) { 96 | test.notEqual(typeof this.beaglebone[property.name], "undefined"); 97 | }, this); 98 | 99 | test.done(); 100 | }, 101 | 102 | readonly: function(test) { 103 | test.expect(11); 104 | 105 | test.equal(this.beaglebone.HIGH, 1); 106 | 107 | this.beaglebone.HIGH = 42; 108 | test.equal(this.beaglebone.HIGH, 1); 109 | 110 | test.equal(this.beaglebone.LOW, 0); 111 | 112 | this.beaglebone.LOW = 42; 113 | test.equal(this.beaglebone.LOW, 0); 114 | 115 | test.equal(this.beaglebone.MODES.INPUT, 0); 116 | test.equal(this.beaglebone.MODES.OUTPUT, 1); 117 | test.equal(this.beaglebone.MODES.ANALOG, 2); 118 | test.equal(this.beaglebone.MODES.PWM, 3); 119 | test.equal(this.beaglebone.MODES.SERVO, 4); 120 | 121 | this.beaglebone.MODES.INPUT = 42; 122 | test.equal(this.beaglebone.MODES.INPUT, 0); 123 | 124 | this.beaglebone.MODES = 42; 125 | test.equal(typeof this.beaglebone.MODES, "object"); 126 | 127 | test.done(); 128 | }, 129 | 130 | emitter: function(test) { 131 | test.expect(1); 132 | 133 | test.ok(this.beaglebone instanceof Emitter); 134 | 135 | test.done(); 136 | }, 137 | 138 | connected: function(test) { 139 | test.expect(1); 140 | 141 | this.beaglebone.on("connect", function() { 142 | test.ok(true); 143 | 144 | test.done(); 145 | }); 146 | }, 147 | 148 | ready: function(test) { 149 | test.expect(1); 150 | 151 | this.beaglebone.on("ready", function() { 152 | test.ok(true); 153 | 154 | test.done(); 155 | }); 156 | }, 157 | 158 | normalize: function(test) { 159 | test.expect(4); 160 | 161 | test.equal(2, this.beaglebone.normalize(2)); 162 | test.equal(2, this.beaglebone.normalize("P8_9")); 163 | test.equal(41, this.beaglebone.normalize("USR3")); 164 | test.equal(34, this.beaglebone.normalize("A0")); 165 | 166 | test.done(); 167 | } 168 | }; 169 | 170 | exports["BeagleBone.prototype.analogRead"] = { 171 | setUp: function(done) { 172 | this.clock = sinon.useFakeTimers(); 173 | this.beaglebone = new BeagleBone(); 174 | 175 | done(); 176 | }, 177 | 178 | tearDown: function(done) { 179 | restore(this); 180 | this.beaglebone._analogReports = []; 181 | 182 | done(); 183 | }, 184 | 185 | correctMode: function(test) { 186 | test.expect(1); 187 | 188 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog"); 189 | 190 | this.beaglebone.pinMode("A0", 2); 191 | 192 | test.equal(this.beaglebone.pins[this.beaglebone.normalize("A0")].mode, 2); 193 | 194 | test.done(); 195 | }, 196 | 197 | analogPin: function(test) { 198 | test.expect(2); 199 | 200 | var value = 1023; 201 | 202 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog"); 203 | this.analogRead = sinon.stub(this.beaglebone, "_analogRead") 204 | .callsFake(function(pinData, cb) { 205 | cb(null, value); 206 | }); 207 | 208 | this.beaglebone.pinMode("A0", 2); 209 | 210 | test.equal(this.beaglebone.pins[this.beaglebone.normalize("A0")].mode, 2); 211 | 212 | var handler = function(data) { 213 | test.equal(data, value); 214 | 215 | test.done(); 216 | }; 217 | 218 | this.beaglebone.analogRead("A0", handler); 219 | 220 | this.clock.tick(5); 221 | }, 222 | 223 | channel: function(test) { 224 | test.expect(1); 225 | 226 | var channel = 0; 227 | 228 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog") 229 | .callsFake(function(pinData) { 230 | test.equal(pinData.analogChannel, channel); 231 | 232 | test.done(); 233 | }); 234 | 235 | this.beaglebone.pinMode("A0", 2); 236 | }, 237 | 238 | handler: function(test) { 239 | test.expect(1); 240 | 241 | var value = 511; 242 | 243 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog"); 244 | this.analogRead = sinon.stub(this.beaglebone, "_analogRead") 245 | .callsFake(function(pinData, cb) { 246 | cb(null, value); 247 | }); 248 | 249 | this.beaglebone.pinMode("A0", 2); 250 | 251 | var handler = function(data) { 252 | test.equal(data, value); 253 | 254 | test.done(); 255 | }; 256 | 257 | this.beaglebone.analogRead("A0", handler); 258 | 259 | this.clock.tick(5); 260 | }, 261 | 262 | event: function(test) { 263 | test.expect(1); 264 | 265 | var value = 255; 266 | var event = "analog-read-" + this.beaglebone.normalize("A0"); 267 | 268 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog"); 269 | this.analogRead = sinon.stub(this.beaglebone, "_analogRead") 270 | .callsFake(function(pinData, cb) { 271 | cb(null, value); 272 | }); 273 | 274 | this.beaglebone.once(event, function(data) { 275 | test.equal(data, value); 276 | test.done(); 277 | }); 278 | 279 | this.beaglebone.pinMode("A0", 2); 280 | this.beaglebone.analogRead("A0", function(data) {}); 281 | 282 | this.clock.tick(5); 283 | } 284 | }; 285 | 286 | exports["BeagleBone.prototype.digitalRead"] = { 287 | setUp: function(done) { 288 | this.clock = sinon.useFakeTimers(); 289 | this.beaglebone = new BeagleBone(); 290 | 291 | done(); 292 | }, 293 | 294 | tearDown: function(done) { 295 | restore(this); 296 | this.beaglebone._digitalReports = []; 297 | 298 | done(); 299 | }, 300 | 301 | correctMode: function(test) { 302 | test.expect(1); 303 | 304 | this.pinModeInput = sinon.stub(this.beaglebone, "_pinModeInput"); 305 | 306 | this.beaglebone.pinMode("P8_13", 0); 307 | 308 | test.equal( 309 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 310 | 0 311 | ); 312 | 313 | test.done(); 314 | }, 315 | 316 | port: function(test) { 317 | test.expect(1); 318 | 319 | this.pinModeInput = sinon.stub(this.beaglebone, "_pinModeInput"); 320 | this.digitalReadSync = sinon.stub(this.beaglebone, "_digitalReadSync") 321 | .callsFake(function(pinData) { 322 | test.equal("P8_13", pinData.custom.id); 323 | test.done(); 324 | }); 325 | 326 | this.beaglebone.pinMode("P8_13", 0); 327 | this.beaglebone.digitalRead("P8_13", function() {}); 328 | 329 | this.clock.tick(5); 330 | }, 331 | 332 | handler: function(test) { 333 | test.expect(1); 334 | 335 | var value = 1; 336 | 337 | this.pinModeInput = sinon.stub(this.beaglebone, "_pinModeInput"); 338 | this.digitalReadSync = sinon.stub(this.beaglebone, "_digitalReadSync") 339 | .callsFake(function(pinData) { 340 | return value; 341 | }); 342 | 343 | var handler = function(data) { 344 | test.equal(data, value); 345 | test.done(); 346 | }; 347 | 348 | this.beaglebone.pinMode("P8_13", 0); 349 | this.beaglebone.digitalRead("P8_13", handler); 350 | 351 | this.clock.tick(5); 352 | }, 353 | 354 | event: function(test) { 355 | test.expect(1); 356 | 357 | var value = 1; 358 | var pinNo = this.beaglebone.normalize("P8_13"); 359 | var event = "digital-read-" + pinNo; 360 | 361 | this.pinModeInput = sinon.stub(this.beaglebone, "_pinModeInput"); 362 | this.digitalReadSync = sinon.stub(this.beaglebone, "_digitalReadSync") 363 | .callsFake(function(pinData) { 364 | return value; 365 | }); 366 | 367 | this.beaglebone.once(event, function(data) { 368 | test.equal(data, value); 369 | test.done(); 370 | }); 371 | 372 | var handler = function(data) {}; 373 | this.beaglebone.pinMode("P8_13", 0); 374 | this.beaglebone.digitalRead("P8_13", handler); 375 | 376 | this.clock.tick(5); 377 | } 378 | }; 379 | 380 | exports["BeagleBone.prototype.analogWrite"] = { 381 | setUp: function(done) { 382 | this.clock = sinon.useFakeTimers(); 383 | this.beaglebone = new BeagleBone(); 384 | 385 | done(); 386 | }, 387 | 388 | tearDown: function(done) { 389 | restore(this); 390 | 391 | done(); 392 | }, 393 | 394 | mode: function(test) { 395 | test.expect(1); 396 | 397 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 398 | 399 | this.beaglebone.pinMode("P8_13", 3); 400 | 401 | test.equal( 402 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 403 | 3 404 | ); 405 | 406 | test.done(); 407 | }, 408 | 409 | write: function(test) { 410 | test.expect(3); 411 | 412 | var value = 255; 413 | 414 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 415 | this.pwmWriteSync = sinon.stub(this.beaglebone, "_pwmWriteSync"); 416 | 417 | this.beaglebone.pinMode("P8_13", 3); 418 | this.beaglebone.analogWrite("P8_13", value); 419 | test.ok(this.pwmWriteSync.calledOnce); 420 | test.equal(this.pwmWriteSync.firstCall.args[0].custom.id, "P8_13"); 421 | test.equal(this.pwmWriteSync.firstCall.args[1], value); 422 | 423 | test.done(); 424 | }, 425 | 426 | stored: function(test) { 427 | test.expect(1); 428 | 429 | var value = 255; 430 | 431 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 432 | this.pwmWriteSync = sinon.stub(this.beaglebone, "_pwmWriteSync"); 433 | 434 | this.beaglebone.pinMode("P8_13", 3); 435 | this.beaglebone.analogWrite("P8_13", value); 436 | 437 | test.equal( 438 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].value, 439 | value 440 | ); 441 | 442 | test.done(); 443 | } 444 | }; 445 | 446 | exports["BeagleBone.prototype.pwmWrite"] = { 447 | setUp: function(done) { 448 | this.clock = sinon.useFakeTimers(); 449 | this.beaglebone = new BeagleBone(); 450 | 451 | done(); 452 | }, 453 | 454 | tearDown: function(done) { 455 | restore(this); 456 | 457 | done(); 458 | }, 459 | 460 | mode: function(test) { 461 | test.expect(1); 462 | 463 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 464 | 465 | this.beaglebone.pinMode("P9_42", 3); 466 | 467 | test.equal( 468 | this.beaglebone.pins[this.beaglebone.normalize("P9_42")].mode, 469 | 3 470 | ); 471 | 472 | test.done(); 473 | }, 474 | 475 | write: function(test) { 476 | test.expect(3); 477 | 478 | var value = 255; 479 | 480 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 481 | this.pwmWriteSync = sinon.stub(this.beaglebone, "_pwmWriteSync"); 482 | 483 | this.beaglebone.pinMode("P9_42", 3); 484 | this.beaglebone.pwmWrite("P9_42", value); 485 | test.ok(this.pwmWriteSync.calledOnce); 486 | test.equal(this.pwmWriteSync.firstCall.args[0].custom.id, "P9_42"); 487 | test.equal(this.pwmWriteSync.firstCall.args[1], value); 488 | 489 | test.done(); 490 | }, 491 | 492 | stored: function(test) { 493 | test.expect(1); 494 | 495 | var value = 127; 496 | 497 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 498 | this.pwmWriteSync = sinon.stub(this.beaglebone, "_pwmWriteSync"); 499 | 500 | this.beaglebone.pinMode("P9_42", 3); 501 | this.beaglebone.pwmWrite("P9_42", value); 502 | 503 | test.equal( 504 | this.beaglebone.pins[this.beaglebone.normalize("P9_42")].value, 505 | value 506 | ); 507 | 508 | test.done(); 509 | } 510 | }; 511 | 512 | exports["BeagleBone.prototype.digitalWrite"] = { 513 | setUp: function(done) { 514 | this.clock = sinon.useFakeTimers(); 515 | this.beaglebone = new BeagleBone(); 516 | 517 | done(); 518 | }, 519 | 520 | tearDown: function(done) { 521 | restore(this); 522 | 523 | done(); 524 | }, 525 | 526 | mode: function(test) { 527 | test.expect(1); 528 | 529 | this.pinModeOutput = sinon.stub(this.beaglebone, "_pinModeOutput"); 530 | 531 | this.beaglebone.pinMode("P8_13", 1); 532 | 533 | test.equal( 534 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 535 | 1 536 | ); 537 | 538 | test.done(); 539 | }, 540 | 541 | write: function(test) { 542 | test.expect(3); 543 | 544 | var value = 1; 545 | 546 | this.pinModeOutput = sinon.stub(this.beaglebone, "_pinModeOutput"); 547 | this.digitalWriteSync = sinon.stub(this.beaglebone, "_digitalWriteSync"); 548 | 549 | this.beaglebone.pinMode("P8_13", 1); 550 | this.beaglebone.digitalWrite("P8_13", value); 551 | test.ok(this.digitalWriteSync.calledOnce); 552 | test.equal(this.digitalWriteSync.firstCall.args[0].custom.id, "P8_13"); 553 | test.equal(this.digitalWriteSync.firstCall.args[1], value); 554 | 555 | test.done(); 556 | }, 557 | 558 | stored: function(test) { 559 | test.expect(1); 560 | 561 | var value = 1; 562 | 563 | this.pinModeOutput = sinon.stub(this.beaglebone, "_pinModeOutput"); 564 | this.digitalWriteSync = sinon.stub(this.beaglebone, "_digitalWriteSync"); 565 | 566 | this.beaglebone.pinMode("P8_13", 1); 567 | this.beaglebone.digitalWrite("P8_13", value); 568 | 569 | test.equal( 570 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].value, 571 | value 572 | ); 573 | 574 | test.done(); 575 | } 576 | }; 577 | 578 | exports["BeagleBone.prototype.servoWrite"] = { 579 | setUp: function(done) { 580 | this.clock = sinon.useFakeTimers(); 581 | this.beaglebone = new BeagleBone(); 582 | 583 | done(); 584 | }, 585 | 586 | tearDown: function(done) { 587 | restore(this); 588 | 589 | done(); 590 | }, 591 | 592 | mode: function(test) { 593 | test.expect(1); 594 | 595 | this.pinModeServo = sinon.stub(this.beaglebone, "_pinModeServo"); 596 | 597 | this.beaglebone.pinMode("P8_13", 4); 598 | 599 | test.equal( 600 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 601 | 4 602 | ); 603 | 604 | test.done(); 605 | }, 606 | 607 | write: function(test) { 608 | test.expect(3); 609 | 610 | var value = 90; 611 | 612 | this.pinModeServo = sinon.stub(this.beaglebone, "_pinModeServo"); 613 | this.servoWriteSync = sinon.stub(this.beaglebone, "_servoWriteSync"); 614 | 615 | this.beaglebone.pinMode("P8_13", 4); 616 | this.beaglebone.servoWrite("P8_13", value); 617 | test.ok(this.servoWriteSync.calledOnce); 618 | test.equal(this.servoWriteSync.firstCall.args[0].custom.id, "P8_13"); 619 | test.equal(this.servoWriteSync.firstCall.args[1], value); 620 | 621 | test.done(); 622 | }, 623 | 624 | stored: function(test) { 625 | test.expect(1); 626 | 627 | var value = 180; 628 | 629 | this.pinModeServo = sinon.stub(this.beaglebone, "_pinModeServo"); 630 | this.servoWriteSync = sinon.stub(this.beaglebone, "_servoWriteSync"); 631 | 632 | this.beaglebone.pinMode("P8_13", 4); 633 | this.beaglebone.servoWrite("P8_13", value); 634 | 635 | test.equal( 636 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].value, 637 | value 638 | ); 639 | 640 | test.done(); 641 | } 642 | }; 643 | 644 | exports["BeagleBone.prototype.pinMode (analog)"] = { 645 | setUp: function(done) { 646 | this.clock = sinon.useFakeTimers(); 647 | this.beaglebone = new BeagleBone(); 648 | 649 | done(); 650 | }, 651 | 652 | tearDown: function(done) { 653 | restore(this); 654 | 655 | done(); 656 | }, 657 | 658 | analogOut: function(test) { 659 | test.expect(1); 660 | 661 | this.pinModePwm = sinon.stub(this.beaglebone, "_pinModePwm"); 662 | 663 | this.beaglebone.pinMode("P9_42", 3); 664 | test.equal( 665 | this.beaglebone.pins[this.beaglebone.normalize("P9_42")].mode, 666 | 3 667 | ); 668 | 669 | test.done(); 670 | }, 671 | 672 | analogIn: function(test) { 673 | test.expect(1); 674 | 675 | this.pinModeAnalog = sinon.stub(this.beaglebone, "_pinModeAnalog"); 676 | 677 | this.beaglebone.pinMode("A0", 2); 678 | test.equal(this.beaglebone.pins[this.beaglebone.normalize("A0")].mode, 2); 679 | 680 | test.done(); 681 | } 682 | }; 683 | 684 | exports["BeagleBone.prototype.pinMode (digital)"] = { 685 | setUp: function(done) { 686 | this.clock = sinon.useFakeTimers(); 687 | this.beaglebone = new BeagleBone(); 688 | 689 | done(); 690 | }, 691 | 692 | tearDown: function(done) { 693 | restore(this); 694 | 695 | done(); 696 | }, 697 | 698 | digitalOut: function(test) { 699 | test.expect(1); 700 | 701 | this.pinModeOutput = sinon.stub(this.beaglebone, "_pinModeOutput"); 702 | 703 | this.beaglebone.pinMode("P8_13", 1); 704 | test.equal( 705 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 706 | 1 707 | ); 708 | 709 | test.done(); 710 | }, 711 | 712 | digitalIn: function(test) { 713 | test.expect(1); 714 | 715 | this.pinModeInput = sinon.stub(this.beaglebone, "_pinModeInput"); 716 | 717 | this.beaglebone.pinMode("P8_13", 0); 718 | test.equal( 719 | this.beaglebone.pins[this.beaglebone.normalize("P8_13")].mode, 720 | 0 721 | ); 722 | 723 | test.done(); 724 | } 725 | }; 726 | 727 | --------------------------------------------------------------------------------