Last active
December 19, 2015 16:59
-
-
Save synaptiko/5987868 to your computer and use it in GitHub Desktop.
LED PWM with Python & Node.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
label { | |
display: inline-block; width: 20px; height: 20px; float: left; text-align: center; | |
} | |
input { | |
display: inline-block; width: 25%; height: 20px; | |
} | |
</style> | |
</head> | |
<body> | |
<label for="r" style="background-color: red">R</label><input id="r" type="range" min="0" max="100" step="1" value="0"> | |
<br/> | |
<label for="g" style="background-color: green">G</label><input id="g" type="range" min="0" max="100" step="1" value="0"> | |
<br/> | |
<label for="b" style="background-color: blue">B</label><input id="b" type="range" min="0" max="100" step="1" value="0"> | |
<br/><br/> | |
<a id="rainbow" href="#">Rainbow</a> | |
<a id="discoteque" href="#">Discoteque</a> | |
<script> | |
var r = document.getElementById('r'); | |
var g = document.getElementById('g'); | |
var b = document.getElementById('b'); | |
var rainbow = document.getElementById('rainbow'); | |
var discoteque = document.getElementById('discoteque'); | |
var timeoutId; | |
r.addEventListener('change', onChange.bind(r), false); | |
g.addEventListener('change', onChange.bind(g), false); | |
b.addEventListener('change', onChange.bind(b), false); | |
rainbow.addEventListener('click', onRainbow, false); | |
discoteque.addEventListener('click', onDiscoteque, false); | |
function onChange() { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', ['/set?', this.id, '=', this.value].join(''), true); | |
xhr.send(); | |
} | |
function onRainbow(event) { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', '/rainbow', true); | |
xhr.send(); | |
event.preventDefault(); | |
} | |
function onDiscoteque() { | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', '/discoteque', true); | |
xhr.send(); | |
event.preventDefault(); | |
} | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var childProcess = require('child_process'); | |
var fs = require('fs'); | |
var path = require('path'); | |
var pwmPipeName = path.join(__dirname, 'node2py-pipe'); | |
var pwmColors = { r: '15', g: '11', b: '12' }; | |
var pwmColorIndices = { r: 0, g: 1, b: 2 }; | |
var pwmParams = [pwmColors.r, pwmColors.g, pwmColors.b, '50']; // Red pin, Green pin, Blue pin, PWM frequency in HZ | |
var pwmPipe; | |
var pwmProcess; | |
var intervalId; | |
function _createPipe(callback) { | |
var mkfifoProcess = childProcess.spawn('mkfifo', [pwmPipeName]); | |
mkfifoProcess.on('exit', function(code) { | |
if (code === 0) { | |
callback(); | |
} | |
else { | |
console.error('fail to create fifo with code:', code); | |
process.exit(1); | |
} | |
}); | |
} | |
function _startPwm(callback) { | |
pwmPipe = fs.openSync(pwmPipeName, 'r+'); | |
pwmProcess = childProcess.spawn(path.join(__dirname, 'led-pwm.py'), pwmParams, { | |
stdio: [pwmPipe, 1, 2] | |
}); | |
process.on('SIGINT', end); | |
process.on('SIGTERM', end); | |
pwmProcess.on('exit', function() { | |
fs.closeSync(pwmPipe); | |
process.exit(); | |
}); | |
callback(); | |
} | |
function init(callback) { | |
if (!fs.existsSync(pwmPipeName)) { | |
_createPipe(_startPwm.bind(null, callback)); | |
} | |
else { | |
_startPwm(callback); | |
} | |
} | |
function set(options, callback) { | |
var color; | |
var calls = 0; | |
if (intervalId !== undefined) { | |
clearInterval(intervalId); | |
intervalId = undefined; | |
// reset colors | |
return set({ | |
r: options.r || 0, | |
g: options.g || 0, | |
b: options.b || 0 | |
}, callback); | |
} | |
for (color in options) { | |
calls++; | |
_set(pwmColorIndices[color], parseInt(options[color], 10), callbackWrap); | |
} | |
if (calls === 0) callback(); | |
function callbackWrap() { | |
calls--; | |
if (calls === 0) callback(); | |
} | |
} | |
function _set(index, value, callback) { | |
var buffer = new Buffer(2); | |
buffer[0] = index; | |
buffer[1] = value; | |
fs.write(pwmPipe, buffer, 0, 2, null, callback); | |
} | |
function discoteque() { | |
if (intervalId !== undefined) { | |
clearInterval(intervalId); | |
} | |
intervalId = setInterval(function() { | |
var index = Math.floor(Math.random() * 3); | |
var value = Math.floor(Math.random() * 101); | |
_set(index, value); | |
}, 50); | |
} | |
function rainbow() { | |
var angle = 0; | |
if (intervalId !== undefined) { | |
clearInterval(intervalId); | |
} | |
intervalId = setInterval(function() { | |
var color = []; | |
var i; | |
angle += 1; | |
angle = angle % 360; | |
color[0] = Math.max(0, Math.floor(Math.cos((angle * Math.PI) / 180) * 100)); | |
color[1] = Math.max(0, Math.floor(Math.cos(((angle - 120) * Math.PI) / 180) * 100)); | |
color[2] = Math.max(0, Math.floor(Math.cos(((angle - 240) * Math.PI) / 180) * 100)); | |
for (i = 0; i < color.length; i++) { | |
_set(i, color[i]); | |
} | |
}, 100); | |
} | |
function end() { | |
var buffer = new Buffer(1); | |
buffer[0] = 3; | |
fs.writeSync(pwmPipe, buffer, 0, 1, null); | |
} | |
module.exports = { | |
init: init, | |
set: set, | |
discoteque: discoteque, | |
rainbow: rainbow, | |
end: end | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import sys | |
import RPi.GPIO as GPIO | |
pins = [int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])] | |
freq = int(sys.argv[4]) | |
GPIO.setmode(GPIO.BOARD) | |
for i in range(len(pins)): | |
pin = pins[i] | |
GPIO.setup(pin, GPIO.OUT) | |
pins[i] = GPIO.PWM(pin, freq) | |
pins[i].start(0) | |
try: | |
while 1: | |
pin = ord(sys.stdin.read(1)) | |
if pin > 2: | |
break | |
dc = ord(sys.stdin.read(1)) | |
pins[pin].ChangeDutyCycle(dc) | |
except KeyboardInterrupt: | |
print 'keyboard interrupt' | |
finally: | |
print 'cleanup' | |
for pin in pins: | |
pin.stop() | |
GPIO.cleanup() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var http = require('http'); | |
var fs = require('fs'); | |
var path = require('path'); | |
var url = require('url'); | |
var query = require('querystring'); | |
var ledController = require('./led-controller'); | |
var app = http.createServer(function(request, response) { | |
var parsedUrl = url.parse(request.url); | |
var parsedQuery; | |
if (parsedUrl.pathname === '/') { | |
response.writeHead(200); | |
fs.readFile(path.join(__dirname, 'index.html'), function(error, buffer) { | |
response.write(buffer); | |
response.end(); | |
}); | |
} | |
else if (parsedUrl.pathname === '/set' && parsedUrl.query) { | |
parsedQuery = query.parse(parsedUrl.query); | |
ledController.set(parsedQuery, function() { | |
response.writeHead(200); | |
response.end(); | |
}); | |
} | |
else if (parsedUrl.pathname === '/discoteque') { | |
ledController.discoteque(); | |
response.writeHead(200); | |
response.end(); | |
} | |
else if (parsedUrl.pathname === '/rainbow') { | |
ledController.rainbow(); | |
response.writeHead(200); | |
response.end(); | |
} | |
else if (parsedUrl.pathname === '/end') { | |
ledController.end(); | |
} | |
else { | |
response.writeHead(404); | |
response.end(); | |
} | |
}); | |
ledController.init(function() { | |
app.listen(8080); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment