Управляємо світлодіодом через інтернет з використанням RaspberryPi

В наш час звичайна річ, підключена до інтернету, починає ставати буденністю. Навіть з'явилося поняття — «інтернет речей» (Internet of Things, IoT). Але як підступитись до цього своєрідного інтернету новачкові — не завжди зрозуміло, тому що хоча статей по даній темі багато, але кожному хочеться, щоб стаття була простою для відтворення і щоб в ній розбирався щось дуже близьке і приємний для читача.

Тому спробуємо підключити до інтернету найпростіше — світлодіод, взятий з зламаною оптичної миші. Будемо через сторінку в інтернеті включати і вимикати світлодіод, управляти частотою його мерехтінь.

Для нашого експерименту потрібно

  • Інтернет через ethernet кабель
  • Raspberry Pi
  • Зламана оптична мишка, дроти, паяльник
  • Доступ до сайту на vps з правами рута

Збираємо схему
Схема підключення світлодіода до інтернету буде наступна:



Отже, зберемо всі деталі на столі і спаяні нашу просту схемку. З мишки дістаємо світлодіод і резистор в 220 Ом. Резистор потрібен для обмеження струму, він дрібний і його ледве можна розгледіти на кінці дроту. Для з'єднання проводів з GPIO використовую коннектори, які випросив у сервісі, ремонтирующем комп'ютери.



Готуємо софт
На сервері і «малинці» повинен стояти node.js і npm (node package manager). Встановлюємо по даній інструкції.

Для того, щоб node.js зміг працювати з GPIO, потрібно встановити модуль rpi-gpio. А для з'єднання з сервером RPi потрібно
socket.io-client
. Встановлюються пакети командою
sudo npm install rpi-gpio
та
sudo npm install socket.io-client
.

Скрипт для node.js на Raspberry Pi:
var socket = require('socket.io-client')('vpssite.domain:3141');
var gpio = require('rpi-gpio');
var fs = require('fs');

// hack due to error
fs.exists = require('path').exists;
var async = require('async');

// pin GPIO4
var pin = 7;

// current fps
var piFps = 0;
var currentValue = false;
var timemanager;


var set0 = function(err, results) {
if (err)
console.log(err);
console.log('Pin ' + pin + ' closed');
directWrite(pin, false, function() {
clearTimeout(timemanager);
});
};

var blinkexec = function() {
delayedWrite(7, true, function() {
delayedWrite(7, false, blinkexec)
});
};

var blink = function(err, results) {
if (err)
console.log(err);
console.log('Pin ' + pin + ' blinking');
blinkexec();
};


function directWrite(pin, value, callback) {
return gpio.write(pin, value, callback);

}
function delayedWrite(pin, value, callback) {
var delay = Math.round(1000 / piFps / 2);

clearTimeout(timemanager);
timemanager = setTimeout(function() {
directWrite(pin, value, callback);
}, delay);
}


var release = function() {
console.log('Writes complete, pause then unexport pins');
setTimeout(function() {
gpio.destroy(function() {
console.log('Closed pins, now exit');
return process.exit(0);
});
}, 500);
};


socket.on('connect', function() {
console.log('connected');

socket.on('setfps', function(data) {
console.log(data);

if (data.fps > 0) {
piFps = data.fps;
gpio.setup(pin, gpio.DIR_OUT, blink);
} else {
gpio.setup(pin, gpio.DIR_OUT, set0);
}
});

socket.on('disconnect', function() {
console.log('disconnect');
release();
});
});




Наступний код на сервері створює сервер на порту 3141 і приймає команду setfps і розсилає її далі всім браузерам і Raspberry Pi.

Скрипт для node.js на vps
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

var allClients = [];
var count = 0;
var fpsPi = 0;

server.listen(3141);

server.on('error', function(e) {
if (e.code == 'EADDRINUSE') {
console.log('Address in use, exit...');
process.exit();
}
});

app.get('/', function (req, res) {
res.send('Fps is ' + fpsPi);
console.log('requested / - show ' + fpsPi);
});

function getDate() {
var datas = new Date();
return datas.getHours() + ':' + datas.getMinutes() + ':' + datas.getSeconds() + '.' + datas.getMilliseconds()
}

function consolelog(msg) {
console.log(getDate() + ' ' + msg);
}

io.on('connection', function (socket) {
io.emit('setfps', {fps: fpsPi});

// browser subscribes to listen to the station 
socket.on(subscribe, function(data) {
socket.json.emit('subscribed', {fps: fpsPi});
io.emit('setfps', {fps: fpsPi});
});

// disconnect on error. Browser will reconnect
socket.on('error', function() {
socket.disconnect();
});

// client disconnects
socket.on('disconnect', function() {
consolelog('Client disconnected.');
});

// save to RPi and browsers new fps
socket.on('setfps', function(fps){
fpsPi = fps;
consolelog('setfps ' + fpsPi);
io.emit('setfps', {fps: fpsPi});
});
});




Запуск роботи
Запускаємо скрипти наступним чином. На RaspberryPi — з правами рута:
sudo nodejs led.js
, а на сервері — просто додаємо в кронтаб
* * * * * cd /var/www/apps; node server.js >> cron_rpi.log
, це не так красиво, зате завжди сервер буде запущений і можемо про нього забути.

На сторінці свого сайту включаємо код для слайдера jquery-ui і socket.io з нашого сервера. При отриманні сигналу від node.js-сервера слайдер виставляє поточне значення fps і навпаки — при пересуванні слайдера ми на сервер відсилаємо нове значення fps, яке сервер потім розсилає всім клієнтам в браузери і на Raspberry Pi.

Код, що розміщується на сторінці сайту
<script src="http://vpssite.domain:3141/socket.io/socket.io.js"></script>

<script>
function setSlided(val) {
if (val == 0) {
$('#freq').html('Вимкнено');
$('#freq2').hide();
}
else {
$('#freq').html(val);
$('#freq2').show();
}
}

$(function() {
// єднаємося з nodejs на сервері
var socket = io.connect('http://bk-it.ru:3141');
socket.emit(subscribe);

// при відповіді сервера виставляємо поточну fps
socket.on('subscribed', function(data) {
if (!data.error) {
setSlided(data.fps);
$("#loading").hide();

$("#slider").slider({
min: 0,
max: 20,
value: data.fps,
slide: function(event, ui) {
$("#slider").slider({ disabled: true });
socket.emit('setfps', ui.value);
//setSlided(ui.value);
}
});
}
});
socket.on('setfps', function(data) {
if (!data.error) {
setSlided(data.fps);
$("#slider").slider({value: data.fps});
$("#slider").slider({ disabled: false});
}
});
});
</script>

<h1>Світлодіод, підключений до інтернету</h1>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>

<div class="panel panel-info">
<div class="panel-heading">Керування світлодіодом через сайт</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div style="height:40px;position:relative;top:12px;">
<div id="slider"><div id="loading" style="position:relative;top:-4px;">Єднаємося <img src="/img/loading.gif" alt=""></div></div>
</div>
</div>
<div class="col-md-6">
<div class="well-sm">Частота мерехтіння <b id="freq">Вимкнений</b> <span id="freq2" style="display:none;">раз/сек</span></div>
</div>
</div>
</div>
<div class="panel-footer">
Не так часто зустрічаєте світлодіод, підключений до інтернету?
</div>
</div>



Результати роботи
А ось і відео, яке описує, що вийшло:



Ось, власне, і все, світлодіод підключений до інтернету. Тепер з будь-якого пристрою з інтернетом ми можемо керувати його мерехтінням. Простір для подальшого творчості великий. Можна до висновків підключити модуль-реле або кнопку на своєму сайті включати і виключати будь-яке обладнання. Модулів для Raspberry Pi продається дуже багато, тому політ фантазії майже не обмежений, особливо якщо в наявності захоплений восьмирічний шанувальник електроніки.

Корисні посилання, помогшие експерименту
Документація Socket.io;
Документація Node.js;
Пакет rpi-gpio;
Документація на jquery-ui слайдер;
Терморегулятори GPIO на Raspberry Pi;
Модуль respawn для автоматичного запуску nodejs-додатки (але я вибрав crontab).

Код можете взяти з rpi-led на гітхабі.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.