Merge branch 'master' into literate

* master:
  Crazyflies
  Updated servo examples to use a limit range of motion instead of full 180.
  Update digital read to parseInt buffer response.
  DigitalRead buffer data converted to string now.
  Debugging digitalPin read.
  Added servo example for Raspi.
  Add more supported devices to README
  Update to 0.6.1
  Update digital pin close callback param.
  Fixes err param not being passed.
  Updated digital pin and added pwm raspi example.

Conflicts:
	examples/servo.coffee
This commit is contained in:
Andrew Stewart 2013-11-28 12:07:51 -08:00
commit 2c52db8086
10 changed files with 125 additions and 44 deletions

View File

@ -77,7 +77,9 @@ Cylon.js has a extensible system for connecting to hardware devices. The followi
- [Ardrone](http://ardrone2.parrot.com/) <==> [Adaptor/Drivers](https://github.com/hybridgroup/cylon-ardrone) - [Ardrone](http://ardrone2.parrot.com/) <==> [Adaptor/Drivers](https://github.com/hybridgroup/cylon-ardrone)
- [Arduino](http://www.arduino.cc/) <==> [Adaptor](https://github.com/hybridgroup/cylon-firmata) - [Arduino](http://www.arduino.cc/) <==> [Adaptor](https://github.com/hybridgroup/cylon-firmata)
- [Crazyflie](http://www.bitcraze.se/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-crazyflie)
- [Leap Motion](https://www.leapmotion.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-leapmotion) - [Leap Motion](https://www.leapmotion.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-leapmotion)
- [Pebble](http://www.getpebble.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-pebble)
- [Raspberry Pi](http://www.raspberrypi.org/) <==> [Adaptor](https://github.com/hybridgroup/cylon-raspi) - [Raspberry Pi](http://www.raspberrypi.org/) <==> [Adaptor](https://github.com/hybridgroup/cylon-raspi)
- [Salesforce](http://www.force.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-force) - [Salesforce](http://www.force.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-force)
- [Sphero](http://www.gosphero.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-sphero) - [Sphero](http://www.gosphero.com/) <==> [Adaptor/Driver](https://github.com/hybridgroup/cylon-sphero)
@ -86,11 +88,19 @@ Support for many devices that use General Purpose Input/Output (GPIO) have
a shared set of drivers provded using the cylon-gpio module: a shared set of drivers provded using the cylon-gpio module:
- [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/cylon-gpio) - [GPIO](https://en.wikipedia.org/wiki/General_Purpose_Input/Output) <=> [Drivers](https://github.com/hybridgroup/cylon-gpio)
- Analog Sensor
- Button
- LED
- Motor
- Maxbotix Ultrasonic Range Finder
- Servo
Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of Support for devices that use Inter-Integrated Circuit (I2C) have a shared set of
drivers provded using the cylon-i2c module: drivers provded using the cylon-i2c module:
- [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/cylon-i2c) - [I2C](https://en.wikipedia.org/wiki/I%C2%B2C) <=> [Drivers](https://github.com/hybridgroup/cylon-i2c)
- BlinkM
- HMC6352 Digital Compass
More platforms and drivers are coming soon... More platforms and drivers are coming soon...

12
dist/digital-pin.js vendored
View File

@ -62,7 +62,7 @@
DigitalPin.prototype.close = function() { DigitalPin.prototype.close = function() {
var _this = this; var _this = this;
return FS.writeFile(this._unexportPath(), "" + this.pinNum, function(err) { return FS.writeFile(this._unexportPath(), "" + this.pinNum, function(err) {
return _this._closeCallback(); return _this._closeCallback(err);
}); });
}; };
@ -77,13 +77,14 @@
this._setMode('w'); this._setMode('w');
} }
this.status = value === 1 ? 'high' : 'low'; this.status = value === 1 ? 'high' : 'low';
return FS.writeFile(this._valuePath(), value, function(err) { FS.writeFile(this._valuePath(), value, function(err) {
if (err) { if (err) {
return _this.emit('error', "Error occurred while writing value " + value + " to pin " + _this.pinNum); return _this.emit('error', "Error occurred while writing value " + value + " to pin " + _this.pinNum);
} else { } else {
return _this.emit('digitalWrite', value); return _this.emit('digitalWrite', value);
} }
}); });
return value;
}; };
DigitalPin.prototype.digitalRead = function(interval) { DigitalPin.prototype.digitalRead = function(interval) {
@ -93,16 +94,17 @@
this._setMode('r'); this._setMode('r');
} }
readData = null; readData = null;
return setInterval(function() { setInterval(function() {
return FS.readFile(_this._valuePath(), function(err, data) { return FS.readFile(_this._valuePath(), function(err, data) {
if (err) { if (err) {
return _this.emit('error', "Error occurred while reading from pin " + _this.pinNum); return _this.emit('error', "Error occurred while reading from pin " + _this.pinNum);
} else { } else {
readData = data; readData = parseInt(data.toString());
return _this.emit('digitalRead', data); return _this.emit('digitalRead', readData);
} }
}); });
}, interval); }, interval);
return true;
}; };
DigitalPin.prototype.setHigh = function() { DigitalPin.prototype.setHigh = function() {

19
examples/crazyflie.coffee Normal file
View File

@ -0,0 +1,19 @@
Cylon = require '..'
Cylon.robot
connection:
name: 'crazyflie', adaptor: 'crazyflie', port: "radio://1/10/250KPS"
device:
name: 'drone', driver: 'crazyflie'
work: (my) ->
#my.drone.setParam('flightmode.althold', true)
my.drone.on 'start', ->
my.drone.takeoff()
after 10.seconds(), ->
my.drone.land()
after 15.seconds(), ->
my.drone.stop()
.start()

View File

@ -0,0 +1,20 @@
Cylon = require('..')
# Initialize the robot
Cylon.robot
connection:
name: 'raspi', adaptor: 'raspi', port: '/dev/ttyACM0'
device:
name: 'led', driver: 'led', pin: 11
work: (my) ->
# we do our thing here
brightness = 0
fade = 5
every 0.05.seconds(), ->
brightness += fade
my.led.brightness(brightness)
fade = -fade if (brightness is 0) or (brightness is 255)
.start()

View File

@ -0,0 +1,22 @@
Cylon = require('..')
# Initialize the robot
Cylon.robot
connection:
name: 'raspi', adaptor: 'raspi', port: '/dev/ttyACM0'
device:
name: 'servo', driver: 'servo', pin: 11
work: (my) ->
# we do our thing here
work: (my) ->
angle = 30
increment = 40
every 1.seconds(), ->
angle += increment
my.servo.angle(angle)
console.log("Current Angle => #{ my.servo.currentAngle() }")
increment = -increment if (angle is 30) or (angle is 150)
.start()

View File

@ -5,8 +5,8 @@ Cylon.robot
device: { name: 'servo', driver: 'servo', pin: 3 } device: { name: 'servo', driver: 'servo', pin: 3 }
work: (my) -> work: (my) ->
angle = 0 angle = 30
increment = 90 increment = 40
every 1.seconds(), -> every 1.seconds(), ->
angle += increment angle += increment
@ -14,6 +14,6 @@ Cylon.robot
Logger.info "Current Angle: #{my.servo.currentAngle()}" Logger.info "Current Angle: #{my.servo.currentAngle()}"
increment = -increment if (angle is 0) or (angle is 180) increment = -increment if (angle is 30) or (angle is 150)
.start() .start()

View File

@ -5,8 +5,8 @@ Cylon.robot({
device: { name: 'servo', driver: 'servo', pin: 3 }, device: { name: 'servo', driver: 'servo', pin: 3 },
work: function(my) { work: function(my) {
var angle = 0; var angle = 30;
var increment = 90; var increment = 40;
every(1..seconds(), function() { every(1..seconds(), function() {
angle += increment; angle += increment;
@ -14,7 +14,7 @@ Cylon.robot({
Logger.info("Current Angle: " + (my.servo.currentAngle())); Logger.info("Current Angle: " + (my.servo.currentAngle()));
if ((angle === 0) || (angle === 180)) { increment = -increment; } if ((angle === 30) || (angle === 150)) { increment = -increment; }
}); });
} }
}).start(); }).start();

View File

@ -27,19 +27,19 @@ We'll start defining the work for our robot next:
We'll define variables to hold our servo's angle, and the rate at which that We'll define variables to hold our servo's angle, and the rate at which that
angle will change: angle will change:
angle = 0 angle = 30
increment = 5 increment = 40
Every second, we'll increment the `angle`, set the servo to run at that angle, Every second, we'll increment the `angle`, set the servo to run at that angle,
and log the angle we're running at to the console. We'll also make sure to and log the angle we're running at to the console. We'll also make sure to
change the increment if the angle is at the upper/lower bounds of the values change the increment if the angle is at the upper/lower bounds of the values
supported: supported:
every 0.05.seconds(), -> every 1.seconds(), ->
angle += increment angle += increment
my.servo.angle(angle) my.servo.angle(angle)
Logger.info "Current angle: #{my.servo.currentAngle() }" Logger.info "Current angle: #{my.servo.currentAngle() }"
increment = -increment if (angle is 0) or (angle is 180) increment = -increment if (angle is 30) or (angle is 150)
And with all that done, we can now start our robot: And with all that done, we can now start our robot:

View File

@ -1,6 +1,6 @@
{ {
"name": "cylon", "name": "cylon",
"version": "0.6.0", "version": "0.6.1",
"main": "dist/cylon.js", "main": "dist/cylon.js",
"description": "A JavaScript robotics framework using Node.js", "description": "A JavaScript robotics framework using Node.js",
"homepage": "http://cylonjs.com", "homepage": "http://cylonjs.com",

View File

@ -34,29 +34,31 @@ namespace 'Cylon.IO', ->
@mode ?= mode @mode ?= mode
# Check if the pin acceess file is already in the GPIO folder # Check if the pin acceess file is already in the GPIO folder
FS.exists @_pinPath(), (exists) => FS.exists(@_pinPath(), (exists) =>
if exists then @_openPin() else @_createGPIOPin() if exists then @_openPin() else @_createGPIOPin()
)
close: -> close: ->
FS.writeFile @_unexportPath(), "#{ @pinNum }", (err) => FS.writeFile(@_unexportPath(), "#{ @pinNum }", (err) =>
@_closeCallback() @_closeCallback(err)
)
closeSync: -> closeSync: ->
FS.writeFileSync @_unexportPath(), "#{ @pinNum }" FS.writeFileSync(@_unexportPath(), "#{ @pinNum }")
@_closeCallback false @_closeCallback(false)
digitalWrite: (value) -> digitalWrite: (value) ->
@_setMode('w') unless @mode is 'w' @_setMode('w') unless @mode is 'w'
@status = if value is 1 then 'high' else 'low' @status = if value is 1 then 'high' else 'low'
FS.writeFile @_valuePath(), value, (err) => FS.writeFile(@_valuePath(), value, (err) =>
if err if err
@emit( @emit('error', "Error occurred while writing value #{value} to pin #{@pinNum}")
'error',
"Error occurred while writing value #{value} to pin #{@pinNum}"
)
else else
@emit 'digitalWrite', value @emit('digitalWrite', value)
)
value
# Reads the pin input every interval amount of time: # Reads the pin input every interval amount of time:
# params: # params:
@ -65,14 +67,17 @@ namespace 'Cylon.IO', ->
@_setMode('r') unless @mode is 'r' @_setMode('r') unless @mode is 'r'
readData = null readData = null
setInterval => setInterval(() =>
FS.readFile @_valuePath(), (err, data) => FS.readFile(@_valuePath(), (err, data) =>
if err if err
@emit 'error', "Error occurred while reading from pin #{ @pinNum }" @emit('error', "Error occurred while reading from pin #{ @pinNum }")
else else
readData = data readData = parseInt(data.toString())
@emit 'digitalRead', data @emit('digitalRead', readData)
, interval )
, interval)
true
setHigh: -> setHigh: ->
@digitalWrite 1 @digitalWrite 1
@ -85,35 +90,38 @@ namespace 'Cylon.IO', ->
# Creates the GPIO file to read/write from # Creates the GPIO file to read/write from
_createGPIOPin: () -> _createGPIOPin: () ->
FS.writeFile @_exportPath(), "#{ @pinNum }", (err) => FS.writeFile(@_exportPath(), "#{ @pinNum }", (err) =>
if err if err
@emit 'error', 'Error while creating pin files' @emit('error', 'Error while creating pin files')
else else
@_openPin() @_openPin()
)
_openPin: () -> _openPin: () ->
@_setMode @mode, true @_setMode(@mode, true)
@emit 'open' @emit('open')
_closeCallback: (err) -> _closeCallback: (err) ->
if err if err
@emit 'error', 'Error while closing pin files' @emit('error', 'Error while closing pin files')
else else
@emit 'close', @pinNum @emit('close', @pinNum)
# Sets the mode for the GPIO pin by writing the correct values to the pin reference files # Sets the mode for the GPIO pin by writing the correct values to the pin reference files
_setMode: (mode, emitConnect = false) -> _setMode: (mode, emitConnect = false) ->
@mode = mode @mode = mode
if mode is 'w' if mode is 'w'
FS.writeFile @_directionPath(), GPIO_DIRECTION_WRITE, (err) => FS.writeFile(@_directionPath(), GPIO_DIRECTION_WRITE, (err) =>
@_setModeCallback err, emitConnect @_setModeCallback(err, emitConnect)
)
else if mode is 'r' else if mode is 'r'
FS.writeFile @_directionPath(), GPIO_DIRECTION_READ, (err) => FS.writeFile(@_directionPath(), GPIO_DIRECTION_READ, (err) =>
@_setModeCallback err, emitConnect @_setModeCallback(err, emitConnect)
)
_setModeCallback: (err, emitConnect) -> _setModeCallback: (err, emitConnect) ->
if err if err
@emit 'error', "Setting up pin direction failed" @emit('error', "Setting up pin direction failed")
else else
@ready = true @ready = true
@emit('connect', @mode) if emitConnect @emit('connect', @mode) if emitConnect