Вместо введения
Спасибо моему анонимному хабрадедуморозу за подарочек (pro mini). Долго колебался, что с ней делать. Махнул рукой и заказал в дополнение китайскую посылочку…
Спустя месяцок настало и моё время “помигать светодиодом” ;).
Идея
Пока ехала посылка, думал что бы такого сделать. В итоге принято решение сделать что-нибудь чуть больше, чем помигать светодиодом.
Идея заключается в следующем — отобразить прогресс просмотра видео, используя какой-нибудь индикатор.
Задача
- вытащить статистику по запущенному фильму;
- обработать и передать в arduino данные;
- отобразить прогресс на индикаторе.
Для нетерпеливых сразу результат
Реализация
1. MPC
Сколько себя помню, на ПК у меня всегда установлен Media PLayer Classic. Оказывается MPC умеет отдавать статистику по, скажем так, текущей сессии в виде html-странички со следующим содержанием:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>MPC-HC WebServer - Variables</title> <link rel="stylesheet" href="default.css"> <link rel="icon" href="favicon.ico"> </head> <body> <!--[if lt IE 8]> <div class="browser-warning"><strong>Warning!</strong> You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</div> <![endif]--> <p id="filepatharg">D:%5cFILMS%5cIts.Always.Sunny.in.Philadelphia.S10E10.720p.WEB.rus.LostFilm.TV.mp4</p> <p id="filepath">D:\FILMS\Its.Always.Sunny.in.Philadelphia.S10E10.720p.WEB.rus.LostFilm.TV.mp4</p> <p id="filedirarg">D:%5cFILMS</p> <p id="filedir">D:\FILMS</p> <p id="state">1</p> <p id="statestring">Пауза</p> <p id="position">1069384</p> <p id="positionstring">00:17:49</p> <p id="duration">1255210</p> <p id="durationstring">00:20:55</p> <p id="volumelevel">75</p> <p id="muted">0</p> <p id="playbackrate">1</p> <p id="reloadtime">0</p> </body> </html>
Что бы добиться от него такого функционала, нужно проставить галочку "Слушать порт" в настройках
![](http://habrastorage.org/files/240/7fc/cae/2407fccae9134125bb35900dc6689c09.png)
Всё самое важное содержится в тегах
<p id="параметр">значение</p>
Остаётся только разобрать их и выбрать нужное.
2. NodeJS
Разбирать страничку будем при помощи NodeJS. Кстати, страница доступна по адресу localhost:13580/variables.html (порт из настроек).
Всю логику можно разделить на 3 блока:
- модуль работы с MPC web-сервером;
- модуль обработки данных;
- модуль работы с arduino.
Далее основные моменты. Весь проект вместе с кодом можно глянуть на github
main.prototype.get = function(){ var that = this return new Promise(function(done){ http.get(that.mpc_uri, function(res) { res.on('data', function (chunk) { that.mpc_obj.parse(chunk) done(that.mpc_obj.get()); }); }).on('error', function(e) { done(e.message); }); }) }
Методом parse объекта mpc_obj разбираю полученные данные
MPC_obj.prototype.parse = function(data){ var obj = {} data.toString().split('\n').forEach(function(line){ // отбираем параграфы, так как параметры только в них if (match=/\<p/.test(line)){ var name2 = line.match(/id\=\"(\w+)\"/)[1] if (!obj.hasOwnProperty(name2)) obj[name2]=line.substring(line.indexOf('>')+1,line.lastIndexOf('<')) } }) this.settings=obj; }
На выходе имеем вот такой объект
{ filepatharg: 'D:%5cmbrr555.avi', filepath: 'D:\\mbrr555.avi', filedirarg: 'D:%5c', filedir: 'D:\\', state: '1', statestring: 'Пауза', position: '1023', positionstring: '00:00:01', duration: '114906', durationstring: '00:01:54', volumelevel: '77', muted: '0', playbackrate: '1', reloadtime: '0' }
Подготавливаем данные для arduino
// Возвращает прогресс просмотренного MPC_obj.prototype.getProgress = function(){ return (this.settings["position"]/this.settings["duration"]).toFixed(5) } // Возвращает прогресс для ШИМ (PWM) 1,0 -> 255 MPC_obj.prototype.PWM = function(){ return (this.getProgress()*255).toFixed(0) }
Общение с arduino происходит путём обмена данными на com-порту. Для работы с com выбрал библиотеку node-serialport
Подключаемся с её помощью к порту com5 и устанавливаем скорость
var SerialPort = require('serialport').SerialPort; var serialPort = new SerialPort("COM5", { baudrate: 57600 }, false);
Открываем порт и посылаем в ответ arduino наш прогресс каждый раз, когда она попросит
serialPort.open(function (error) { if ( error ) { console.log('failed to open: '+error); } else { console.log('open'); //получил данные от arduino serialPort.on('data', function(data) { main.init(function(a){ //послал в ответ прогресс фильма serialPort.write(a); }); }); } });
3. Arduino
Теперь железо. Данные для arduino мы подготовили, теперь определимся с той самой индикацией. Для отображения прогресса я выбрал вот такой очень дешёвый модуль вольтметра и немного его «подкрасил»
![](http://habrastorage.org/files/b1b/57c/836/b1b57c836b1f4384b3fdcba585328ede.png)
Ну а далее размеры и пара новых панелек
![](http://habrastorage.org/files/7ad/b29/f46/7adb29f46d4d477a95f95dff0886a9ac.png)
В arduino мы посылаем данные о прогрессе фильма и пропорционально изменяем напряжение на одной из ног микроконтроллера. Принципиальная схема (наличие светодиода для того, что бы им помигать в конце сеанса ;))
Теперь запрограммируем наш микроконтроллер.
В переменную inByte будем считывать данные, полученные по com-порту. Вешаем на 3й пин светодиод, а на 9й — вольтметр. Устанавливаем точно такую же скорость как и раньше. loop — наш бесконечный цикл. Каждые 100мс отправляем в порт абстрактные данные Serial.print(‘A’). Ждём наличие ответа Serial.available() > 0. Если на ПК запущен MPC и nodeJS-приложение, которое возвращает прогресс, то чуть подсветим светодиод на 3м пине analogWrite(3, 5) и передадим на 9й пин вольтметра значение прогресса analogWrite(9, inByte). Функция analogWrite передаёт значения от 0 до 255, что в нашем случае соответствует от 0В до 5В. Тут нужно почитать про ШИМ (PWM) — это всё благодаря ему.
Когда мы просмотрели половину фильма, в этот момент на 9й пин будет передано 255/2 = analogWrite(9, 127), что соответствует 2,5В на вольтметре. Как только фильм закончен — бодренько мигаем светодиодом 😉
int inByte = 0; void setup() { pinMode(9, OUTPUT); pinMode(3, OUTPUT); analogWrite(3, 0); analogWrite(9, 0); Serial.begin(57600); } void loop() { Serial.print('A'); delay(100); if (Serial.available() > 0) { analogWrite(3, 5); inByte = Serial.parseInt(); analogWrite(9, inByte); if (inByte==255) analogWrite(3, 255); } }
Вот так это всё выглядит в живую на макетке
да ещё и на видео 😉
Кстати в этом проекте использован как раз подарочек от того самого хабрадедамороза.
PS.
Рядом лежит Attiny13, как время будет — попробую перенести всё на неё.
Ссылки:
- подарочек от хабрадедамороза;
- Media PLayer Classic;
- Весь проект на github;
- модуль для работы с com-портом node-serialport;
- про ШИМ (PWM) ;
- свеженький NodeJS;
- Arduino IDE.
Если где-то написал полную ерунду или ошибся — подсказывайте, подправлю ;). Спасибо за внимание.
ссылка на оригинал статьи http://habrahabr.ru/post/254911/
Добавить комментарий