From dd65b5c0f42e05ed88daa71c6ff7e2b853aea5b6 Mon Sep 17 00:00:00 2001 From: Leonhardt Wille Date: Thu, 1 Mar 2012 22:01:29 +0100 Subject: [PATCH 01/55] emit "error" event instead of throwing --- lib/board.js | 65 +++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/lib/board.js b/lib/board.js index dc29c87..b6391b9 100644 --- a/lib/board.js +++ b/lib/board.js @@ -16,38 +16,41 @@ var Board = function (options) { var self = this; this.detect(function (err, serial) { - if (err) throw err; - self.serial = serial; - self.emit('connected'); - - self.log('info', 'binding serial events'); - self.serial.on('data', function(data){ - self.log('receive', data.toString().red); - self.emit('data', data); - }); - - setTimeout(function(){ - self.log('info', 'board ready'); - self.sendClearingBytes(); - - if (self.debug) { - self.log('info', 'sending debug mode toggle on to board'); - self.write('99' + self.normalizePin(0) + self.normalizeVal(1)); - process.on('SIGINT', function(){ - self.log('info', 'sending debug mode toggle off to board'); - self.write('99' + self.normalizePin(0) + self.normalizeVal(0)); - delete self.serial; - setTimeout(function(){ - process.exit(); - }, 100); - }); - } - - if (self.writeBuffer.length > 0) { - self.processWriteBuffer(); + if (err) { + self.emit('error', err); + }else{ + self.serial = serial; + self.emit('connected'); + + self.log('info', 'binding serial events'); + self.serial.on('data', function(data){ + self.log('receive', data.toString().red); + self.emit('data', data); + }); + + setTimeout(function(){ + self.log('info', 'board ready'); + self.sendClearingBytes(); + + if (self.debug) { + self.log('info', 'sending debug mode toggle on to board'); + self.write('99' + self.normalizePin(0) + self.normalizeVal(1)); + process.on('SIGINT', function(){ + self.log('info', 'sending debug mode toggle off to board'); + self.write('99' + self.normalizePin(0) + self.normalizeVal(0)); + delete self.serial; + setTimeout(function(){ + process.exit(); + }, 100); + }); + } + + if (self.writeBuffer.length > 0) { + self.processWriteBuffer(); + } + + self.emit('ready'); } - - self.emit('ready'); }, 500); }); } From 8bde1613c562d96a67ec83404f816ed86544c22b Mon Sep 17 00:00:00 2001 From: Leonhardt Wille Date: Thu, 1 Mar 2012 22:05:16 +0100 Subject: [PATCH 02/55] fixed scope error --- lib/board.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/board.js b/lib/board.js index b6391b9..4c0e6f2 100644 --- a/lib/board.js +++ b/lib/board.js @@ -49,9 +49,9 @@ var Board = function (options) { self.processWriteBuffer(); } - self.emit('ready'); - } - }, 500); + self.emit('ready'); + }, 500); + } }); } From e251cf97c116661efe40dfbd35af08171ba48937 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Tue, 13 Mar 2012 18:32:42 -0400 Subject: [PATCH 03/55] Adds LDR module for reading analog light dependent resistors Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/ldr.js | 16 ++++++++++++++++ lib/ldr.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 examples/ldr.js create mode 100644 lib/ldr.js diff --git a/examples/ldr.js b/examples/ldr.js new file mode 100644 index 0000000..f1810eb --- /dev/null +++ b/examples/ldr.js @@ -0,0 +1,16 @@ +var arduino = require('../'); + +var board = new arduino.Board({ + // debug: true +}); + +var ldr = new arduino.LDR({ + board: board, + pin: 'A0' +}); + +ldr.on('data', function( value ) { + + // |value| is reading of the light dependent resistor + console.log( value ); +}); diff --git a/lib/ldr.js b/lib/ldr.js new file mode 100644 index 0000000..959ef45 --- /dev/null +++ b/lib/ldr.js @@ -0,0 +1,31 @@ +var events = require('events'), + util = require('util'); + +/* + * Main LDR constructor + * Process options + * Tell the board to set it up + */ +var LDR = function (options) { + if (!options || !options.board) throw new Error('Must supply required options to LDR'); + this.board = options.board; + this.pin = options.pin || 'A0'; + this.board.pinMode(this.pin, 'in'); + + var self = this; + setInterval(function () { + self.board.analogRead(self.pin); + }, 50); + + this.board.on('data', function (m) { + m = m.slice(0, -1).split('::'); + self.emit('data', m[1]); + }); +} + +/* + * EventEmitter, I choose you! + */ +util.inherits(LDR, events.EventEmitter); + +module.exports = LDR; From 3d679dedfc989da913a7cfc680fb9e422c2bc3b9 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 14 Mar 2012 10:26:39 -0400 Subject: [PATCH 04/55] Typo correction (Sutton=>Servo). Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/servo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/servo.js b/lib/servo.js index c609411..56d0705 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -4,7 +4,7 @@ * Tell the board to set it up */ var Servo = function (options) { - if (!options || !options.board) throw new Error('Must supply required options to Sutton'); + if (!options || !options.board) throw new Error('Must supply required options to Servo'); this.board = options.board; this.pin = this.board.normalizePin(options.pin || 9); var self = this; From 988d222803a4712ec559cbb5d4c03de89f423916 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 14 Mar 2012 12:21:36 -0400 Subject: [PATCH 05/55] strncpy correct source and num chars to copy. Fixes #17 Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/servo.js | 4 +--- src/du.ino | 16 ++++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/servo.js b/examples/servo.js index 517ae78..e6af92b 100644 --- a/examples/servo.js +++ b/examples/servo.js @@ -8,6 +8,4 @@ var servo = new arduino.Servo({ board: board }); -board.on('ready', function(){ - servo.sweep(); -}); +servo.sweep(); diff --git a/src/du.ino b/src/du.ino index ba26406..59db18d 100644 --- a/src/du.ino +++ b/src/du.ino @@ -27,21 +27,21 @@ void loop() { */ void process() { index = 0; - + strncpy(cmd, messageBuffer, 2); cmd[2] = '\0'; strncpy(pin, messageBuffer + 2, 2); pin[2] = '\0'; - strncpy(val, messageBuffer + 4, 3); + strncpy(val, messageBuffer + 4, 2); val[3] = '\0'; - strncpy(aux, messageBuffer + 7, 3); + strncpy(aux, messageBuffer + 6, 3); aux[3] = '\0'; - + if (debug) { Serial.println(messageBuffer); } int cmdid = atoi(cmd); - + switch(cmdid) { case 0: sm(pin,val); break; case 1: dw(pin,val); break; @@ -122,7 +122,7 @@ void ar(char *pin, char *val) { char m[8]; sprintf(m, "%s::%03d", pin, rval); Serial.println(m); -} +} void aw(char *pin, char *val) { if(debug) Serial.println("aw"); @@ -155,7 +155,7 @@ int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error } return ret; } - + /* * Handle Servo commands @@ -176,4 +176,4 @@ void handleServo(char *pin, char *val, char *aux) { Serial.println(atoi(aux)); servo.write(atoi(aux)); } -} \ No newline at end of file +} From d44af879297ced3412c6891bf3684e75bfd5c53c Mon Sep 17 00:00:00 2001 From: Leonhardt Wille Date: Wed, 14 Mar 2012 23:13:05 +0100 Subject: [PATCH 06/55] optional error event, throws if no handler is registered --- lib/board.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/board.js b/lib/board.js index 4c0e6f2..e5a2242 100644 --- a/lib/board.js +++ b/lib/board.js @@ -17,7 +17,10 @@ var Board = function (options) { var self = this; this.detect(function (err, serial) { if (err) { - self.emit('error', err); + if(self.listeners('error').length) + self.emit('error', err); + else + throw new Error(err); }else{ self.serial = serial; self.emit('connected'); From fa2c91a523320e44a4e42bbd168cfdbd23c28825 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Thu, 15 Mar 2012 21:24:04 -0400 Subject: [PATCH 07/55] Bolster servo controls Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/servo.js | 15 +++++++++++++-- src/du.ino | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/examples/servo.js b/examples/servo.js index e6af92b..5dc3110 100644 --- a/examples/servo.js +++ b/examples/servo.js @@ -5,7 +5,18 @@ var board = new arduino.Board({ }); var servo = new arduino.Servo({ - board: board + board: board, + pin: "A0" }); -servo.sweep(); + + +servo.on("attached", function() { + + this.read(function(current) { + this.write(180); + }); + + + +}); diff --git a/src/du.ino b/src/du.ino index 59db18d..fd93243 100644 --- a/src/du.ino +++ b/src/du.ino @@ -1,5 +1,6 @@ #include + char messageBuffer[12]; int index = 0; char cmd[3]; @@ -7,6 +8,7 @@ char pin[3]; char val[4]; char aux[4]; bool debug = false; +int pos = 0; Servo servo; void setup() { @@ -166,14 +168,54 @@ void handleServo(char *pin, char *val, char *aux) { int p = getPin(pin); if(p == -1) { if(debug) Serial.println("badpin"); return; } Serial.println("got signal"); + if (atoi(val) == 0) { servo.detach(); + Serial.println("detached"); } else if (atoi(val) == 1) { servo.attach(p); Serial.println("attached"); } else if (atoi(val) == 2) { Serial.println("writing to servo"); Serial.println(atoi(aux)); - servo.write(atoi(aux)); + + // servo.write(atoi(aux)); + moveTo( atoi(aux) ); + + } else if (atoi(val) == 3) { + Serial.println("reading servo"); + int sval = servo.read(); + char m[8]; + sprintf(m, "%s::%03d::read", pin, sval); + Serial.println(m); + } + //delay(15); +} + +// move to the given position +void moveTo(int pos) { + int step = 4; // decrease this to slow movement + int current = servo.read(); + int movement = pos - current; // the number of degrees to move + + Serial.println(movement); + if (movement < 0) { + while (current > pos) { + current = current - step; + if (current < pos) + current = pos; + + servo.write( current); + delay(15); + } + } else { + while (current < pos) { + current = current + step; + if (current > pos) + current = pos; + + servo.write( current); + delay(15); + } } } From 2ee0d8b1a435148f54ef7840fe10a4915b121d0e Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Thu, 15 Mar 2012 21:25:17 -0400 Subject: [PATCH 08/55] Only emit for this.pin messages Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/ldr.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ldr.js b/lib/ldr.js index 959ef45..dcabc92 100644 --- a/lib/ldr.js +++ b/lib/ldr.js @@ -19,7 +19,10 @@ var LDR = function (options) { this.board.on('data', function (m) { m = m.slice(0, -1).split('::'); - self.emit('data', m[1]); + + if (this.pin === m[0]) { + self.emit('data', m[1]); + } }); } From 9995b39c9edcf0345eb5ea253b236ee3c37450a6 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Fri, 16 Mar 2012 11:26:39 -0400 Subject: [PATCH 09/55] Simplify handleServo responsibilities Signed-off-by: Rick Waldron waldron.rick@gmail.com --- src/du.ino | 59 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/du.ino b/src/du.ino index fd93243..48733d8 100644 --- a/src/du.ino +++ b/src/du.ino @@ -179,8 +179,8 @@ void handleServo(char *pin, char *val, char *aux) { Serial.println("writing to servo"); Serial.println(atoi(aux)); - // servo.write(atoi(aux)); - moveTo( atoi(aux) ); + servo.write(atoi(aux)); + // moveTo( atoi(aux) ); } else if (atoi(val) == 3) { Serial.println("reading servo"); @@ -189,33 +189,32 @@ void handleServo(char *pin, char *val, char *aux) { sprintf(m, "%s::%03d::read", pin, sval); Serial.println(m); } - //delay(15); } -// move to the given position -void moveTo(int pos) { - int step = 4; // decrease this to slow movement - int current = servo.read(); - int movement = pos - current; // the number of degrees to move - - Serial.println(movement); - if (movement < 0) { - while (current > pos) { - current = current - step; - if (current < pos) - current = pos; - - servo.write( current); - delay(15); - } - } else { - while (current < pos) { - current = current + step; - if (current > pos) - current = pos; - - servo.write( current); - delay(15); - } - } -} +// // move to the given position +// void moveTo(int pos) { +// int step = 4; // decrease this to slow movement +// int current = servo.read(); +// int movement = pos - current; // the number of degrees to move + +// Serial.println(movement); +// if (movement < 0) { +// while (current > pos) { +// current = current - step; +// if (current < pos) +// current = pos; + +// servo.write( current); +// delay(15); +// } +// } else { +// while (current < pos) { +// current = current + step; +// if (current > pos) +// current = pos; + +// servo.write( current); +// delay(15); +// } +// } +// } From e828e8154eeb5d55eba703098cd3342c014cee86 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 14:49:09 -0400 Subject: [PATCH 10/55] Updates all servo functionality for maximum flexibility in use cases. New events: attached, detached, read (returns current servo position reading) Signed-off-by: Rick Waldron waldron.rick@gmail.com --- src/du.ino | 57 +++++++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/src/du.ino b/src/du.ino index 48733d8..bbb0c18 100644 --- a/src/du.ino +++ b/src/du.ino @@ -1,14 +1,18 @@ #include -char messageBuffer[12]; +bool debug = false; + int index = 0; + +char messageBuffer[12]; char cmd[3]; char pin[3]; char val[4]; char aux[4]; -bool debug = false; -int pos = 0; + + + Servo servo; void setup() { @@ -171,50 +175,29 @@ void handleServo(char *pin, char *val, char *aux) { if (atoi(val) == 0) { servo.detach(); - Serial.println("detached"); + char m[12]; + sprintf(m, "%s::detached", pin); + Serial.println(m); } else if (atoi(val) == 1) { - servo.attach(p); - Serial.println("attached"); + servo.attach(p, 600, 2200); + char m[12]; + sprintf(m, "%s::attached", pin); + Serial.println(m); } else if (atoi(val) == 2) { Serial.println("writing to servo"); Serial.println(atoi(aux)); - + // Write to servo servo.write(atoi(aux)); - // moveTo( atoi(aux) ); + // TODO: Experiment with microsecond pulses + // digitalWrite(pin, HIGH); // start the pulse + // delayMicroseconds(pulseWidth); // pulse width + // digitalWrite(pin, LOW); // stop the pulse } else if (atoi(val) == 3) { Serial.println("reading servo"); int sval = servo.read(); char m[8]; - sprintf(m, "%s::%03d::read", pin, sval); + sprintf(m, "%s::read::%03d", pin, sval); Serial.println(m); } } - -// // move to the given position -// void moveTo(int pos) { -// int step = 4; // decrease this to slow movement -// int current = servo.read(); -// int movement = pos - current; // the number of degrees to move - -// Serial.println(movement); -// if (movement < 0) { -// while (current > pos) { -// current = current - step; -// if (current < pos) -// current = pos; - -// servo.write( current); -// delay(15); -// } -// } else { -// while (current < pos) { -// current = current + step; -// if (current > pos) -// current = pos; - -// servo.write( current); -// delay(15); -// } -// } -// } From ab2a02fe8693192d1ab851cd2219e873f091d5da Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 14:53:22 -0400 Subject: [PATCH 11/55] Adds functionality to Servo module to handle attached, detached, read events Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/servo.js | 156 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 23 deletions(-) diff --git a/lib/servo.js b/lib/servo.js index c609411..1602844 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -1,3 +1,6 @@ +var events = require('events'), + util = require('util'); + /* * Main Servo constructor * Process options @@ -7,32 +10,139 @@ var Servo = function (options) { if (!options || !options.board) throw new Error('Must supply required options to Sutton'); this.board = options.board; this.pin = this.board.normalizePin(options.pin || 9); - var self = this; + + var types = { + attached: true, + detached: true, + read: true, + moved: true + }; + this.board.on('ready', function () { - self.attach(); - }); -} + this.attach(); + }.bind(this)); -Servo.prototype.write = function (pos) { - this.board.write('98' + this.pin + '02' + pos); -} + this.board.on('data', function (message) { + var m = message.slice(0, -1).split('::'), + pin, type, data; + + if (!m.length) { + return; + } + + pin = m[0] + type = m[1]; + data = m.length === 3 ? m[2] : null; + + if (pin === this.pin && types[type]) { + this.emit(type, data); + } + }.bind(this)); +}; + +util.inherits(Servo, events.EventEmitter); + +Servo.prototype.command = function () { + var msg = '98' + this.pin + ([].slice.call(arguments).join('')); + + // this.board.log( 'info', 'command', msg ); + this.board.write(msg); +}; + +Servo.prototype.detach = function () { + this.command('00'); +}; Servo.prototype.attach = function () { - this.board.write('98' + this.pin + '01'); -} - -Servo.prototype.read = function () {} -Servo.prototype.detach = function () {} -Servo.prototype.writeMilliseconds = function () {} -Servo.prototype.attached = function () {} - -Servo.prototype.sweep = function () { - var self = this; - var pos = 0; - setInterval(function() { - self.write(pos++); - if (pos == 180) clearInterval(this); - }, 25); -} + this.command('01'); +}; + +Servo.prototype.write = function (pos) { + pos = this.board.lpad(3, '0', pos); + this.board.log('info', 'moving to: ' + pos); + this.command('02' + pos); +}; + +Servo.prototype.read = function (callback) { + this.command('03'); +}; + +// Servo.prototype.writeMilliseconds = function () {}; +// Servo.prototype.attached = function (callback) { +// this.callbacks.attached.push(callback); +// }; + +Servo.prototype.sweep = function (options) { + // Ensure no missing options object + options = options || {}; + + var timeout = { + inner: null, + outer: null + }, + moves = 0, + // sweep settings + lapse = options.lapse || 500, + to = options.to || 180, + from = options.from || 1; + // sweep handlers + doSweep = function doSweep(pos) { + // this.board.log('info', 'current position: ', pos); + var moveTo, + posint = +pos; + + // this.board.log('info', 'current pos int: ', posint); + + if (posint === 93) { + moveTo = 1; + } else { + + // this.board.log('info', 'posint not 93.....'); + + if (posint < to) { + moveTo = to; + } else if (posint == to) { + moveTo = 90; + } else { + moveTo = from; + } + } + + this.write(moveTo); + + moves++; + + // this.board.log( 'info', 'moves: ', moves ); + }; + + this.on('read', doSweep); + + // this.write(1); + + // Initialize sweep; wait for for stack unwind. + timeout.outer = setTimeout(function loop() { + // Read the current position, will trigger + // 'read' event with position data; + + + if (moves < 2) { + this.read(); + + timeout.inner = setTimeout(loop.bind(this), lapse); + } else { + // this.board.log('info', 'info', 'clearing'); + + clearTimeout(timeout.inner); + clearTimeout(timeout.outer); + + loop = null; + + this.removeListener('read', doSweep); + this.emit.call(this, 'aftersweep'); + + // this.board.log('info', this); + } + }.bind(this), 0); +}; module.exports = Servo; From 4403974604fd7247472310434921244ae90feabf Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:03:37 -0400 Subject: [PATCH 12/55] Servo event examples Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/servo.js | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/examples/servo.js b/examples/servo.js index 5dc3110..10c8b87 100644 --- a/examples/servo.js +++ b/examples/servo.js @@ -1,22 +1,50 @@ -var arduino = require('../'); +var arduino = require('../'), + board, led, servo; -var board = new arduino.Board({ +// Construct instances +board = new arduino.Board({ debug: true }); -var servo = new arduino.Servo({ +led = new arduino.Led({ board: board, - pin: "A0" + pin: 13 }); +servo = new arduino.Servo({ + board: board, + pin: 9 +}); +// Once servo is attached: +// - "read" +// - log position +// - "aftersweep" +// - blink the led +// - read the position +// - detach the servo +// - "detached" +// - log detach message +// +// - execute full sweep + +servo.on('attached', function() { + console.log('attached'); + + this.on('read', function(pos) { + console.log(pos); + }); -servo.on("attached", function() { - - this.read(function(current) { - this.write(180); + this.on('detached', function() { + console.log('detached'); }); + this.on('aftersweep', function() { + led.blink(); + this.read(); + this.detach(); + }); + this.sweep(); }); From a2ef830ca4c7dff9f64458bf60451d923879c38b Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:04:54 -0400 Subject: [PATCH 13/55] Abstract numeric normalization/padding into reusable method Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/board.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/board.js b/lib/board.js index 789e71a..5afcbf6 100644 --- a/lib/board.js +++ b/lib/board.js @@ -125,20 +125,18 @@ Board.prototype.write = function (m) { * Add a 0 to the front of a single-digit pin number */ Board.prototype.normalizePin = function (pin) { - return ("00" + pin).substr(-2); - /*pin = String(pin).split(''); - if (pin.length > 1) { - return pin.join(''); - } else { - pin.unshift('0'); - return pin.join(''); - }*/ + return this.lpad( 2, "0", pin ); } Board.prototype.normalizeVal = function(val) { - return ("000" + val).substr(-3); + return this.lpad( 3, "0", val ); } +// +Board.prototype.lpad = function(len, chr, str) { + return (Array(len + 1).join(chr || ' ') + str).substr(-len); +}; + /* * Define constants */ @@ -204,8 +202,9 @@ Board.prototype.delay = function (ms) { * Logger utility function */ Board.prototype.log = function (level, message) { + var args = [].slice.call(arguments); if (this.debug) { - console.log(String(+new Date()).grey + ' duino '.blue + level.magenta + ' ' + message); + console.log(String(+new Date()).grey + ' duino '.blue + args.shift().magenta + ' ' + args.join(", ")); } } From 546968a7f95c036b4d0cce312edf5322ddf8b787 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:21:46 -0400 Subject: [PATCH 14/55] Pivot LDR module into generic Sensor module Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/sensor.js | 17 +++++++++++++++++ index.js | 3 ++- lib/sensor.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 examples/sensor.js create mode 100644 lib/sensor.js diff --git a/examples/sensor.js b/examples/sensor.js new file mode 100644 index 0000000..0e987a5 --- /dev/null +++ b/examples/sensor.js @@ -0,0 +1,17 @@ +var arduino = require('../'), + board, ldr; + +board = new arduino.Board({ + debug: true +}); + +ldr = new arduino.Sensor({ + board: board, + pin: 'A0' +}); + +ldr.on('read', function(value) { + + // |value| is reading of the light dependent resistor + console.log(value); +}); diff --git a/index.js b/index.js index 360176f..203e3a2 100644 --- a/index.js +++ b/index.js @@ -4,5 +4,6 @@ module.exports = { Led: require('./lib/led'), Piezo: require('./lib/piezo'), Button: require('./lib/button'), + Sensor: require('./lib/sensor'), Servo: require('./lib/servo') -} +}; diff --git a/lib/sensor.js b/lib/sensor.js new file mode 100644 index 0000000..f3f4328 --- /dev/null +++ b/lib/sensor.js @@ -0,0 +1,44 @@ +var events = require('events'), + util = require('util'); + +/* + * Main Sensor constructor + * Process options + * Tell the board to set it up + */ +var Sensor = function (options) { + if (!options || !options.board) throw new Error('Must supply required options to Sensor'); + this.board = options.board; + this.pin = options.pin || 'A0'; + this.board.pinMode(this.pin, 'in'); + + // Poll for sensor readings + setInterval(function () { + this.board.analogRead(this.pin); + }.bind(this), 50); + + // When data is received, parse inbound message + // match pin to instance pin value + this.board.on('data', function (m) { + var m = message.slice(0, -1).split('::'), + pin, data; + + if (!m.length) { + return; + } + + pin = m[0] + data = m.length === 2 ? m[1] : null; + + if (pin === this.pin) { + this.emit('read', data); + } + }.bind(this)); +}; + +/* + * EventEmitter, I choose you! + */ +util.inherits(Sensor, events.EventEmitter); + +module.exports = Sensor; From 489562de7b546c2c5393bf7160d379811d54115a Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:24:08 -0400 Subject: [PATCH 15/55] Removes ldr.js files Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/ldr.js | 16 ---------------- lib/ldr.js | 34 ---------------------------------- 2 files changed, 50 deletions(-) delete mode 100644 examples/ldr.js delete mode 100644 lib/ldr.js diff --git a/examples/ldr.js b/examples/ldr.js deleted file mode 100644 index f1810eb..0000000 --- a/examples/ldr.js +++ /dev/null @@ -1,16 +0,0 @@ -var arduino = require('../'); - -var board = new arduino.Board({ - // debug: true -}); - -var ldr = new arduino.LDR({ - board: board, - pin: 'A0' -}); - -ldr.on('data', function( value ) { - - // |value| is reading of the light dependent resistor - console.log( value ); -}); diff --git a/lib/ldr.js b/lib/ldr.js deleted file mode 100644 index dcabc92..0000000 --- a/lib/ldr.js +++ /dev/null @@ -1,34 +0,0 @@ -var events = require('events'), - util = require('util'); - -/* - * Main LDR constructor - * Process options - * Tell the board to set it up - */ -var LDR = function (options) { - if (!options || !options.board) throw new Error('Must supply required options to LDR'); - this.board = options.board; - this.pin = options.pin || 'A0'; - this.board.pinMode(this.pin, 'in'); - - var self = this; - setInterval(function () { - self.board.analogRead(self.pin); - }, 50); - - this.board.on('data', function (m) { - m = m.slice(0, -1).split('::'); - - if (this.pin === m[0]) { - self.emit('data', m[1]); - } - }); -} - -/* - * EventEmitter, I choose you! - */ -util.inherits(LDR, events.EventEmitter); - -module.exports = LDR; From ddc6237ec528a4393ae6f8b58e2e7978fe3fc919 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:26:47 -0400 Subject: [PATCH 16/55] Consistent quotes Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/board.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/board.js b/lib/board.js index 5afcbf6..c7d6e9a 100644 --- a/lib/board.js +++ b/lib/board.js @@ -73,7 +73,7 @@ Board.prototype.detect = function (cb) { try { tempSerial = new serial.SerialPort('/dev/' + possible[i], { baudrate: 115200, - parser: serial.parsers.readline("\n") + parser: serial.parsers.readline('\n') }); } catch (e) { err = e; @@ -125,11 +125,11 @@ Board.prototype.write = function (m) { * Add a 0 to the front of a single-digit pin number */ Board.prototype.normalizePin = function (pin) { - return this.lpad( 2, "0", pin ); + return this.lpad( 2, '0', pin ); } Board.prototype.normalizeVal = function(val) { - return this.lpad( 3, "0", val ); + return this.lpad( 3, '0', val ); } // @@ -204,7 +204,7 @@ Board.prototype.delay = function (ms) { Board.prototype.log = function (level, message) { var args = [].slice.call(arguments); if (this.debug) { - console.log(String(+new Date()).grey + ' duino '.blue + args.shift().magenta + ' ' + args.join(", ")); + console.log(String(+new Date()).grey + ' duino '.blue + args.shift().magenta + ' ' + args.join(', ')); } } From 8301f1a94a742f79c68e29bbe2d6d030a998372c Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:27:40 -0400 Subject: [PATCH 17/55] No formal param list for logging function Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/board.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/board.js b/lib/board.js index c7d6e9a..72af24b 100644 --- a/lib/board.js +++ b/lib/board.js @@ -201,7 +201,7 @@ Board.prototype.delay = function (ms) { /* * Logger utility function */ -Board.prototype.log = function (level, message) { +Board.prototype.log = function (/*level, message*/) { var args = [].slice.call(arguments); if (this.debug) { console.log(String(+new Date()).grey + ' duino '.blue + args.shift().magenta + ' ' + args.join(', ')); From b1cf76f09f1e7425860fe9ee201c65719e1a3357 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sat, 17 Mar 2012 15:31:02 -0400 Subject: [PATCH 18/55] Widen servo pulse range Signed-off-by: Rick Waldron waldron.rick@gmail.com --- src/du.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/du.ino b/src/du.ino index bbb0c18..293aa06 100644 --- a/src/du.ino +++ b/src/du.ino @@ -179,7 +179,7 @@ void handleServo(char *pin, char *val, char *aux) { sprintf(m, "%s::detached", pin); Serial.println(m); } else if (atoi(val) == 1) { - servo.attach(p, 600, 2200); + servo.attach(p, 100, 2200); char m[12]; sprintf(m, "%s::attached", pin); Serial.println(m); From b2ac21686ee435558a6e14a78ace9f2c94ac4173 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 12:34:56 -0400 Subject: [PATCH 19/55] Adds Ping module to API Signed-off-by: Rick Waldron waldron.rick@gmail.com --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 203e3a2..a323f65 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ module.exports = { Led: require('./lib/led'), Piezo: require('./lib/piezo'), Button: require('./lib/button'), + Servo: require('./lib/servo'), Sensor: require('./lib/sensor'), - Servo: require('./lib/servo') + Ping: require('./lib/ping') }; From e1c969919c107b55756a6a0a5b329a8689d63373 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 12:35:34 -0400 Subject: [PATCH 20/55] Removes obsolete callback arg Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/servo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/servo.js b/lib/servo.js index 1602844..de77d5f 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -63,7 +63,7 @@ Servo.prototype.write = function (pos) { this.command('02' + pos); }; -Servo.prototype.read = function (callback) { +Servo.prototype.read = function () { this.command('03'); }; From 3e9ff4bf536deb32708a222349cccb547cb1a455 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 13:30:21 -0400 Subject: [PATCH 21/55] Adds .DS_Store to gitignore Signed-off-by: Rick Waldron waldron.rick@gmail.com --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b512c09..9daa824 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +.DS_Store +node_modules From 590050dc2ffdb6312a2e0738904c1c4e3415e6c9 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 13:50:13 -0400 Subject: [PATCH 22/55] Implement arcuino io support for ping))) Signed-off-by: Rick Waldron waldron.rick@gmail.com --- src/du.ino | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/du.ino b/src/du.ino index 293aa06..87da363 100644 --- a/src/du.ino +++ b/src/du.ino @@ -11,8 +11,6 @@ char pin[3]; char val[4]; char aux[4]; - - Servo servo; void setup() { @@ -54,6 +52,7 @@ void process() { case 2: dr(pin,val); break; case 3: aw(pin,val); break; case 4: ar(pin,val); break; + case 97: handlePing(pin,val,aux); break; case 98: handleServo(pin,val,aux); break; case 99: toggleDebug(val); break; default: break; @@ -162,6 +161,37 @@ int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error return ret; } +/* + * Handle Ping commands + * fire, read + */ +void handlePing(char *pin, char *val, char *aux) { + if (debug) Serial.println("ss"); + int p = getPin(pin); + + if(p == -1) { if(debug) Serial.println("badpin"); return; } + Serial.println("got signal"); + + // 01(1) Fire and Read + if (atoi(val) == 1) { + char m[16]; + + pinMode(p, OUTPUT); + digitalWrite(p, LOW); + delayMicroseconds(2); + digitalWrite(p, HIGH); + delayMicroseconds(5); + digitalWrite(p, LOW); + + Serial.println("ping fired"); + + pinMode(p, INPUT); + sprintf(m, "%s::read::%08d", pin, pulseIn(p, HIGH)); + Serial.println(m); + + delay(50); + } +} /* * Handle Servo commands @@ -173,16 +203,21 @@ void handleServo(char *pin, char *val, char *aux) { if(p == -1) { if(debug) Serial.println("badpin"); return; } Serial.println("got signal"); + // 00(0) Detach if (atoi(val) == 0) { servo.detach(); char m[12]; sprintf(m, "%s::detached", pin); Serial.println(m); + + // 01(1) Attach } else if (atoi(val) == 1) { servo.attach(p, 100, 2200); char m[12]; sprintf(m, "%s::attached", pin); Serial.println(m); + + // 02(2) Write } else if (atoi(val) == 2) { Serial.println("writing to servo"); Serial.println(atoi(aux)); @@ -193,10 +228,12 @@ void handleServo(char *pin, char *val, char *aux) { // digitalWrite(pin, HIGH); // start the pulse // delayMicroseconds(pulseWidth); // pulse width // digitalWrite(pin, LOW); // stop the pulse + + // 03(3) Read } else if (atoi(val) == 3) { Serial.println("reading servo"); int sval = servo.read(); - char m[8]; + char m[13]; sprintf(m, "%s::read::%03d", pin, sval); Serial.println(m); } From bd3a75e8015e2f01b65db4fcf04ecd0b62d3e93c Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 13:51:03 -0400 Subject: [PATCH 23/55] Ping module and example with link to arduino board spec Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/ping.js | 31 +++++++++++++++++++++ lib/ping.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 examples/ping.js create mode 100644 lib/ping.js diff --git a/examples/ping.js b/examples/ping.js new file mode 100644 index 0000000..cf38716 --- /dev/null +++ b/examples/ping.js @@ -0,0 +1,31 @@ +var arduino = require('../'), + board, ping; + +board = new arduino.Board({ + debug: false +}); + +ping = new arduino.Ping({ + board: board, + pin: 7 +}); + +// 'read' events fire approx ~50ms +ping.on('read', function() { + + // Current sensor data stored in properties + // of this Ping instance: + // + // this.microseconds - time lapse from fire to read + // this.inches - calculated distance to object in inches + // this.centimeters - calculated distance to object in centimeters + + console.log('Object is ~' + Math.round(this.inches) + ' inches from sensor'); + +}); + +// To test, use the following: +// http://arduino.cc/en/uploads/Tutorial/ping_bb.png +// +// More information: +// http://arduino.cc/en/Tutorial/Ping diff --git a/lib/ping.js b/lib/ping.js new file mode 100644 index 0000000..3a3f850 --- /dev/null +++ b/lib/ping.js @@ -0,0 +1,70 @@ +var events = require('events'), + util = require('util'); + +/* + * Main Ping constructor + * Process options + * Tell the board to set it up + */ +var Ping = function (options) { + if (!options || !options.board) throw new Error('Must supply required options to Ping'); + this.board = options.board; + this.pin = this.board.normalizePin(options.pin || 9); + + // Data response is in microseconds + this.microseconds = 0; + this.inches = 0; + this.centimeters = 0; + + var types = { + read: true + }; + + // Loop and trigger fire-read sequences + setInterval(function () { + this.fire(); + }.bind(this), 50); + + this.board.on('data', function (message) { + var m = message.slice(0, -1).split('::'), + pin, type, data; + + if (!m.length) { + return; + } + + pin = m[0] + type = m[1]; + data = m.length === 3 ? m[2] : null; + + if (pin === this.pin && types[type]) { + // See: http://arduino.cc/en/Tutorial/Ping + // According to Parallax's datasheet for the PING))), there are + // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per + // second). This gives the distance travelled by the ping, outbound + // and return, so we divide by 2 to get the distance of the obstacle. + // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf + this.inches = data / 74 / 2; + // The speed of sound is 340 m/s or 29 microseconds per centimeter. + // The ping travels out and back, so to find the distance of the + // object we take half of the distance travelled. + this.centimeters = data / 29 / 2; + + this.emit(type, data); + } + }.bind(this)); +}; + +util.inherits(Ping, events.EventEmitter); + +Ping.prototype.command = function () { + var msg = '97' + this.pin + ([].slice.call(arguments).join('')); + + this.board.write(msg); +}; + +Ping.prototype.fire = function () { + this.command('01'); +}; + +module.exports = Ping; From d9d7284bedb0ae6c55237d629d84b28bef15ffc3 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 16:15:38 -0400 Subject: [PATCH 24/55] Implements PIR sensor inferface; calibrated, motionstart, motionend events Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/pir.js | 51 ++++++++++++++++++++++++++++++++++++ index.js | 3 ++- lib/pir.js | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 examples/pir.js create mode 100644 lib/pir.js diff --git a/examples/pir.js b/examples/pir.js new file mode 100644 index 0000000..bf38c47 --- /dev/null +++ b/examples/pir.js @@ -0,0 +1,51 @@ +var arduino = require('../'), + board, pir; + +board = new arduino.Board({ + debug: false +}); + +pir = new arduino.PIR({ + board: board, + pin: 7 +}); + +// 'calibrated' event fired when PIR sensor is +// ready to detect movement/motion in observable range +// +// All events receive error and date arguments +pir.on('calibrated', function(err, date) { + + console.log('calibrated'); + + // Current sensor data stored in properties + // of this PIR instance: + // + // this.state - current state of motion + // 0 No motion currently detected + // 1 Motion currently detected + + // 'motionstart' event fired when motion occurs + // within the observable range of the PIR sensor + this.on('motionstart', function(err, date) { + + console.log('motionstart', this.state); + console.log( date ); + + }); + + // 'motionend' event fired when motion has ceased + // within the observable range of the PIR sensor + this.on('motionend', function(err, date) { + + console.log('motionend', this.state); + + }); +}); + + +// To test, use the following: +// http://www.ladyada.net/images/sensors/pirardbb.gif +// +// More information: +// http://www.ladyada.net/learn/sensors/pir.html diff --git a/index.js b/index.js index a323f65..a30f8f9 100644 --- a/index.js +++ b/index.js @@ -6,5 +6,6 @@ module.exports = { Button: require('./lib/button'), Servo: require('./lib/servo'), Sensor: require('./lib/sensor'), - Ping: require('./lib/ping') + Ping: require('./lib/ping'), + PIR: require('./lib/pir') }; diff --git a/lib/pir.js b/lib/pir.js new file mode 100644 index 0000000..cef77dc --- /dev/null +++ b/lib/pir.js @@ -0,0 +1,69 @@ +var events = require('events'), + util = require('util'); + +/* + * Main PIR constructor + * Process options + * Tell the board to set it up + */ +var PIR = function (options) { + if (!options || !options.board) { + throw new Error('Must supply required options to PIR'); + } + this.board = options.board; + this.pin = this.board.normalizePin(options.pin || 9); + this.state = null; + this.calibrated = false; + + setInterval(function () { + this.board.digitalRead(this.pin); + }.bind(this), 50); + + this.board.on('data', function (message) { + var m = message.slice(0, -1).split('::'), + timestamp = new Date(), + err = null, + pin, data; + + if (!m.length) { + return; + } + + pin = m[0]; + data = m[1]; + + if (pin === this.pin) { + + // If this is not a calibration event + if (this.state != null && this.state != +data) { + + // Update current state of PIR instance + this.state = +data; + + // 'motionstart' event fired when motion occurs + // within the observable range of the PIR sensor + if (data === '01') { + this.emit('motionstart', err, timestamp); + } + + // 'motionend' event fired when motion has ceased + // within the observable range of the PIR sensor + if (data === '00') { + this.emit('motionend', err, timestamp); + } + } + + // 'calibrated' event fired when PIR sensor is + // ready to detect movement/motion in observable range + if (!this.calibrated) { + this.calibrated = true; + this.state = +data; + this.emit('calibrated', err, timestamp); + } + } + }.bind(this)); +}; + +util.inherits(PIR, events.EventEmitter); + +module.exports = PIR; From ba695e736df2d065dff686445c5a91cfa365fbec Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 16:16:46 -0400 Subject: [PATCH 25/55] First arg is err for all new and updated modules Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/ping.js | 2 +- examples/sensor.js | 2 +- examples/servo.js | 14 ++++++++++---- lib/button.js | 7 +++++-- lib/ping.js | 5 +++-- lib/sensor.js | 3 ++- lib/servo.js | 11 ++--------- src/du.ino | 1 + 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/examples/ping.js b/examples/ping.js index cf38716..c50499c 100644 --- a/examples/ping.js +++ b/examples/ping.js @@ -11,7 +11,7 @@ ping = new arduino.Ping({ }); // 'read' events fire approx ~50ms -ping.on('read', function() { +ping.on('read', function(err) { // Current sensor data stored in properties // of this Ping instance: diff --git a/examples/sensor.js b/examples/sensor.js index 0e987a5..6e0d21d 100644 --- a/examples/sensor.js +++ b/examples/sensor.js @@ -10,7 +10,7 @@ ldr = new arduino.Sensor({ pin: 'A0' }); -ldr.on('read', function(value) { +ldr.on('read', function(err, value) { // |value| is reading of the light dependent resistor console.log(value); diff --git a/examples/servo.js b/examples/servo.js index 10c8b87..eb732ab 100644 --- a/examples/servo.js +++ b/examples/servo.js @@ -28,18 +28,18 @@ servo = new arduino.Servo({ // // - execute full sweep -servo.on('attached', function() { +servo.on('attached', function(err) { console.log('attached'); - this.on('read', function(pos) { + this.on('read', function(err, pos) { console.log(pos); }); - this.on('detached', function() { + this.on('detached', function(err) { console.log('detached'); }); - this.on('aftersweep', function() { + this.on('aftersweep', function(err) { led.blink(); this.read(); @@ -48,3 +48,9 @@ servo.on('attached', function() { this.sweep(); }); + +// To test, use the following: +// http://arduino.cc/en/uploads/Tutorial/sweep_BB.png +// +// More information: +// http://www.ladyada.net/learn/sensors/pir.html diff --git a/lib/button.js b/lib/button.js index eb886ae..636a132 100644 --- a/lib/button.js +++ b/lib/button.js @@ -18,16 +18,19 @@ var Button = function (options) { }, 50); this.board.on('data', function (m) { m = m.slice(0, -1).split('::'); + + var err = null; + if (m.length > 1 && m[0] == self.pin) { // 0 is up // 1 is down if (m[1] == 0 && self.down) { self.down = false; - self.emit('up'); + self.emit('up', err); } if (m[1] == 1 && !self.down) { self.down = true; - self.emit('down'); + self.emit('down', err); } } }); diff --git a/lib/ping.js b/lib/ping.js index 3a3f850..9eac71b 100644 --- a/lib/ping.js +++ b/lib/ping.js @@ -27,13 +27,14 @@ var Ping = function (options) { this.board.on('data', function (message) { var m = message.slice(0, -1).split('::'), + err = null, pin, type, data; if (!m.length) { return; } - pin = m[0] + pin = m[0]; type = m[1]; data = m.length === 3 ? m[2] : null; @@ -50,7 +51,7 @@ var Ping = function (options) { // object we take half of the distance travelled. this.centimeters = data / 29 / 2; - this.emit(type, data); + this.emit(type, err, data); } }.bind(this)); }; diff --git a/lib/sensor.js b/lib/sensor.js index f3f4328..4bd91c8 100644 --- a/lib/sensor.js +++ b/lib/sensor.js @@ -21,6 +21,7 @@ var Sensor = function (options) { // match pin to instance pin value this.board.on('data', function (m) { var m = message.slice(0, -1).split('::'), + err = null, pin, data; if (!m.length) { @@ -31,7 +32,7 @@ var Sensor = function (options) { data = m.length === 2 ? m[1] : null; if (pin === this.pin) { - this.emit('read', data); + this.emit('read', err, data); } }.bind(this)); }; diff --git a/lib/servo.js b/lib/servo.js index de77d5f..f2c2fc6 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -24,6 +24,7 @@ var Servo = function (options) { this.board.on('data', function (message) { var m = message.slice(0, -1).split('::'), + err = null, pin, type, data; if (!m.length) { @@ -35,7 +36,7 @@ var Servo = function (options) { data = m.length === 3 ? m[2] : null; if (pin === this.pin && types[type]) { - this.emit(type, data); + this.emit(type, err, data); } }.bind(this)); }; @@ -111,20 +112,14 @@ Servo.prototype.sweep = function (options) { this.write(moveTo); moves++; - - // this.board.log( 'info', 'moves: ', moves ); }; this.on('read', doSweep); - // this.write(1); - // Initialize sweep; wait for for stack unwind. timeout.outer = setTimeout(function loop() { // Read the current position, will trigger // 'read' event with position data; - - if (moves < 2) { this.read(); @@ -139,8 +134,6 @@ Servo.prototype.sweep = function (options) { this.removeListener('read', doSweep); this.emit.call(this, 'aftersweep'); - - // this.board.log('info', this); } }.bind(this), 0); }; diff --git a/src/du.ino b/src/du.ino index 87da363..ae2b932 100644 --- a/src/du.ino +++ b/src/du.ino @@ -223,6 +223,7 @@ void handleServo(char *pin, char *val, char *aux) { Serial.println(atoi(aux)); // Write to servo servo.write(atoi(aux)); + delay(15); // TODO: Experiment with microsecond pulses // digitalWrite(pin, HIGH); // start the pulse From b060853d28601c0fd4016abb7dabd57a52fd6554 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 16:32:03 -0400 Subject: [PATCH 26/55] Additional breadboard schematic for PIR Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/pir.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/pir.js b/examples/pir.js index bf38c47..fd3e788 100644 --- a/examples/pir.js +++ b/examples/pir.js @@ -46,6 +46,7 @@ pir.on('calibrated', function(err, date) { // To test, use the following: // http://www.ladyada.net/images/sensors/pirardbb.gif +// http://bildr.org/blog/wp-content/uploads/2011/06/PIR-Arduino_hookup.png // // More information: // http://www.ladyada.net/learn/sensors/pir.html From c1a2a524c54dd142eec261880ff82b26a50fe54c Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 20:39:16 -0400 Subject: [PATCH 27/55] Servo improvement tweaks Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/servo.js | 5 +++-- src/du.ino | 37 +++++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/servo.js b/lib/servo.js index de77d5f..b85ef96 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -7,7 +7,7 @@ var events = require('events'), * Tell the board to set it up */ var Servo = function (options) { - if (!options || !options.board) throw new Error('Must supply required options to Sutton'); + if (!options || !options.board) throw new Error('Must supply required options to Servo'); this.board = options.board; this.pin = this.board.normalizePin(options.pin || 9); @@ -19,6 +19,7 @@ var Servo = function (options) { }; this.board.on('ready', function () { + console.log('board ready, attaching servo', this); this.attach(); }.bind(this)); @@ -82,7 +83,7 @@ Servo.prototype.sweep = function (options) { }, moves = 0, // sweep settings - lapse = options.lapse || 500, + lapse = options.lapse || 2000, to = options.to || 180, from = options.from || 1; // sweep handlers diff --git a/src/du.ino b/src/du.ino index 87da363..3d9276a 100644 --- a/src/du.ino +++ b/src/du.ino @@ -36,16 +36,30 @@ void process() { cmd[2] = '\0'; strncpy(pin, messageBuffer + 2, 2); pin[2] = '\0'; - strncpy(val, messageBuffer + 4, 2); - val[3] = '\0'; - strncpy(aux, messageBuffer + 6, 3); - aux[3] = '\0'; + + if (atoi(cmd) > 90) { + Serial.println("tesT"); + strncpy(val, messageBuffer + 4, 2); + val[2] = '\0'; + strncpy(aux, messageBuffer + 6, 3); + aux[3] = '\0'; + } else { + strncpy(val, messageBuffer + 4, 3); + val[4] = '\0'; + strncpy(aux, messageBuffer + 7, 3); + aux[4] = '\0'; + } if (debug) { Serial.println(messageBuffer); } int cmdid = atoi(cmd); + // Serial.println(cmd); + // Serial.println(pin); + // Serial.println(val); + // Serial.println(aux); + switch(cmdid) { case 0: sm(pin,val); break; case 1: dw(pin,val); break; @@ -139,10 +153,8 @@ void aw(char *pin, char *val) { int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error int ret = -1; - if(pin[0] == 'A' || pin[0] == 'a') - { - switch(pin[1]) - { + if(pin[0] == 'A' || pin[0] == 'a') { + switch(pin[1]) { case '0': ret = A0; break; case '1': ret = A1; break; case '2': ret = A2; break; @@ -153,8 +165,7 @@ int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error } } else { ret = atoi(pin); - if(ret == 0 && (pin[0] != '0' || pin[1] != '0')) - { + if(ret == 0 && (pin[0] != '0' || pin[1] != '0')) { ret = -1; } } @@ -201,7 +212,7 @@ void handleServo(char *pin, char *val, char *aux) { if (debug) Serial.println("ss"); int p = getPin(pin); if(p == -1) { if(debug) Serial.println("badpin"); return; } - Serial.println("got signal"); + Serial.println("signal: servo"); // 00(0) Detach if (atoi(val) == 0) { @@ -212,7 +223,8 @@ void handleServo(char *pin, char *val, char *aux) { // 01(1) Attach } else if (atoi(val) == 1) { - servo.attach(p, 100, 2200); + // servo.attach(p, 750, 2250); + servo.attach(p); char m[12]; sprintf(m, "%s::attached", pin); Serial.println(m); @@ -223,6 +235,7 @@ void handleServo(char *pin, char *val, char *aux) { Serial.println(atoi(aux)); // Write to servo servo.write(atoi(aux)); + delay(15); // TODO: Experiment with microsecond pulses // digitalWrite(pin, HIGH); // start the pulse From e5f4149276149f50b0c37fe7528e48432a98883c Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Sun, 18 Mar 2012 20:41:32 -0400 Subject: [PATCH 28/55] Board module improvements, use while() loop in place of for-in for mutable array iteration Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/board.js | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/board.js b/lib/board.js index 72af24b..af30801 100644 --- a/lib/board.js +++ b/lib/board.js @@ -62,30 +62,38 @@ util.inherits(Board, events.EventEmitter); * Loop through all USB devices and try to connect * This should really message the device and wait for a correct response */ -Board.prototype.detect = function (cb) { +Board.prototype.detect = function (callback) { this.log('info', 'attempting to find Arduino board'); var self = this; child.exec('ls /dev | grep usb', function(err, stdout, stderr){ - var possible = stdout.slice(0, -1).split('\n'), - found = false; - for (var i in possible) { - var tempSerial, err; - try { - tempSerial = new serial.SerialPort('/dev/' + possible[i], { - baudrate: 115200, - parser: serial.parsers.readline('\n') - }); - } catch (e) { - err = e; - } - if (!err) { - found = tempSerial; - self.log('info', 'found board at ' + tempSerial.port); - break; + var usb = stdout.slice(0, -1).split('\n'), + found = false, + err = null, + possible, temp; + + while ( usb.length ) { + possible = usb.pop(); + + if (possible.slice(0, 2) !== 'cu') { + try { + temp = new serial.SerialPort('/dev/' + possible, { + baudrate: 115200, + parser: serial.parsers.readline('\n') + }); + } catch (e) { + err = e; + } + if (!err) { + found = temp; + self.log('info', 'found board at ' + temp.port); + break; + } else { + err = new Error('Could not find Arduino'); + } } } - if (found) cb(null, found); - else cb(new Error('Could not find Arduino')); + + callback(err, found); }); } From 66148471a268f1fbd52af8bfba1c352da760a290 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 21 Mar 2012 14:28:58 -0400 Subject: [PATCH 29/55] Removes logging message Signed-off-by: Rick Waldron waldron.rick@gmail.com --- src/du.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/src/du.ino b/src/du.ino index 3d9276a..2427435 100644 --- a/src/du.ino +++ b/src/du.ino @@ -38,7 +38,6 @@ void process() { pin[2] = '\0'; if (atoi(cmd) > 90) { - Serial.println("tesT"); strncpy(val, messageBuffer + 4, 2); val[2] = '\0'; strncpy(aux, messageBuffer + 6, 3); From 4d05603c6afa56de75e96538bbac33d0752de07e Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 21 Mar 2012 14:29:37 -0400 Subject: [PATCH 30/55] Fixes m=>message bug. Signed-off-by: Rick Waldron waldron.rick@gmail.com --- lib/sensor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sensor.js b/lib/sensor.js index f3f4328..96b4381 100644 --- a/lib/sensor.js +++ b/lib/sensor.js @@ -19,7 +19,7 @@ var Sensor = function (options) { // When data is received, parse inbound message // match pin to instance pin value - this.board.on('data', function (m) { + this.board.on('data', function (message) { var m = message.slice(0, -1).split('::'), pin, data; From 6f59b13c8f7b0fc74aba6ec6728cf0d2987453ae Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 21 Mar 2012 14:31:07 -0400 Subject: [PATCH 31/55] Adds links to confirmed/tested sensors Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/sensor.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/sensor.js b/examples/sensor.js index 0e987a5..df20cb1 100644 --- a/examples/sensor.js +++ b/examples/sensor.js @@ -15,3 +15,11 @@ ldr.on('read', function(value) { // |value| is reading of the light dependent resistor console.log(value); }); + +// Tested with: +// SoftPot +// http://www.spectrasymbol.com/how-it-works-softpot +// http://www.sparkfun.com/datasheets/Sensors/Flex/SoftPot-Datasheet.pdf +// +// LDR +// http://www.ladyada.net/learn/sensors/cds.html From 830bfb248ed78f2df1a19e8b68c8a5cd93ca474f Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 21 Mar 2012 14:39:27 -0400 Subject: [PATCH 32/55] Make examples/sensor.js more generic Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/sensor.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/sensor.js b/examples/sensor.js index df20cb1..c4a2936 100644 --- a/examples/sensor.js +++ b/examples/sensor.js @@ -1,18 +1,18 @@ var arduino = require('../'), - board, ldr; + board, sensor; board = new arduino.Board({ debug: true }); -ldr = new arduino.Sensor({ +sensor = new arduino.Sensor({ board: board, pin: 'A0' }); -ldr.on('read', function(value) { - - // |value| is reading of the light dependent resistor +sensor.on('read', function(err, value) { + value = +value; + // |value| is current reading of sensor console.log(value); }); @@ -21,5 +21,5 @@ ldr.on('read', function(value) { // http://www.spectrasymbol.com/how-it-works-softpot // http://www.sparkfun.com/datasheets/Sensors/Flex/SoftPot-Datasheet.pdf // -// LDR +// sensor // http://www.ladyada.net/learn/sensors/cds.html From 8e926823141d5ac122f302399d2e5466affa4541 Mon Sep 17 00:00:00 2001 From: "Rick Waldron waldron.rick@gmail.com" Date: Wed, 21 Mar 2012 17:45:23 -0400 Subject: [PATCH 33/55] Throttled sensor example Signed-off-by: Rick Waldron waldron.rick@gmail.com --- examples/piezo.js | 4 ++++ examples/sensor-throttled.js | 36 ++++++++++++++++++++++++++++++++++++ examples/sensor.js | 4 ++-- lib/sensor.js | 2 +- 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 examples/sensor-throttled.js diff --git a/examples/piezo.js b/examples/piezo.js index 67ab39a..dd59278 100644 --- a/examples/piezo.js +++ b/examples/piezo.js @@ -15,3 +15,7 @@ board.on('ready', function(){ piezo.note('b', 1100); }, 1000); }); + + +// Resources +// http://arduino.cc/en/Tutorial/Tone4 diff --git a/examples/sensor-throttled.js b/examples/sensor-throttled.js new file mode 100644 index 0000000..1e4ed85 --- /dev/null +++ b/examples/sensor-throttled.js @@ -0,0 +1,36 @@ +var arduino = require('../'), + board, sensor, piezo; + +board = new arduino.Board({ + debug: false +}); + +sensor = new arduino.Sensor({ + board: board, + pin: 'A0', + throttle: 100 +}); + +piezo = new arduino.Piezo({ + board: board, + pin: 11 +}); + +sensor.on('read', function(err, value) { + value = +value; + + // |value| is the raw sensor output + console.log( value ); + + if ( value > 0 ) { + piezo.note('b', 100); + } +}); + +// Tested with: +// SoftPot +// http://www.spectrasymbol.com/how-it-works-softpot +// http://www.sparkfun.com/datasheets/Sensors/Flex/SoftPot-Datasheet.pdf +// +// sensor +// http://www.ladyada.net/learn/sensors/cds.html diff --git a/examples/sensor.js b/examples/sensor.js index e621c7b..b1a105a 100644 --- a/examples/sensor.js +++ b/examples/sensor.js @@ -12,8 +12,8 @@ sensor = new arduino.Sensor({ sensor.on('read', function(err, value) { value = +value; - // |value| is reading of the light dependent resistor - console.log(value/4); + // |value| is the raw sensor output + console.log( value ); }); // Tested with: diff --git a/lib/sensor.js b/lib/sensor.js index c09d1dc..a1883fc 100644 --- a/lib/sensor.js +++ b/lib/sensor.js @@ -15,7 +15,7 @@ var Sensor = function (options) { // Poll for sensor readings setInterval(function () { this.board.analogRead(this.pin); - }.bind(this), 50); + }.bind(this), options.throttle || 50); // When data is received, parse inbound message // match pin to instance pin value From 1e7de48872cb006cd7b387b3ea5cefc509bed9c8 Mon Sep 17 00:00:00 2001 From: Cam Pedersen Date: Tue, 24 Apr 2012 11:57:08 -0400 Subject: [PATCH 34/55] [dist] level up, add contributors and keywords --- package.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f606f2..bce03bb 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,17 @@ { "author": "Cam Pedersen (http://campedersen.com/)", + "contributors": [ + { "name": "Rick Waldron", "email": "waldron.rick@gmail.com" }, + { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, + ], "name": "duino", "description": "Arduino framework for mad scientists", - "version": "0.0.5", + "version": "0.0.6", + "keywords": [ + "arduino", + "serial", + "framework" + ], "repository": { "type": "git", "url": "git://github.com/ecto/duino.git" From 3793d6be198ccae62a0cd922890738a1a07a9984 Mon Sep 17 00:00:00 2001 From: Cam Pedersen Date: Tue, 24 Apr 2012 11:57:41 -0400 Subject: [PATCH 35/55] [derp] remove comma --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bce03bb..cba649f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Cam Pedersen (http://campedersen.com/)", "contributors": [ { "name": "Rick Waldron", "email": "waldron.rick@gmail.com" }, - { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, + { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" } ], "name": "duino", "description": "Arduino framework for mad scientists", From 87ecabce3a4067ae3b30fc8c864005eb977d42e3 Mon Sep 17 00:00:00 2001 From: Seiya Konno Date: Wed, 13 Jun 2012 20:13:53 +0900 Subject: [PATCH 36/55] Fixed global leak --- lib/servo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/servo.js b/lib/servo.js index 2a9b1d4..de61334 100644 --- a/lib/servo.js +++ b/lib/servo.js @@ -86,7 +86,7 @@ Servo.prototype.sweep = function (options) { // sweep settings lapse = options.lapse || 2000, to = options.to || 180, - from = options.from || 1; + from = options.from || 1, // sweep handlers doSweep = function doSweep(pos) { // this.board.log('info', 'current position: ', pos); From 5ac9eb73642434f3e21a0454df2c002dd7582892 Mon Sep 17 00:00:00 2001 From: Cam Pedersen Date: Wed, 13 Jun 2012 12:23:29 -0400 Subject: [PATCH 37/55] [dist] bump version and add contributor --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cba649f..7c7b79b 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "author": "Cam Pedersen (http://campedersen.com/)", "contributors": [ { "name": "Rick Waldron", "email": "waldron.rick@gmail.com" }, - { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" } + { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, + { "name": "Seiya Konno", "email": "nulltask@gmail.com" } ], "name": "duino", "description": "Arduino framework for mad scientists", - "version": "0.0.6", + "version": "0.0.7", "keywords": [ "arduino", "serial", From 009f338654cf41aaa3eb28c5d8ed5aa0a315daaf Mon Sep 17 00:00:00 2001 From: Trae Robrock Date: Tue, 28 Aug 2012 10:37:24 -0700 Subject: [PATCH 38/55] Make the baud rate configurable --- examples/adjustable-baud.js | 15 +++++++++++++++ lib/board.js | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 examples/adjustable-baud.js diff --git a/examples/adjustable-baud.js b/examples/adjustable-baud.js new file mode 100644 index 0000000..f897045 --- /dev/null +++ b/examples/adjustable-baud.js @@ -0,0 +1,15 @@ +var arduino = require('../'); + +var board = new arduino.Board({ + debug: true, + baudrate: 9600 +}); + +var led = new arduino.Led({ + board: board, + pin: 9 +}); + +board.on('ready', function(){ + led.blink(); +}); diff --git a/lib/board.js b/lib/board.js index 770d4c8..a1acf89 100644 --- a/lib/board.js +++ b/lib/board.js @@ -12,6 +12,7 @@ var events = require('events'), var Board = function (options) { this.log('info', 'initializing'); this.debug = options && options.debug || false; + this.baudrate = options && options.baudrate || 115200; this.writeBuffer = []; var self = this; @@ -83,7 +84,7 @@ Board.prototype.detect = function (callback) { if (possible.slice(0, 2) !== 'cu') { try { temp = new serial.SerialPort('/dev/' + possible, { - baudrate: 115200, + baudrate: self.baudrate, parser: serial.parsers.readline('\n') }); } catch (e) { From 1dc12777607d03899b211f61c43db6b0e8c49181 Mon Sep 17 00:00:00 2001 From: Setola Date: Mon, 3 Sep 2012 00:44:03 +0200 Subject: [PATCH 39/55] port is now manually configurable --- README.md | 9 ++++++++- lib/board.js | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3d84d2..f416183 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,14 @@ The way this works is simple (in theory, not in practice). The Arduino listens f ##board -Right now, the board library will attempt to autodiscover the Arduino. I'm going to make it configurable, don't worry. +````javascript +var board = new arduino.Board({ + device: "ACM" +}); +```` +The 'device' wich arduino is attached on. +Here you can set the exact device (ex. ttyACM0 in my case) or the initial part of it (ex ttyACM) +If this parameter is empty the board library will attempt to autodiscover the Arduino by quering every usb device (not the ttyACM*) ````javascript var board = new arduino.Board({ diff --git a/lib/board.js b/lib/board.js index 770d4c8..55f5197 100644 --- a/lib/board.js +++ b/lib/board.js @@ -12,6 +12,7 @@ var events = require('events'), var Board = function (options) { this.log('info', 'initializing'); this.debug = options && options.debug || false; + this.device = options && options.device || 'usb'; this.writeBuffer = []; var self = this; @@ -71,7 +72,7 @@ util.inherits(Board, events.EventEmitter); Board.prototype.detect = function (callback) { this.log('info', 'attempting to find Arduino board'); var self = this; - child.exec('ls /dev | grep usb', function(err, stdout, stderr){ + child.exec('ls /dev | grep '+ this.device, function(err, stdout, stderr){ var usb = stdout.slice(0, -1).split('\n'), found = false, err = null, From 737ef75fc957ca584433360906ea920bfb2cdc54 Mon Sep 17 00:00:00 2001 From: Setola Date: Mon, 3 Sep 2012 00:49:44 +0200 Subject: [PATCH 40/55] little improve in documentation --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f416183..0d1ab31 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,8 @@ var board = new arduino.Board({ }); ```` The 'device' wich arduino is attached on. -Here you can set the exact device (ex. ttyACM0 in my case) or the initial part of it (ex ttyACM) -If this parameter is empty the board library will attempt to autodiscover the Arduino by quering every usb device (not the ttyACM*) +Here you can set the exact device (ex. `ttyACM0` in my case) or the initial part of it (ex `ttyACM`) +If this parameter is empty the board library will attempt to autodiscover the Arduino by quering every usb device (not the `ttyACM*`) ````javascript var board = new arduino.Board({ From 343454df2cc93f217fd2628d3b5d67b457127310 Mon Sep 17 00:00:00 2001 From: Setola Date: Tue, 11 Dec 2012 10:49:04 +0100 Subject: [PATCH 41/55] Added example of configurable port --- examples/adjustable-port.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 examples/adjustable-port.js diff --git a/examples/adjustable-port.js b/examples/adjustable-port.js new file mode 100644 index 0000000..3815493 --- /dev/null +++ b/examples/adjustable-port.js @@ -0,0 +1,15 @@ +var arduino = require('../'); + +var board = new arduino.Board({ + debug: true, + device: "ACM" +}); + +var led = new arduino.Led({ + board: board, + pin: "13" +}); + +board.on('ready', function(){ + led.blink(); +}); \ No newline at end of file From fa229830e7f954458c7472bf27a17a729de94550 Mon Sep 17 00:00:00 2001 From: Setola Date: Tue, 11 Dec 2012 11:01:39 +0100 Subject: [PATCH 42/55] fixed grep syntax error on board auto searching feature --- lib/board.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/board.js b/lib/board.js index 3180d0b..2bef103 100644 --- a/lib/board.js +++ b/lib/board.js @@ -73,7 +73,7 @@ util.inherits(Board, events.EventEmitter); Board.prototype.detect = function (callback) { this.log('info', 'attempting to find Arduino board'); var self = this; - child.exec('ls /dev | grep '+ this.device, function(err, stdout, stderr){ + child.exec('ls /dev | grep "'+ self.device +'"', function(err, stdout, stderr){ var usb = stdout.slice(0, -1).split('\n'), found = false, err = null, @@ -224,4 +224,4 @@ Board.prototype.log = function (/*level, message*/) { } } -module.exports = Board; \ No newline at end of file +module.exports = Board; From 99dc31805d92053aab5aa1e198f32dc3c7a63386 Mon Sep 17 00:00:00 2001 From: Setola Date: Tue, 11 Dec 2012 11:20:39 +0100 Subject: [PATCH 43/55] Documentation for parameter 'device' of the object Board --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0d1ab31..072b4ac 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,11 @@ var board = new arduino.Board({ device: "ACM" }); ```` -The 'device' wich arduino is attached on. -Here you can set the exact device (ex. `ttyACM0` in my case) or the initial part of it (ex `ttyACM`) -If this parameter is empty the board library will attempt to autodiscover the Arduino by quering every usb device (not the `ttyACM*`) +The board library will attempt to autodiscover the Arduino. +The `device` option can be used to set a regex filter that will help the library when scanning for matching devices. +**Note**: the value of this parameter will be used as argument of the grep command + +If this parameter is not provided the board library will attempt to autodiscover the Arduino by quering every device containing 'usb' in its name. ````javascript var board = new arduino.Board({ From 7bdbd9f8f7b97b73f14e8ae5ddf03b3f305eaf90 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Wed, 2 Jan 2013 13:55:10 -0600 Subject: [PATCH 44/55] update readme with stuff found in code --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index f3d84d2..2119e19 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,20 @@ setInterval(function(){ }, 1000); ```` +##ping + +See: + +````javascript +var range = new arduino.Ping({ + board: board +}); + +range.on('read', function () { + console.log("Distance to target (cm)", range.centimeters); +}); +```` + ##servo ````javascript @@ -213,6 +227,8 @@ What is implemented right now: * `02` digitalRead * `03` analogWrite * `04` analogRead +* `97` ping +* `98` servo * `99` debug ##pin From 68268162ab6d29102d6035f8e392a77cb29d83f5 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 11:15:20 -0600 Subject: [PATCH 45/55] fix off by one error initing val/aux buffers --- src/du.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/du.ino b/src/du.ino index 2427435..728da1e 100644 --- a/src/du.ino +++ b/src/du.ino @@ -44,9 +44,9 @@ void process() { aux[3] = '\0'; } else { strncpy(val, messageBuffer + 4, 3); - val[4] = '\0'; + val[3] = '\0'; strncpy(aux, messageBuffer + 7, 3); - aux[4] = '\0'; + aux[3] = '\0'; } if (debug) { From d61ef40b5ab5b5167dc0c0f575dc7ee573351588 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 12:50:09 -0600 Subject: [PATCH 46/55] =?UTF-8?q?first=20go=20at=20handling=20commands=20d?= =?UTF-8?q?evice-side=20=E2=80=94=20this=20really=20won't=20work=20due=20t?= =?UTF-8?q?o=20text-based=20framing=20protocol=20(print=20and=20createChar?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/du.ino | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/du.ino b/src/du.ino index 728da1e..e4a2ab4 100644 --- a/src/du.ino +++ b/src/du.ino @@ -1,4 +1,5 @@ #include +#include bool debug = false; @@ -65,6 +66,7 @@ void process() { case 2: dr(pin,val); break; case 3: aw(pin,val); break; case 4: ar(pin,val); break; + case 89: handleLCD(messageBuffer); break; case 97: handlePing(pin,val,aux); break; case 98: handleServo(pin,val,aux); break; case 99: toggleDebug(val); break; @@ -171,6 +173,101 @@ int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error return ret; } +/* + * Handle LiquidCrystal commands + * + */ +void handleLCD(char *messageBuffer) { + static LiquidCrystal *lcd = NULL; + + uint8_t *msg = (uint8_t *)messageBuffer; + uint8_t cmd = msg[0]; + if (cmd && !lcd) { if(debug) Serial.println("notready"); return; } + + // 0 init + if (cmd == 0) { + int p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11; + p00 = msg[1] >> 4; + if (!p00) lcd = new LiquidCrystal(12, 11, 5, 4, 3, 2); + else { + p01 = msg[1] & 0xF; + p02 = msg[2] >> 4; + p03 = msg[2] & 0xF; + p04 = msg[3] >> 4; + p05 = msg[3] & 0xF; + p06 = msg[4] >> 4; + if (!p06) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05); + else { + p07 = msg[4] & 0xF; + if (!p07) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06); + else { + p08 = msg[5] >> 4; + p09 = msg[5] & 0xF; + p10 = msg[6] >> 4; + //p11 = msg[6] & 0xF; // extra + if (!p10) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06, p07, p08, p09); + else lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, p10); + } + } + } + + // 1 begin + } else if (cmd == 1) { + lcd->begin(msg[1], msg[2]); + + // 2 clear + } else if (cmd == 2) { + lcd->clear(); + + // 3 home + } else if (cmd == 3) { + lcd->home(); + + // 4 setCursor + } else if (cmd == 4) { + lcd->setCursor(atoi(val), atoi(aux)); + + // 5 write + } else if (cmd == 5) { + char writeBuffer[7]; + strncpy(writeBuffer, val, 3); + strncpy(writeBuffer, aux, 3); + writeBuffer[6] = '\0'; + lcd->write(writeBuffer); + + // 6 cursor on/off + } else if (cmd == 6) { + if (val[1] == 'n') lcd->cursor(); + else lcd->noCursor(); + + // 7 blink on/off + } else if (cmd == 7) { + if (val[1] == 'n') lcd->blink(); + else lcd->noBlink(); + + // 8 display on/off + } else if (cmd == 8) { + if (val[1] == 'n') lcd->display(); + else lcd->noDisplay(); + + // 9 scroll left/right, autoscroll on/off + } else if (cmd == 9) { + if (val[0] == 'l') lcd->scrollDisplayLeft(); + else if (val[0] == 'r') lcd->scrollDisplayRight(); + else if (val[1] == 'n') lcd->autoscroll(); + else lcd->noAutoscroll(); + + // A text and autoscroll ltr/rtl + } else if (cmd == 'A') { + if (val[0] == 'r') lcd->rightToLeft(); + else lcd->leftToRight(); + + // B createChar + } else if (cmd == 'B') { + lcd->createChar(msg[1], msg+2); // TDB: need 8 byte aux! + } +} + /* * Handle Ping commands * fire, read From 00912978f1ed80d413e3220dd1c55e19af01ad7c Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 12:50:16 -0600 Subject: [PATCH 47/55] =?UTF-8?q?Revert=20"first=20go=20at=20handling=20co?= =?UTF-8?q?mmands=20device-side=20=E2=80=94=20this=20really=20won't=20work?= =?UTF-8?q?=20due=20to=20text-based=20framing=20protocol=20(print=20and=20?= =?UTF-8?q?createChar)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d61ef40b5ab5b5167dc0c0f575dc7ee573351588. --- src/du.ino | 97 ------------------------------------------------------ 1 file changed, 97 deletions(-) diff --git a/src/du.ino b/src/du.ino index e4a2ab4..728da1e 100644 --- a/src/du.ino +++ b/src/du.ino @@ -1,5 +1,4 @@ #include -#include bool debug = false; @@ -66,7 +65,6 @@ void process() { case 2: dr(pin,val); break; case 3: aw(pin,val); break; case 4: ar(pin,val); break; - case 89: handleLCD(messageBuffer); break; case 97: handlePing(pin,val,aux); break; case 98: handleServo(pin,val,aux); break; case 99: toggleDebug(val); break; @@ -173,101 +171,6 @@ int getPin(char *pin) { //Converts to A0-A5, and returns -1 on error return ret; } -/* - * Handle LiquidCrystal commands - * - */ -void handleLCD(char *messageBuffer) { - static LiquidCrystal *lcd = NULL; - - uint8_t *msg = (uint8_t *)messageBuffer; - uint8_t cmd = msg[0]; - if (cmd && !lcd) { if(debug) Serial.println("notready"); return; } - - // 0 init - if (cmd == 0) { - int p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, p10, p11; - p00 = msg[1] >> 4; - if (!p00) lcd = new LiquidCrystal(12, 11, 5, 4, 3, 2); - else { - p01 = msg[1] & 0xF; - p02 = msg[2] >> 4; - p03 = msg[2] & 0xF; - p04 = msg[3] >> 4; - p05 = msg[3] & 0xF; - p06 = msg[4] >> 4; - if (!p06) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05); - else { - p07 = msg[4] & 0xF; - if (!p07) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06); - else { - p08 = msg[5] >> 4; - p09 = msg[5] & 0xF; - p10 = msg[6] >> 4; - //p11 = msg[6] & 0xF; // extra - if (!p10) lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06, p07, p08, p09); - else lcd = new LiquidCrystal(p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, p10); - } - } - } - - // 1 begin - } else if (cmd == 1) { - lcd->begin(msg[1], msg[2]); - - // 2 clear - } else if (cmd == 2) { - lcd->clear(); - - // 3 home - } else if (cmd == 3) { - lcd->home(); - - // 4 setCursor - } else if (cmd == 4) { - lcd->setCursor(atoi(val), atoi(aux)); - - // 5 write - } else if (cmd == 5) { - char writeBuffer[7]; - strncpy(writeBuffer, val, 3); - strncpy(writeBuffer, aux, 3); - writeBuffer[6] = '\0'; - lcd->write(writeBuffer); - - // 6 cursor on/off - } else if (cmd == 6) { - if (val[1] == 'n') lcd->cursor(); - else lcd->noCursor(); - - // 7 blink on/off - } else if (cmd == 7) { - if (val[1] == 'n') lcd->blink(); - else lcd->noBlink(); - - // 8 display on/off - } else if (cmd == 8) { - if (val[1] == 'n') lcd->display(); - else lcd->noDisplay(); - - // 9 scroll left/right, autoscroll on/off - } else if (cmd == 9) { - if (val[0] == 'l') lcd->scrollDisplayLeft(); - else if (val[0] == 'r') lcd->scrollDisplayRight(); - else if (val[1] == 'n') lcd->autoscroll(); - else lcd->noAutoscroll(); - - // A text and autoscroll ltr/rtl - } else if (cmd == 'A') { - if (val[0] == 'r') lcd->rightToLeft(); - else lcd->leftToRight(); - - // B createChar - } else if (cmd == 'B') { - lcd->createChar(msg[1], msg+2); // TDB: need 8 byte aux! - } -} - /* * Handle Ping commands * fire, read From b337ee3920cbf697ebeb9dbd6d4eb820d8314696 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 21:37:34 -0600 Subject: [PATCH 48/55] (not working) partial port of LiquidCrystal.cpp --- index.js | 3 +- lib/lcd.js | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 lib/lcd.js diff --git a/index.js b/index.js index a30f8f9..3c55f8c 100644 --- a/index.js +++ b/index.js @@ -7,5 +7,6 @@ module.exports = { Servo: require('./lib/servo'), Sensor: require('./lib/sensor'), Ping: require('./lib/ping'), - PIR: require('./lib/pir') + PIR: require('./lib/pir'), + LCD: require('./lib/lcd') }; diff --git a/lib/lcd.js b/lib/lcd.js new file mode 100644 index 0000000..8352d73 --- /dev/null +++ b/lib/lcd.js @@ -0,0 +1,195 @@ +// port of LiquidCrystal.cpp by natevw + + +// commands +LCD_CLEARDISPLAY = 0x01; +LCD_RETURNHOME = 0x02; +LCD_ENTRYMODESET = 0x04; +LCD_DISPLAYCONTROL = 0x08; +LCD_CURSORSHIFT = 0x10; +LCD_FUNCTIONSET = 0x20; +LCD_SETCGRAMADDR = 0x40; +LCD_SETDDRAMADDR = 0x80; + +// flags for display entry mode +LCD_ENTRYRIGHT = 0x00; +LCD_ENTRYLEFT = 0x02; +LCD_ENTRYSHIFTINCREMENT = 0x01; +LCD_ENTRYSHIFTDECREMENT = 0x00; + +// flags for display on/off control +LCD_DISPLAYON = 0x04; +LCD_DISPLAYOFF = 0x00; +LCD_CURSORON = 0x02; +LCD_CURSOROFF = 0x00; +LCD_BLINKON = 0x01; +LCD_BLINKOFF = 0x00; + +// flags for display/cursor shift +LCD_DISPLAYMOVE = 0x08; +LCD_CURSORMOVE = 0x00; +LCD_MOVERIGHT = 0x04; +LCD_MOVELEFT = 0x00; + +// flags for function set +LCD_8BITMODE = 0x10; +LCD_4BITMODE = 0x00; +LCD_2LINE = 0x08; +LCD_1LINE = 0x00; +LCD_5x10DOTS = 0x04; +LCD_5x8DOTS = 0x00; + + + +var LCD = function (options) { + if (!options || !options.board) throw new Error('Must supply required options'); + this.board = options.board; + + var pins = options.pins || [12, 11, 5, 4, 3, 2]; + if (!Array.isArray(pins)) + this.pins = pins; + else if (pins.length % 2) + this.pins = {rs:pins[0], rw:pins[1], e:pins[2], data:pins.slice(3)}; + else + this.pins = {rs:pins[0], rw:255, e:pins[1], data:pins.slice(2)}; + + this.board.pinMode(this.pins.rs, 'out'); + if (this.pins.rw !== 255) { + this.board.pinMode(this.pins.rw, 'out'); + } + this.board.pinMode(this.pins.e, 'out'); + + this.begin(16, 1); + console.log(this); +} + +LCD.prototype.begin = function (cols, lines, dotsize) { + this._numlines = lines; + + var functionFlags = 0; + functionFlags |= (lines > 1) ? LCD_2LINE : LCD_1LINE; + functionFlags |= (dotsize && lines === 1) ? LCD_5x10DOTS : LCD_5x8DOTS; + + this._delayMicroseconds(50000); + this.board.digitalWrite(this.pins.rs, this.board.LOW); + this.board.digitalWrite(this.pins.e, this.board.LOW); + if (this.pins.rw !== 255) + this.board.digitalWrite(this.pins.rw, this.board.LOW); + + // put the LCD into 4 bit or 8 bit mode + if (this.pins.data.length === 4) { + functionFlags |= LCD_4BITMODE; + this._writeNbits(4, 0x03); + this._delayMicroseconds(4500); + this._writeNbits(4, 0x03); + this._delayMicroseconds(4500); + this._writeNbits(4, 0x03); + this._delayMicroseconds(150); + this._writeNbits(4, 0x02); + } else { + functionFlags |= LCD_8BITMODE; + this.command(LCD_FUNCTIONSET | functionFlags); + this._delayMicroseconds(4500); + this.command(LCD_FUNCTIONSET | functionFlags); + this._delayMicroseconds(150); + this.command(LCD_FUNCTIONSET | functionFlags); + } + + this.command(LCD_FUNCTIONSET | functionFlags); + + this._displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + this.display(); + + this.clear(); + + this._displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + this.leftToRight(); +} + + +LCD.prototype.display = function (on) { + on = (arguments.length) ? true : on; + if (on) this._displaycontrol = LCD_DISPLAYON + else this._displaycontrol &= ~LCD_DISPLAYON; + this.command(LCD_DISPLAYCONTROL | this._displaycontrol); +} + +LCD.prototype.noDisplay = function () { this.display(false); } + +LCD.prototype.clear = function () { + this.command(LCD_CLEARDISPLAY); + this._delayMicroseconds(2000); // this command takes a long time! +} + +LCD.prototype.leftToRight = function () { + this._displaymode |= LCD_ENTRYLEFT; + this.command(LCD_ENTRYMODESET | this._displaymode); +} + +LCD.prototype.rightToLeft = function () { + this._displaymode &= ~LCD_ENTRYLEFT; + this.command(LCD_ENTRYMODESET | this._displaymode); +} + +LCD.prototype.setCursor = function (col, row) { + if (row >= this._numlines) { + row = this._numlines - 1; + } + + var row_offsets = [0x00, 0x40, 0x14, 0x54]; + this.command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} + + +LCD.prototype.print = LCD.prototype.write = function (str) { + // TODO: map misc Unicode chars to typical LCD charset? + for (var i = 0, len = str.length; i < len; i++) + this.send(str.charCodeAt(i), this.board.HIGH); +} + + +/* + * mid/low level stuff + */ + +LCD.prototype.command = function (value) { + this.send(value, this.board.LOW); +} + +LCD.prototype.send = function (value, mode) { + this.board.digitalWrite(this.pins.rs, mode); + if (this.pins.rw !== 255) { + this.board.digitalWrite(this.pins.rw, this.board.LOW); + } + if (this.pins.data.length === 8) { + this._writeNbits(8, value); + } else { + this._writeNbits(4, value >> 4); + this._writeNbits(4, value & 0xF); + } +} + +LCD.prototype._writeNbits = function (n, value) { + for (var i = 0; i < n; i++) { + this.board.pinMode(this.pins.data[i], 'out'); + var bit = (value >> i) & 0x01; + this.board.digitalWrite(this.pins.data[i], (bit) ? this.board.HIGH : this.board.LOW); + } + this._pulseEnable(); +} + +LCD.prototype._pulseEnable = function () { + this.board.digitalWrite(this.pins.e, this.board.LOW); + this._delayMicroseconds(1); + this.board.digitalWrite(this.pins.e, this.board.HIGH); + this._delayMicroseconds(1); // enable pulse must be >450ns + this.board.digitalWrite(this.pins.e, this.board.LOW); + this._delayMicroseconds(100); // commands need > 37us to settle +} + +LCD.prototype._delayMicroseconds = function (us) { + console.log('delay', us); + this.board.delay(us/1000); +} + +module.exports = LCD; \ No newline at end of file From 88441b0b13548547569c004da3d8cb76d2d1c028 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 21:59:50 -0600 Subject: [PATCH 49/55] fix some issues, including swapped display flag that was the main trouble --- lib/lcd.js | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/lcd.js b/lib/lcd.js index 8352d73..8515738 100644 --- a/lib/lcd.js +++ b/lib/lcd.js @@ -60,15 +60,14 @@ var LCD = function (options) { this.board.pinMode(this.pins.e, 'out'); this.begin(16, 1); - console.log(this); } LCD.prototype.begin = function (cols, lines, dotsize) { this._numlines = lines; - var functionFlags = 0; - functionFlags |= (lines > 1) ? LCD_2LINE : LCD_1LINE; - functionFlags |= (dotsize && lines === 1) ? LCD_5x10DOTS : LCD_5x8DOTS; + var displayfunction = 0; + displayfunction |= (lines > 1) ? LCD_2LINE : LCD_1LINE; + displayfunction |= (dotsize && lines === 1) ? LCD_5x10DOTS : LCD_5x8DOTS; this._delayMicroseconds(50000); this.board.digitalWrite(this.pins.rs, this.board.LOW); @@ -78,7 +77,7 @@ LCD.prototype.begin = function (cols, lines, dotsize) { // put the LCD into 4 bit or 8 bit mode if (this.pins.data.length === 4) { - functionFlags |= LCD_4BITMODE; + displayfunction |= LCD_4BITMODE; this._writeNbits(4, 0x03); this._delayMicroseconds(4500); this._writeNbits(4, 0x03); @@ -87,15 +86,15 @@ LCD.prototype.begin = function (cols, lines, dotsize) { this._delayMicroseconds(150); this._writeNbits(4, 0x02); } else { - functionFlags |= LCD_8BITMODE; - this.command(LCD_FUNCTIONSET | functionFlags); + displayfunction |= LCD_8BITMODE; + this.command(LCD_FUNCTIONSET | displayfunction); this._delayMicroseconds(4500); - this.command(LCD_FUNCTIONSET | functionFlags); + this.command(LCD_FUNCTIONSET | displayfunction); this._delayMicroseconds(150); - this.command(LCD_FUNCTIONSET | functionFlags); + this.command(LCD_FUNCTIONSET | displayfunction); } - this.command(LCD_FUNCTIONSET | functionFlags); + this.command(LCD_FUNCTIONSET | displayfunction); this._displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; this.display(); @@ -108,14 +107,33 @@ LCD.prototype.begin = function (cols, lines, dotsize) { LCD.prototype.display = function (on) { - on = (arguments.length) ? true : on; - if (on) this._displaycontrol = LCD_DISPLAYON + on = (arguments.length) ? on : true; + if (on) this._displaycontrol |= LCD_DISPLAYON else this._displaycontrol &= ~LCD_DISPLAYON; this.command(LCD_DISPLAYCONTROL | this._displaycontrol); } LCD.prototype.noDisplay = function () { this.display(false); } +LCD.prototype.cursor = function (on) { + on = (arguments.length) ? on : true; + if (on) this._displaycontrol |= LCD_CURSORON + else this._displaycontrol &= ~LCD_CURSORON; + this.command(LCD_DISPLAYCONTROL | this._displaycontrol); +} + +LCD.prototype.noCursor = function () { this.cursor(false); } + +LCD.prototype.blink = function (on) { + on = (arguments.length) ? on : true; + if (on) this._displaycontrol |= LCD_BLINKON + else this._displaycontrol &= ~LCD_BLINKON; + this.command(LCD_DISPLAYCONTROL | this._displaycontrol); +} + +LCD.prototype.noBlink = function () { this.blink(false); } + + LCD.prototype.clear = function () { this.command(LCD_CLEARDISPLAY); this._delayMicroseconds(2000); // this command takes a long time! @@ -188,7 +206,6 @@ LCD.prototype._pulseEnable = function () { } LCD.prototype._delayMicroseconds = function (us) { - console.log('delay', us); this.board.delay(us/1000); } From 3c5df29451227c213bddd7de8893e33e3c86b4ae Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Thu, 3 Jan 2013 23:08:54 -0600 Subject: [PATCH 50/55] fill in most remaining methods --- lib/lcd.js | 51 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/lcd.js b/lib/lcd.js index 8515738..2341968 100644 --- a/lib/lcd.js +++ b/lib/lcd.js @@ -105,6 +105,24 @@ LCD.prototype.begin = function (cols, lines, dotsize) { this.leftToRight(); } +LCD.prototype.clear = function () { + this.command(LCD_CLEARDISPLAY); + this._delayMicroseconds(2000); // this command takes a long time! +} + +LCD.prototype.home = function () { + this.command(LCD_RETURNHOME); + this._delayMicroseconds(2000); +} + +LCD.prototype.setCursor = function (col, row) { + if (row >= this._numlines) { + row = this._numlines - 1; + } + + var row_offsets = [0x00, 0x40, 0x14, 0x54]; + this.command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +} LCD.prototype.display = function (on) { on = (arguments.length) ? on : true; @@ -133,12 +151,15 @@ LCD.prototype.blink = function (on) { LCD.prototype.noBlink = function () { this.blink(false); } +LCD.prototype.scrollDisplayLeft = function () { + this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +} -LCD.prototype.clear = function () { - this.command(LCD_CLEARDISPLAY); - this._delayMicroseconds(2000); // this command takes a long time! +LCD.prototype.scrollDisplayRight = function () { + this.command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); } + LCD.prototype.leftToRight = function () { this._displaymode |= LCD_ENTRYLEFT; this.command(LCD_ENTRYMODESET | this._displaymode); @@ -149,17 +170,25 @@ LCD.prototype.rightToLeft = function () { this.command(LCD_ENTRYMODESET | this._displaymode); } -LCD.prototype.setCursor = function (col, row) { - if (row >= this._numlines) { - row = this._numlines - 1; - } - - var row_offsets = [0x00, 0x40, 0x14, 0x54]; - this.command(LCD_SETDDRAMADDR | (col + row_offsets[row])); +LCD.prototype.autoscroll = function (on) { + on = (arguments.length) ? on : true; + if (on) this._displaymode |= LCD_ENTRYSHIFTINCREMENT + else this._displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + this.command(LCD_ENTRYMODESET | this._displaymode); } +LCD.prototype.noAutoscroll = function () { this.autoscroll(false); } + +// TODO: finish this up (make .write handle buffer instead of string?) +LCD.prototype.createCharTODO = function (location, charmap) { + location &= 0x7; + this.command(LCD_SETCGRAMADDR | (location << 3)); + for (var i = 0; i < 8; i++) { + this.write(charmap[i]); + } +} -LCD.prototype.print = LCD.prototype.write = function (str) { +LCD.prototype.write = LCD.prototype.print = function (str) { // TODO: map misc Unicode chars to typical LCD charset? for (var i = 0, len = str.length; i < len; i++) this.send(str.charCodeAt(i), this.board.HIGH); From e4f05ca749b832676b8e50e5f9dc52d361930696 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Fri, 4 Jan 2013 00:37:45 -0600 Subject: [PATCH 51/55] implement createChar (with helper options) and fix `write(int)` --- lib/lcd.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/lcd.js b/lib/lcd.js index 2341968..e18b527 100644 --- a/lib/lcd.js +++ b/lib/lcd.js @@ -179,19 +179,31 @@ LCD.prototype.autoscroll = function (on) { LCD.prototype.noAutoscroll = function () { this.autoscroll(false); } -// TODO: finish this up (make .write handle buffer instead of string?) -LCD.prototype.createCharTODO = function (location, charmap) { +LCD.prototype.createChar = function (location, charmap) { location &= 0x7; this.command(LCD_SETCGRAMADDR | (location << 3)); - for (var i = 0; i < 8; i++) { - this.write(charmap[i]); - } + + var buffer = new Buffer(8); + if (Array.isArray(charmap)) for (var i = 0; i < 8; i++) { + buffer[i] = parseInt(charmap[i], 2); + } else if (typeof charmap === 'string') for (var i = 0; i < 8; i++) { + var byte = 0; + if (charmap[5*i + 0] !== ' ') byte |= 0x10; + if (charmap[5*i + 1] !== ' ') byte |= 0x08; + if (charmap[5*i + 2] !== ' ') byte |= 0x04; + if (charmap[5*i + 3] !== ' ') byte |= 0x02; + if (charmap[5*i + 4] !== ' ') byte |= 0x01; + buffer[i] = byte; + } else buffer = charmap; + this.write(buffer); } LCD.prototype.write = LCD.prototype.print = function (str) { - // TODO: map misc Unicode chars to typical LCD charset? - for (var i = 0, len = str.length; i < len; i++) - this.send(str.charCodeAt(i), this.board.HIGH); + // TODO: map misc Unicode chars to typical LCD extended charset? + var bytes = (typeof str === 'string') ? new Buffer(str, 'ascii') : + (typeof str === 'object') ? str : new Buffer([str]); + for (var i = 0, len = bytes.length; i < len; i++) + this.send(bytes[i], this.board.HIGH); } From da3b074328124b72cc9ef5fe3599aa93a6e5b915 Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Fri, 4 Jan 2013 10:58:06 -0600 Subject: [PATCH 52/55] allow options.pins to leave out .rw --- lib/lcd.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/lcd.js b/lib/lcd.js index e18b527..d9692ce 100644 --- a/lib/lcd.js +++ b/lib/lcd.js @@ -51,7 +51,8 @@ var LCD = function (options) { else if (pins.length % 2) this.pins = {rs:pins[0], rw:pins[1], e:pins[2], data:pins.slice(3)}; else - this.pins = {rs:pins[0], rw:255, e:pins[1], data:pins.slice(2)}; + this.pins = {rs:pins[0], e:pins[1], data:pins.slice(2)}; + if (!('rw' in this.pins)) this.pins.rw = 255; this.board.pinMode(this.pins.rs, 'out'); if (this.pins.rw !== 255) { From 7d7ef3c6bda009d7c044ace218d5cb29aa4284af Mon Sep 17 00:00:00 2001 From: Nathan Vander Wilt Date: Fri, 4 Jan 2013 10:59:45 -0600 Subject: [PATCH 53/55] add documentation and rev version for LCD work (sponsored by &yet) --- README.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 ++++-- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2119e19..98194fa 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,67 @@ Fade the to full brightness then back to minimal brightness in `interval` ms. De Current brightness of the LED +##lcd + +This is a port of the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal) into JavaScript. Note that communicating with the LCD requires use of the synchronous `board.delay()` busy loop which will block other node.js events from being processed for several milliseconds at a time. (This could be converted to pause a board-level buffered message queue instead.) + +````javascript +var lcd = new d.LCD({ + board: board, + pins: {rs:12, rw:11, e:10, data:[5, 4, 3, 2]} +}); +lcd.begin(16, 2); +lcd.print("Hello Internet."); +```` + +In `options`, the "pins" field can either be an array matching a call to any of the [LiquidCrystal constructors](http://arduino.cc/en/Reference/LiquidCrystalConstructor) or an object with "rs", "rw" (optional), "e" and a 4- or 8-long array of "data" pins. Pins will default to `[12, 11, 5, 4, 3, 2]` if not provided. + +###lcd.begin(), lcd.clear(), lcd.home(), lcd.setCursor(), lcd.scrollDisplayLeft(), lcd.scrollDisplayRight() + +These should behave the same as their counterparts in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal). + +###lcd.display(on), lcd.cursor(on), lcd.blink(on), lcd.autoscroll(on) + +These are similar to the methods in the [LiquidCrystal library](http://arduino.cc/en/Reference/LiquidCrystal), however they can take an optional boolean parameter. If true or not provided, the setting is enabled. If false, the setting is disabled. For compatibility `.noDisplay()`, `.noCursor()`, `.noBlink()` and `.noAutoscroll()` methods are provided as well. + +###lcd.write(val), lcd.print(val) + +These take a buffer, string or integer and send it to the display. The `.write` and `print` methods are equivalent, aliases to the same function. + +###lcd.createChar(location, charmap) + +Configures a custom character for code `location` (numbers 0–7). `charmap` can be a 40-byte buffer as in [the C++ method](http://arduino.cc/en/Reference/LiquidCrystalCreateChar), or an array of 5-bit binary strings, or a 40-character string with pixels denoted by any non-space (`' '`) character. These bits determine the 5x8 pixel pattern of the custom character. + +````javascript +var square = new Buffer("1f1f1f1f1f1f1f1f", 'hex'); + +var smiley = [ + '00000', + '10001', + '00000', + '00000', + '10001', + '01110', + '00000' +]; + +var random = + ". .." + + " . . " + + ". . ." + + " . . " + + " .. " + + ". . " + + " . ." + + ".. .." ; + +lcd.createChar(0, square); +lcd.createChar(1, smiley); +lcd.createChar(2, random); +lcd.setCursor(5,2); +lcd.print(new Buffer("\0\1\2\1\0")); // NOTE: when `.print`ing a string, 'ascii' turns \0 into a space +```` + ##piezo ````javascript diff --git a/package.json b/package.json index 7c7b79b..b8a2116 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,13 @@ "contributors": [ { "name": "Rick Waldron", "email": "waldron.rick@gmail.com" }, { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, - { "name": "Seiya Konno", "email": "nulltask@gmail.com" } + { "name": "Seiya Konno", "email": "nulltask@gmail.com" }, + { "name": "Nathan Vander Wilt", "email": "nate@calftrail.com" }, + { "name": "Adam Brault (&yet)", "email": "contact@andyet.com" } ], "name": "duino", "description": "Arduino framework for mad scientists", - "version": "0.0.7", + "version": "0.0.8", "keywords": [ "arduino", "serial", From b4c7610c6598ad1afd335f6e74c36165954d7186 Mon Sep 17 00:00:00 2001 From: Cam Pedersen Date: Wed, 24 Jul 2013 13:55:20 -0500 Subject: [PATCH 54/55] bump version to 0.0.9 --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b8a2116..546ec97 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,12 @@ { "name": "Leonhardt Wille", "email": "wille@riverlabs.de" }, { "name": "Seiya Konno", "email": "nulltask@gmail.com" }, { "name": "Nathan Vander Wilt", "email": "nate@calftrail.com" }, - { "name": "Adam Brault (&yet)", "email": "contact@andyet.com" } + { "name": "Adam Brault (&yet)", "email": "contact@andyet.com" }, + { "name": "Emanuele Tessore", "email": "setola@gmail.com" } ], "name": "duino", "description": "Arduino framework for mad scientists", - "version": "0.0.8", + "version": "0.0.9", "keywords": [ "arduino", "serial", From 05bd409d92729637b52073f15f0f5ceb2d677f3d Mon Sep 17 00:00:00 2001 From: Pi-Uno Date: Mon, 14 Apr 2014 16:19:58 +0000 Subject: [PATCH 55/55] board.js updated to allow Raspberry Pi 'Arduino board' serial ports to be found --- lib/board.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/board.js b/lib/board.js index 2bef103..0901827 100644 --- a/lib/board.js +++ b/lib/board.js @@ -12,7 +12,7 @@ var events = require('events'), var Board = function (options) { this.log('info', 'initializing'); this.debug = options && options.debug || false; - this.device = options && options.device || 'usb'; + this.device = options && options.device || 'usb|ttyACM*|ttyS0'; this.baudrate = options && options.baudrate || 115200; this.writeBuffer = []; @@ -73,7 +73,7 @@ util.inherits(Board, events.EventEmitter); Board.prototype.detect = function (callback) { this.log('info', 'attempting to find Arduino board'); var self = this; - child.exec('ls /dev | grep "'+ self.device +'"', function(err, stdout, stderr){ + child.exec('ls /dev | grep -E "'+ self.device +'"', function(err, stdout, stderr){ var usb = stdout.slice(0, -1).split('\n'), found = false, err = null,