Skip to content

Instantly share code, notes, and snippets.

@synaptiko
Last active December 19, 2015 16:59
Show Gist options
  • Save synaptiko/5987868 to your computer and use it in GitHub Desktop.
Save synaptiko/5987868 to your computer and use it in GitHub Desktop.
LED PWM with Python & Node.js
<!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>
#!/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
}
#!/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()
#!/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