first commit

This commit is contained in:
pandacraft 2025-03-21 16:04:17 +01:00
commit a5a0434432
1126 changed files with 439481 additions and 0 deletions

View file

@ -0,0 +1,99 @@
module.exports = {
//Command Format
// digitalRead() command format header
dRead : [1]
// digitalWrite() command format header
, dWrite : [2]
// analogRead() command format header
, aRead : [3]
// analogWrite() command format header
, aWrite : [4]
// pinMode() command format header
, pMode : [5]
// Ultrasonic read
, uRead : [7]
// Get firmware version
, version : [8]
// Accelerometer (+/- 1.5g) read
, acc_xyz : [20]
// RTC get time
, rtc_getTime : [30]
// DHT Pro sensor temperature
, dht_temp : [40]
// Grove LED Bar commands
// Initialise
, ledBarInit : [50]
// Set orientation
, ledBarOrient : [51]
// Set level
, ledBarLevel : [52]
// Set single LED
, ledBarSetOne : [53]
// Toggle single LED
, ledBarToggleOne : [54]
// Set all LEDs
, ledBarSet : [55]
// Get current state
, ledBarGet : [56]
// Grove 4 Digit Display commands
// Initialise
, fourDigitInit : [70]
// Set brightness, not visible until next cmd
, fourDigitBrightness : [71]
// Set numeric value without leading zeros
, fourDigitValue : [72]
// Set numeric value with leading zeros
, fourDigitValueZeros : [73]
// Set individual digit
, fourDigitIndividualDigit : [74]
// Set individual leds of a segment
, fourDigitIndividualLeds : [75]
// Set left and right values with colon
, fourDigitScore : [76]
// Analog read for n seconds
, fourDigitAnalogRead : [77]
// Entire display on
, fourDigitAllOn : [78]
// Entire display off
, fourDigitAllOff : [79]
// Grove Chainable RGB LED commands
// Store color for later use
, storeColor : [90]
// Initialise
, chainableRgbLedInit : [91]
// Initialise and test with a simple color
, chainableRgbLedTest : [92]
// Set one or more leds to the stored color by pattern
, chainableRgbLedSetPattern : [93]
// Set one or more leds to the stored color by modulo
, chainableRgbLedSetModulo : [94]
// Sets leds similar to a bar graph, reversible
, chainableRgbLedSetLevel : [95]
// Grove IR sensor
// Read the button from IR sensor
, irRead : [21]
// Set pin for the IR reciever
, irRecvPin : [22]
// Grove Dust sensor
, dustSensorRead : [10]
, dustSensorEn : [14]
, dustSensorDis : [15]
// Encoder
, encoderRead : [11]
, encoderEn : [16]
, encoderDis : [17]
// Grove Flow sensor
, flowRead : [12]
, flowEn : [18]
, flowDis : [13]
// This allows us to be more specific about which commands contain unused bytes
, unused : 0
};

View file

@ -0,0 +1,192 @@
// Modules
var i2c = require('i2c-bus')
var async = require('async')
var log = require('npmlog')
var sleep = require('sleep')
var fs = require('fs')
var commands = require('./commands')
var I2CCMD = 1
var debugMode = false
var i2c0Path = '/dev/i2c-0'
var i2c1Path = '/dev/i2c-1'
var bus
var busNumber
var initWait = 1 // in seconds
var isInit = false
var isHalt = false
var isBusy = false
var ADDRESS = 0x04
var onError, onInit
function GrovePi(opts) {
this.BYTESLEN = 4
this.INPUT = 'input'
this.OUTPUT = 'output'
if (typeof opts == 'undefined')
opts = {}
if (typeof opts.debug != 'undefined')
this.debugMode = opts.debug
else
this.debugMode = debugMode
// TODO: Dispatch an error event instead
if (typeof opts.onError == 'function')
onError = opts.onError
// TODO: Dispatch a init event instead
if (typeof opts.onInit == 'function')
onInit = opts.onInit
if (fs.existsSync(i2c0Path)) {
isHalt = false
busNumber = 0
} else if (fs.existsSync(i2c1Path)) {
isHalt = false
busNumber = 1
} else {
var err = new Error('GrovePI could not determine your i2c device')
isHalt = true
if (typeof onError == 'function')
onError(err)
this.debug(err)
}
}
GrovePi.prototype.init = function() {
if (!isHalt) {
bus = i2c.openSync(busNumber)
if (!isInit) {
this.debug('GrovePi is initing')
sleep.sleep(initWait)
isInit = true
if (typeof onInit == 'function')
onInit(true)
} else {
var err = new Error('GrovePI is already initialized')
if (typeof onInit == 'function')
onInit(false)
onError(err)
}
} else {
var err = new Error('GrovePI cannot be initialized')
if (typeof onInit == 'function')
onInit(false)
onError(err)
}
}
GrovePi.prototype.close = function() {
if (typeof bus != 'undefined') {
this.debug('GrovePi is closing')
bus.closeSync()
} else {
this.debug('The device is not defined')
}
}
GrovePi.prototype.run = function(tasks) {
this.debug('GrovePi is about to execute ' + tasks.length + ' tasks')
async.waterfall(tasks)
}
GrovePi.prototype.checkStatus = function() {
if (!isInit || isHalt){
if (!isHalt) {
this.debug('GrovePi needs to be initialized.')
} else {
this.debug('GrovePi is not operative because halted')
}
return false
}
return true
}
GrovePi.prototype.readByte = function() {
var isOperative = this.checkStatus()
if (!isOperative)
return false
var length = 1
var buffer = new Buffer.alloc(length)
var ret = bus.i2cReadSync(ADDRESS, length, buffer)
return ret > 0 ? buffer : false
}
GrovePi.prototype.readBytes = function(length) {
if (typeof length == 'undefined')
length = this.BYTESLEN
var isOperative = this.checkStatus()
if (!isOperative)
return false
var buffer = new Buffer.alloc(length)
var ret = false
try {
var val = bus.i2cReadSync(ADDRESS, length, buffer)
ret = val > 0 ? buffer : false
} catch (err) {
ret = false
} finally {
return ret
}
}
GrovePi.prototype.writeBytes = function(bytes) {
var isOperative = this.checkStatus()
if (!isOperative)
return false
var buffer = new Buffer.from(bytes)
var ret = false
try {
var val = bus.i2cWriteSync(ADDRESS, buffer.length, buffer)
ret = val > 0 ? true : false
} catch (err) {
ret = false
} finally {
return ret
}
}
GrovePi.prototype.pinMode = function(pin, mode) {
var isOperative = this.checkStatus()
if (!isOperative)
return false
if (mode == this.OUTPUT) {
return this.writeBytes(commands.pMode.concat([pin, 1, commands.unused]))
} else if (mode == this.INPUT) {
return this.writeBytes(commands.pMode.concat([pin, 0, commands.unused]))
} else {
this.debug('Unknown pin mode')
}
}
GrovePi.prototype.debug = function(msg) {
if (this.debugMode)
log.info('GrovePi.board', msg)
}
GrovePi.prototype.wait = function(ms) {
sleep.usleep(1000 * ms)
}
// GrovePi functions
GrovePi.prototype.version = function() {
var write = this.writeBytes(commands.version.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.wait(100)
this.readByte()
var bytes = this.readBytes()
if (typeof bytes == 'object')
return (bytes[1] + '.' + bytes[2] + '.' + bytes[3])
else
return false
} else {
return false
}
}
// export the class
module.exports = GrovePi

View file

@ -0,0 +1,32 @@
module.exports.GrovePi = {
commands: require('./commands')
, board: require('./grovepi')
, sensors: {
base: {
Sensor: require('./sensors/base/sensor')
, Analog: require('./sensors/base/analogSensor')
, Digital: require('./sensors/base/digitalSensor')
, I2C: require('./sensors/base/i2cSensor')
}
, DigitalInput: require('./sensors/genericDigitalInputSensor')
, DigitalOutput: require('./sensors/genericDigitalOutputSensor')
, AccelerationI2C: require('./sensors/accelerationI2cSensor')
, AirQualityAnalog: require('./sensors/airQualityAnalogSensor')
, ChainableRGBLedDigital: require('./sensors/chainableRGBLedDigitalSensor')
, DHTDigital: require('./sensors/DHTDigitalSensor')
, FourDigitDigital: require('./sensors/fourDigitDigitalSensor')
, LedBarDigital: require('./sensors/ledBarDigitalSensor')
, LightAnalog: require('./sensors/lightAnalogSensor')
, RTCI2C: require('./sensors/rtcI2cSensor')
, TemperatureAnalog: require('./sensors/temperatureAnalogSensor')
, UltrasonicDigital: require('./sensors/ultrasonicDigitalSensor')
, IRReceiver: require('./sensors/IRReceiverSensor')
, SPDTRelay: require('./sensors/SPDTRelay')
, dustDigital: require('./sensors/dustDigitalSensor')
, encoderDigital: require('./sensors/encoderDigitalSensor')
, waterFlowDigital: require('./sensors/waterFlowDigitalSensor')
, DigitalButton: require('./sensors/digitalButton')
, LoudnessAnalog: require('./sensors/loudnessAnalogSensor')
, RotaryAnalog: require('./sensors/rotaryAngleAnalogSensor')
}
}

View file

@ -0,0 +1,27 @@
{
"name": "node-grovepi",
"version": "2.2.0",
"description": "GrovePi library for Node.js",
"keywords": ["grovepi", "robot", "gpio", "i2c"],
"dependencies": {
"async": "1.*",
"i2c-bus": "1.*",
"npmlog": "2.*",
"sleep": "3.*",
"mathjs": "3.17.*"
},
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git://github.com/marcellobarile/GrovePi.git"
},
"author": "Marcello Barile <marcello.barile@gmail.com> (http://www.barile.eu)",
"license": "MIT",
"bugs": {
"url": "https://github.com/marcellobarile/GrovePi/issues"
},
"homepage": "https://github.com/marcellobarile/GrovePi"
}

View file

@ -0,0 +1,92 @@
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function DHTDigitalSensor(pin, moduleType, scale) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
this.moduleType = moduleType
this.scale = scale
}
function convertCtoF(temp) {
return temp * 9 / 5 + 32
}
function convertFtoC(temp) {
return (temp - 32) * 5 / 9
}
function getHeatIndex(temp, hum, scale) {
// http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
var needsConversion = typeof scale == 'undefined' || scale == DHTDigitalSensor.CELSIUS
temp = needsConversion ? convertCtoF(temp) : temp
// Steadman's result
var heatIndex = 0.5 * (temp + 61 + (temp - 68) * 1.2 + hum * 0.094)
// regression equation of Rothfusz is appropriate
if (temp >= 80) {
var heatIndexBase = (-42.379 +
2.04901523 * temp +
10.14333127 * hum +
-0.22475541 * temp * hum +
-0.00683783 * temp * temp +
-0.05481717 * hum * hum +
0.00122874 * temp * temp * hum +
0.00085282 * temp * hum * hum +
-0.00000199 * temp * temp * hum * hum )
// adjustment
if (hum < 13 && temp <= 112) {
heatIndex = heatIndexBase - (13 - hum) / 4 * Math.sqrt((17 - Math.abs(temp - 95)) / 17)
} else if (hum > 85 && temp <= 87) {
heatIndex = heatIndexBase + ((hum - 85) / 10) * ((87 - temp) / 5)
} else {
heatIndex = heatIndexBase
}
}
return needsConversion ? convertFtoC(heatIndex) : heatIndex
}
DHTDigitalSensor.prototype = new DigitalSensor()
DHTDigitalSensor.VERSION = {
'DHT11' : 0
, 'DHT22' : 1
, 'DHT21' : 2
, 'AM2301': 3
}
DHTDigitalSensor.CELSIUS = 'c'
DHTDigitalSensor.FAHRENHEIT = 'f'
DHTDigitalSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.dht_temp.concat([this.pin, this.moduleType, commands.unused]))
if (write) {
this.board.wait(500)
this.board.readByte()
this.board.wait(200)
var bytes = this.board.readBytes(9)
if (bytes instanceof Buffer) {
var hex
var tempBytes = bytes.slice(1, 5).reverse()
var humBytes = bytes.slice(5, 9).reverse()
hex = '0x' + tempBytes.toString('hex')
var temp = (hex & 0x7fffff | 0x800000) * 1.0 / Math.pow(2, 23) * Math.pow(2, ((hex >> 23 & 0xff) - 127))
temp = +(Number(parseFloat(temp - 0.5).toFixed(2)))
if (this.scale == DHTDigitalSensor.FAHRENHEIT) {
temp = convertCtoF(temp)
}
hex = '0x' + humBytes.toString('hex')
var hum = (hex & 0x7fffff | 0x800000) * 1.0 / Math.pow(2, 23) * Math.pow(2, ((hex >> 23 & 0xff) - 127))
hum = +(Number(parseFloat(hum - 2).toFixed(2)))
var heatIndex = +(Number(parseFloat(getHeatIndex(temp, hum, this.scale)).toFixed(2)))
// From: https://github.com/adafruit/DHT-sensor-library/blob/master/DHT.cpp
return [temp, hum, heatIndex]
} else
return false
} else {
return false
}
}
module.exports = DHTDigitalSensor

View file

@ -0,0 +1,33 @@
var util = require('util')
var Sensor = require('./base/sensor')
var commands = require('../commands')
function IRReceiverSensor(pin) {
Sensor.apply(this, Array.prototype.slice.call(arguments))
this.pin = pin + 1
}
util.inherits(IRReceiverSensor, Sensor);
IRReceiverSensor.prototype = new IRReceiverSensor()
IRReceiverSensor.prototype.read = function() {
this.write(commands.unused)
var writeRet = this.board.writeBytes(commands.irRead.concat([commands.unused, commands.unused, commands.unused]))
if (writeRet) {
this.board.wait(100)
this.board.readByte()
var bytes = this.board.readBytes(22)
if (bytes instanceof Buffer && bytes[1] != 255) {
bytes.slice(0,1)
return bytes
} else {
return false
}
} else {
return false
}
}
IRReceiverSensor.prototype.write = function(value) {
return this.board.writeBytes(commands.irRecvPin.concat([this.pin, value, commands.unused]))
}
module.exports = IRReceiverSensor

View file

@ -0,0 +1,29 @@
var DigitalSensor = require('./base/digitalSensor'),
commands = require('../commands')
function SPDTRelay(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
SPDTRelay.prototype = new DigitalSensor()
SPDTRelay.prototype.on = function () {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.dWrite.concat([this.pin, 1, commands.unused]))
if (write) {
return true
} else {
return false
}
}
SPDTRelay.prototype.off = function () {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.dWrite.concat([this.pin, 0, commands.unused]))
if (write) {
return true
} else {
return false
}
}
module.exports = SPDTRelay

View file

@ -0,0 +1,29 @@
var util = require('util')
var I2cSensor = require('./base/i2cSensor')
var commands = require('../commands')
function AccelerationI2cSensor() {
I2cSensor.apply(this, Array.prototype.slice.call(arguments))
}
AccelerationI2cSensor.prototype = new I2cSensor()
AccelerationI2cSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.acc_xyz.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(100)
this.board.readByte()
var bytes = this.board.readBytes()
if (bytes instanceof Buffer) {
var x = bytes[1] > 32 ? -(bytes[1]-224) : bytes[1]
var y = bytes[2] > 32 ? -(bytes[2]-224) : bytes[2]
var z = bytes[3] > 32 ? -(bytes[3]-224) : bytes[3]
return [x, y, z]
} else {
return false
}
} else {
return false
}
}
module.exports = AccelerationI2cSensor

View file

@ -0,0 +1,14 @@
var AnalogSensor = require('./base/analogSensor')
var commands = require('../commands')
function AirQualityAnalogSensor(pin) {
AnalogSensor.apply(this, Array.prototype.slice.call(arguments))
}
AirQualityAnalogSensor.prototype = new AnalogSensor()
AirQualityAnalogSensor.prototype.read = function() {
var res = AnalogSensor.prototype.read.call(this)
return parseInt(res)
}
module.exports = AirQualityAnalogSensor

View file

@ -0,0 +1,33 @@
var util = require('util')
var Sensor = require('./sensor')
var commands = require('../../commands')
function AnalogSensor(pin) {
Sensor.apply(this, Array.prototype.slice.call(arguments))
this.pin = pin
}
util.inherits(AnalogSensor, Sensor)
AnalogSensor.prototype = new AnalogSensor()
AnalogSensor.prototype.read = function(length) {
if (typeof length == 'undefined')
length = this.board.BYTESLEN
var writeRet = this.board.writeBytes(commands.aRead.concat([this.pin, commands.unused, commands.unused]))
if (writeRet) {
this.board.readByte()
var bytes = this.board.readBytes(length)
if (bytes instanceof Buffer) {
return bytes[1] * 256 + bytes[2]
} else {
return false
}
} else {
return false
}
}
AnalogSensor.prototype.write = function(value) {
return this.board.writeBytes(commands.aWrite.concat([this.pin, value, commands.unused]))
}
module.exports = AnalogSensor

View file

@ -0,0 +1,25 @@
var util = require('util')
var Sensor = require('./sensor')
var commands = require('../../commands')
function DigitalSensor(pin) {
Sensor.apply(this, Array.prototype.slice.call(arguments))
this.pin = pin
}
util.inherits(DigitalSensor, Sensor)
DigitalSensor.prototype = new DigitalSensor()
DigitalSensor.prototype.read = function() {
var writeRet = this.board.writeBytes(commands.dRead.concat([this.pin, commands.unused, commands.unused]))
if (writeRet) {
this.board.wait(100)
return this.board.readBytes(2)[1]
} else {
return false
}
}
DigitalSensor.prototype.write = function(value) {
return this.board.writeBytes(commands.dWrite.concat([this.pin, value, commands.unused]))
}
module.exports = DigitalSensor

View file

@ -0,0 +1,11 @@
var util = require('util')
var Sensor = require('./sensor')
var commands = require('../../commands')
function I2cSensor() {
Sensor.apply(this, Array.prototype.slice.call(arguments))
}
util.inherits(I2cSensor, Sensor)
I2cSensor.prototype = new I2cSensor()
module.exports = I2cSensor

View file

@ -0,0 +1,67 @@
var util = require('util')
var EventEmitter = require('events').EventEmitter
var Board = require('../../grovepi')
var isEqual = function(a, b) {
if (typeof a == 'object') {
for (var i in a) {
if (a[i] !== b[i]) {
return false
}
}
return true
} else {
return a === b
}
}
function Sensor() {
this.board = new Board()
this.lastValue = 0
this.currentValue = 0
this.streamInterval = this.watchInterval = undefined
this.watchDelay = 100
}
util.inherits(Sensor, EventEmitter)
Sensor.prototype.read = function() {}
Sensor.prototype.write = function() {}
Sensor.prototype.stream = function(delay, cb) {
var self = this
delay = typeof delay == 'undefined' ? self.watchDelay : delay
self.stopStream()
self.streamInterval = setInterval(function onStreamInterval() {
var res = self.read()
cb(res)
}, delay)
}
Sensor.prototype.stopStream = function() {
var self = this
if (typeof self.streamInterval != 'undefined')
clearInterval(self.streamInterval)
}
Sensor.prototype.watch = function(delay) {
var self = this
delay = typeof delay == 'undefined' ? self.watchDelay : delay
self.stopWatch()
self.watchInterval = setInterval(function onInterval() {
var res = self.read()
self.lastValue = self.currentValue
self.currentValue = res
if (!isEqual(self.currentValue, self.lastValue))
self.emit('change', self.currentValue)
}, delay)
}
Sensor.prototype.stopWatch = function() {
var self = this
if (typeof self.watchInterval != 'undefined')
clearInterval(self.watchInterval)
}
module.exports = Sensor

View file

@ -0,0 +1,52 @@
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function ChainableRGBLedDigitalSensor(pin, numLeds) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
this.numLeds
}
ChainableRGBLedDigitalSensor.prototype = new DigitalSensor()
ChainableRGBLedDigitalSensor.prototype.init = function() {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.chainableRgbLedInit.concat([this.pin, this.numLeds, commands.unused]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
ChainableRGBLedDigitalSensor.prototype.setPattern = function(pattern, whichLed) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.chainableRgbLedSetPattern.concat([this.pin, pattern, whichLed]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
ChainableRGBLedDigitalSensor.prototype.setModulo = function(offset, divisor) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.chainableRgbLedSetModulo.concat([this.pin, offset, divisor]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
ChainableRGBLedDigitalSensor.prototype.setLevel = function(level, reverse) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.chainableRgbLedSetLevel.concat([this.pin, level, reverse]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
module.exports = ChainableRGBLedDigitalSensor

View file

@ -0,0 +1,46 @@
var DigitalInput = require('./base/digitalSensor')
const buttonMode = {
UP: 0,
DOWN: 1
}
var mode = buttonMode.UP //not pressed
var pressedDateTime
var currentDateTime
var milliseconds
//digital button, can throw singlepress and longpress events
function DigitalButton(pin, longPressDelay) {
DigitalInput.apply(this, Array.prototype.slice.call(arguments))
this.longPressDelay = longPressDelay || 1100
this.on('change', function (res) {
//user presses the button for the first time
if (res == 1 && mode === buttonMode.UP) {
pressedDateTime = new Date()
mode = buttonMode.DOWN
return
}
//user continues to press the button
else if (res == 1 && mode === buttonMode.DOWN) {
//do nothing
return
} else { //res == 0 so user has lifted her finger
currentDateTime = new Date()
milliseconds = currentDateTime.getTime() - pressedDateTime.getTime()
//if less than longPressDelay milliseconds
if (milliseconds <= this.longPressDelay) {
this.emit('down', 'singlepress')
} else {
this.emit('down', 'longpress')
}
//reset the mode
mode = buttonMode.UP
}
});
}
DigitalButton.prototype = new DigitalInput()
module.exports = DigitalButton

View file

@ -0,0 +1,85 @@
// TODO: call disable function on exit
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
var helpers = require('./helpers')
function DustDigitalSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
this.results = new Array()
}
DustDigitalSensor.prototype = new DigitalSensor()
DustDigitalSensor.prototype.read = function () {
var write = this.board.writeBytes(commands.dustSensorRead.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
var bytes = this.board.readBytes()
//console.log(bytes[0] + ' ' + bytes[1] + ' ' + bytes[2] + ' ' + bytes[3])
if (bytes instanceof Buffer && bytes[0] != 0)
return [bytes[0], (bytes[3] * 256 * 256 + bytes[2] * 256 + bytes[1])]
else
return false
} else {
return false
}
}
DustDigitalSensor.prototype.enable = function () {
var write = this.board.writeBytes(commands.dustSensorEn.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
DustDigitalSensor.prototype.disable = function () {
var write = this.board.writeBytes(commands.dustSensorDis.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
DustDigitalSensor.prototype.start = function () {
if (!this.enable())
throw new Error('cannot enable dust sensor')
this.enable()
setInterval(loop.bind(this), 30 * 1000) //every 30 seconds
}
DustDigitalSensor.prototype.stop = function () {
this.disable()
clearInterval(loop)
}
function loop() {
let currentResult = this.read()
this.results.push(currentResult[1])
}
DustDigitalSensor.prototype.readAvgMax = function () {
if (this.results.length === 0) return {
avg: helpers.NOT_AVAILABLE,
max: helpers.NOT_AVAILABLE
};
let sum = this.results.reduce((acc, cur) => acc + cur, 0)
let avg = sum / this.results.length
let max = this.results.reduce(function (a, b) {
return Math.max(a, b)
});
//reset the array
this.results = new Array()
return {
avg: helpers.round(avg, 2),
max: helpers.round(max, 2)
};
}
module.exports = DustDigitalSensor

View file

@ -0,0 +1,43 @@
// TODO: call disable function on exit
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function EncoderDigitalSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
EncoderDigitalSensor.prototype = new DigitalSensor()
EncoderDigitalSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.encoderRead.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
this.board.readByte()
var bytes = this.board.readBytes()
if (bytes instanceof Buffer && bytes[1] != 255)
return [bytes[1], bytes[2]]
else
return false
} else {
return false
}
}
EncoderDigitalSensor.prototype.enable = function() {
var write = this.board.writeBytes(commands.encoderEn.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
EncoderDigitalSensor.prototype.disable = function() {
var write = this.board.writeBytes(commands.encoderDis.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
module.exports = EncoderDigitalSensor

View file

@ -0,0 +1,97 @@
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function FourDigitDigitalSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
FourDigitDigitalSensor.prototype = new DigitalSensor()
FourDigitDigitalSensor.prototype.init = function() {
this.board.pinMode(this.board.OUTPUT)
return this.board.writeBytes(commands.fourDigitInit.concat([this.pin, commands.unused, commands.unused]))
}
FourDigitDigitalSensor.prototype.setNumber = function(value, useLeadingZero) {
this.board.pinMode(this.board.OUTPUT)
var byte1 = value & 255
var byte2 = value >> 8
var command = useLeadingZero ? commands.fourDigitValue : commands.fourDigitValueZeros
var write = this.board.writeBytes(command.concat([this.pin, byte1, byte2]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.setBrightness = function(brightness) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitBrightness.concat([this.pin, brightness, commands.unused]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.setDigit = function(segment, value) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitIndividualDigit.concat([this.pin, segment, value]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.setSegment = function(segment, leds) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitIndividualLeds.concat([this.pin, segment, leds]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.setScore = function(left, right) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitScore.concat([this.pin, left, right]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.monitor = function(analog, duration) {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitAnalogRead.concat([this.pin, analog, duration]))
if (write) {
this.board.wait(duration/1000 + 500) // TODO: This should be tested
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.on = function() {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitAllOn.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
FourDigitDigitalSensor.prototype.off = function() {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.fourDigitAllOff.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(500)
return true
} else {
return false
}
}
module.exports = FourDigitDigitalSensor

View file

@ -0,0 +1,14 @@
// Thanks to Craig Watkins for the contribution
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function GenericDigitalInputSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
GenericDigitalInputSensor.prototype = new DigitalSensor()
GenericDigitalInputSensor.prototype.read = function() {
return DigitalSensor.prototype.read.call(this)
}
module.exports = GenericDigitalInputSensor

View file

@ -0,0 +1,30 @@
// Thanks to Craig Watkins for the contribution
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function GenericDigitalOutputSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
GenericDigitalOutputSensor.prototype = new DigitalSensor()
GenericDigitalOutputSensor.prototype.turnOn = function() {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.dWrite.concat([this.pin, 1, commands.unused]))
if (write) {
return true
} else {
return false
}
}
GenericDigitalOutputSensor.prototype.turnOff = function() {
this.board.pinMode(this.board.OUTPUT)
var write = this.board.writeBytes(commands.dWrite.concat([this.pin, 0, commands.unused]))
if (write) {
return true
} else {
return false
}
}
module.exports = GenericDigitalOutputSensor

View file

@ -0,0 +1,16 @@
function round(number, precision) {
if (isNaN(number)) return NOT_AVAILABLE
if (precision == undefined || isNaN(precision))
precision = 2
var factor = Math.pow(10, precision)
var tempNumber = number * factor
var roundedTempNumber = Math.round(tempNumber)
return roundedTempNumber / factor
}
const NOT_AVAILABLE = 'N/A'
module.exports = {
round,
NOT_AVAILABLE
}

View file

@ -0,0 +1,56 @@
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function LedBarDigitalSensor(pin, orientation) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
this.orientation = orientation
this.level = 0
}
LedBarDigitalSensor.prototype = new DigitalSensor()
LedBarDigitalSensor.prototype.init = function() {
return this.setOrientation(this.orientation)
}
LedBarDigitalSensor.prototype.setOrientation = function(orientation) {
this.board.pinMode(this.board.OUTPUT)
this.orientation = orientation
return this.board.writeBytes(commands.ledBarInit.concat([this.pin, this.orientation, commands.unused]))
}
LedBarDigitalSensor.prototype.setLevel = function(level) {
this.board.pinMode(this.board.OUTPUT)
this.level = level
return this.board.writeBytes(commands.ledBarLevel.concat([this.pin, this.level, commands.unused]))
}
LedBarDigitalSensor.prototype.setLed = function(led, state) {
this.board.pinMode(this.board.OUTPUT)
return this.board.writeBytes(commands.ledBarSetOne.concat([this.pin, led, state]))
}
LedBarDigitalSensor.prototype.toggleLed = function(led) {
this.board.pinMode(this.board.OUTPUT)
return this.board.writeBytes(commands.ledBarToggleOne.concat([this.pin, led, commands.unused]))
}
LedBarDigitalSensor.prototype.setBits = function(led, state) {
this.board.pinMode(this.board.OUTPUT)
var byte1 = state & 255
var byte2 = state >> 8
return this.board.writeBytes(commands.ledBarSet.concat([this.pin, byte1, byte2]))
}
LedBarDigitalSensor.prototype.getBits = function() {
this.board.pinMode(this.board.OUTPUT)
var byte1 = state & 255
var byte2 = state >> 8
var write = this.board.writeBytes(commands.ledBarGet.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
this.board.readByte()
var bytes = this.board.readBytes()
if (bytes instanceof Buffer)
return (bytes[1] ^ (bytes[2] << 8))
else
return false
} else {
return false
}
}
module.exports = LedBarDigitalSensor

View file

@ -0,0 +1,16 @@
var AnalogSensor = require('./base/analogSensor')
var commands = require('../commands')
function LightAnalogSensor(pin) {
AnalogSensor.apply(this, Array.prototype.slice.call(arguments))
}
LightAnalogSensor.prototype = new AnalogSensor()
LightAnalogSensor.prototype.read = function() {
var res = AnalogSensor.prototype.read.call(this)
var number = parseInt(res)
var resistance = number <= 0 ? 0 : +(Number(parseFloat((1023 - number) * 10 / number)).toFixed(2))
return resistance
}
module.exports = LightAnalogSensor

View file

@ -0,0 +1,48 @@
var AnalogSensor = require('./base/analogSensor')
//same class can be used for the sound sensor
function LoudnessAnalogSensor(pin, samplespersecond) {
AnalogSensor.apply(this, Array.prototype.slice.call(arguments))
this.samplespersecond = samplespersecond || 5
this.results = new Array()
}
LoudnessAnalogSensor.prototype = new AnalogSensor()
//returns loudness average and max for values taken since the last time it was called
LoudnessAnalogSensor.prototype.readAvgMax = function () {
if (this.results.length == 0)
throw new Error('no results. Did you call start()?')
//reduce values to get the sum
let sum = this.results.reduce((acc, cur) => acc + cur, 0)
let avg = sum / this.results.length
//reduce the values to get the max
let max = this.results.reduce(function (a, b) {
return Math.max(a, b)
})
//reset the array - clear its elements
this.results = new Array()
return {
avg,
max
}
}
LoudnessAnalogSensor.prototype.start = function () {
loop.bind(this)() //so we can use 'this' inside the loop method
setInterval(loop.bind(this), 1000 / this.samplespersecond)
}
LoudnessAnalogSensor.prototype.stop = function () {
clearInterval(loop)
}
function loop() {
let currentResult = this.read()
this.results.push(currentResult)
}
module.exports = LoudnessAnalogSensor

View file

@ -0,0 +1,74 @@
var AnalogSensor = require('./base/analogSensor')
var helpers = require('./helpers')
const FULL_ANGLE = 300
//RotaryAngleSensor
//returns a value from 0 to 100
//implemented a basic noise filtering algorithm, as in our experiments
//the rotary sensor was throwing random values at random times
function RotaryAngleAnalogSensor(pin, watchDelay, samplesize) {
AnalogSensor.apply(this, Array.prototype.slice.call(arguments))
this.watchDelay = watchDelay || 10
this.samplesize = samplesize || 40
//watchDelay * samplesize equals the miliseconds interval that the sensor will report data
}
RotaryAngleAnalogSensor.prototype = new AnalogSensor()
RotaryAngleAnalogSensor.prototype.read = function () {
let value = AnalogSensor.prototype.read.call(this)
let degrees = convertDHTToDegrees(value)
//Calculate result (0 to 100) from degrees(0 to 300)
let result = Math.floor(degrees / FULL_ANGLE * 100)
return result
}
const convertDHTToDegrees = function (value) {
//http://wiki.seeed.cc/Grove-Rotary_Angle_Sensor/
let adc_ref = 5
let grove_vcc = 5
let voltage = helpers.round((value) * adc_ref / 1023, 2)
//Calculate rotation in degrees(0 to 300)
return helpers.round((voltage * FULL_ANGLE) / grove_vcc, 2)
}
RotaryAngleAnalogSensor.prototype.start = function () {
setInterval(loop.bind(this), this.watchDelay)
}
RotaryAngleAnalogSensor.prototype.stop = function () {
clearInterval(loop)
}
//new array initialized to zero
let temp = Array.apply(null, Array(101)).map(Number.prototype.valueOf, 0) //0..100
let timesRun = 0
let previousData = null
function loop() {
const reading = this.read()
if (reading < 0 || reading > 100) throw new Error('improper reading')
temp[reading]++
if (++timesRun === this.samplesize) {
//find the index of the biggest integer
const result = temp.indexOf(Math.max(...temp))
timesRun = 0
//reset the array
temp = Array.apply(null, Array(101)).map(Number.prototype.valueOf, 0)
//compare current data to previous data
if (previousData === null || Math.abs(result - previousData) != 0) {
//there is a new value
this.emit('data', result)
previousData = result
}
}
}
module.exports = RotaryAngleAnalogSensor

View file

@ -0,0 +1,20 @@
var I2cSensor = require('./base/i2cSensor')
var commands = require('../commands')
function RtcI2cSensor() {
I2cSensor.apply(this, Array.prototype.slice.call(arguments))
}
RtcI2cSensor.prototype = new I2cSensor()
RtcI2cSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.rtc_getTime.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(100)
this.board.readByte()
return this.board.readBytes()
} else {
return false
}
}
module.exports = RtcI2cSensor

View file

@ -0,0 +1,15 @@
var AnalogSensor = require('./base/analogSensor')
var commands = require('../commands')
function TemperatureAnalogSensor(pin) {
AnalogSensor.apply(this, Array.prototype.slice.call(arguments))
}
TemperatureAnalogSensor.prototype = new AnalogSensor()
TemperatureAnalogSensor.prototype.read = function() {
var res = AnalogSensor.prototype.read.call(this)
var resistance = (1023-res) * 10000 / res
return (1 / (Math.log(resistance / 10000) / 3975 + 1 / 298.15) - 273.15)
}
module.exports = TemperatureAnalogSensor

View file

@ -0,0 +1,24 @@
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function UltrasonicDigitalSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
UltrasonicDigitalSensor.prototype = new DigitalSensor()
UltrasonicDigitalSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.uRead.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
this.board.readByte()
var bytes = this.board.readBytes()
if (bytes instanceof Buffer)
return (bytes[1] * 256 + bytes[2])
else
return false
} else {
return false
}
}
module.exports = UltrasonicDigitalSensor

View file

@ -0,0 +1,43 @@
// TODO: call disable function on exit
var DigitalSensor = require('./base/digitalSensor')
var commands = require('../commands')
function WaterFlowDigitalSensor(pin) {
DigitalSensor.apply(this, Array.prototype.slice.call(arguments))
}
WaterFlowDigitalSensor.prototype = new DigitalSensor()
WaterFlowDigitalSensor.prototype.read = function() {
var write = this.board.writeBytes(commands.flowRead.concat([this.pin, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
this.board.readByte()
var bytes = this.board.readBytes()
if (bytes instanceof Buffer && bytes[1] != 255)
return [bytes[1], (bytes[3] * 256 + bytes[2])]
else
return false
} else {
return false
}
}
WaterFlowDigitalSensor.prototype.enable = function() {
var write = this.board.writeBytes(commands.flowEn.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
WaterFlowDigitalSensor.prototype.disable = function() {
var write = this.board.writeBytes(commands.flowDis.concat([commands.unused, commands.unused, commands.unused]))
if (write) {
this.board.wait(200)
return true
} else {
return false
}
}
module.exports = WaterFlowDigitalSensor