999999 в 1 или вторая жизнь Raspberry Pi 3
Если вы не знаете что такое Raspberry, то не спешите пролистывать, возможно, после прочтения, вы очень захотите узнать. Не буду вдаваться в подробности, да и сам я не техник, так что скажу просто: это недорогой одноплатный компьютер, который чаще всего покупают, чтобы поставить на него какой-нибудь линукс или андройд, и используют его, например, как дешевый ПК или мультимедиа центр (хотя конечно на этом спектр его применений не заканчивается). Его можно заказать на Амперке Алиэкспрессе, сразу с корпусом, примерно за 2500 рублей. Никаких особых технических навыков для работы с ним не требуется.
Познакомился я с этим девайсом практически год назад, он был подарком от жены на годовщину, и как игрушка для взрослого дядьки, штука оказалась весьма занятной. Я распечатал ему корпус на 3д принтере, и начал ставить кучи разных дистрибутивов тех же линуксов с андройдами, но когда наигрался, то забросил, не найдя для себя какого-то реального практического применения, так как моего компьютера с телефоном мне хватало на все нужные мне задачи.
И вот прошел почти год. Будучи закостенелым пользователем ПК я очень скептически относился к телевизору (наверное лет десять уже, как жил без него), но все же иногда хочется посмотреть киношку на большом экране, а не на ноутбуке жены, который к тому же занимал полезную площадь на диване и не мог похвастаться качественным звуком или матрицей. И мы приобрели бюджетный 49-дюймовый ТВ. Обычный китайский телик, с меню "привет из 2000-х", поэтому ни о каком смарт ТВ речи быть и не могло.
И тут многие из вас наверное подумали что я сейчас буду распинаться о том как я превратил телик с помощью Raspberry в смарт ТВ, но нет :) Для этих целей я заказал вот такую штуковину, большинство смарт ТВ по сравнению с ней будут отдыхать, но это уже совсем другая история (хотя если кому-то интересно, могу рассказать в отдельном посте).
А пока эта пиндюрина была еще в пути, почему бы не потыкать Raspberry с новым теликом? Я начал копаться в инете в поисках интересных дистрибутивов, и на ютубе обнаружил видосик с вот такой занятной штукой, под названием Recalbox:
Это шикарный эмулятор более 40 ретро-консолей для Raspberry. Благодаря нему и Raspberry можно запустить на телике любые игры детства, и речь не только о "денди-сегах", ведь там стоит ScummVM, а значит привет куче добротных адвенчур (Day of the Tentacle, Full Throttle, The Dig и т.д.), на которых мы выросли, и все это прямо на экране ТВ. Вообще я не любитель эмуляторов, ведь играя на компе, уже нет той ностальгии. Но в случае с Raspberry можно снова, как в старые добрые, сидеть перед теликом с джойстиком, и нигде для этого не нужно шуметь здоровому дорогому системнику, лишь маленькая коробочка спрятана за телевизором. Найдете?) (потроха сзади телика - от компьютера)
В общем, ощущения эмуляции при игре нет, все словно родное, но при этом с кучей бонусов и удобств. Инструкция по установке Recalbox и сам образ лежат здесь. Подытожу и так уже затянутый пост, и распишу плюсы и минусы, которые я выявил:
Плюсы:
• Цена. За те же 2500 рублей можно купить разве что пару китайских клонов-приставок, которые сгорят через неделю.
• Легкость подключения: всего два кабеля - питание MicroUSB которое можно подключить к самому телевизору, и HDMI кабель.
• Удобство работы с библиотекой игр. Можно легко добавлять/удалять игры, и для этого даже не нужно отсоединять Raspberry от ТВ или вынимать флешку, потому что папка с ромами доступна в сетевом окружении.
• Можно делать скриншоты игр, сохраняться, мотать время назад и т.д.
• Поддерживается большинство устройств ввода.
• В систему встроен мультимедиа центр KODI, благодаря которому можно не только играть, но и смотреть фото, видео, слушать музыку, смотреть интернет ТВ, и что важно, оно не тормозит, как на многих других системах, которые мне довелось использовать до этого.
Минусы:
• Нет эмулятора DOSBox, а игр для ScummVM не так много, добавлять их сложнее чем обычные ромы, и не все работают (куда ж без танцев с бубном).
• В DOS играх курсор глючит если играть стиком геймпада. С мышки и тачпада проблем нет.
• Пока не поддерживается Bluetooth
Поскольку я наконец-то нашел реально клевое применение моему Raspberry благодаря видосику на ютубе, я обязан его здесь оставить, и поблагодарить автора. В нем заодно можно подсмотреть некоторые полезные нюансы:
В общем, надеюсь, что кому-то это все было полезно или хотя-бы интересно) И да, я знаю, что есть еще и другие эмуляторы, которые в чем то лучше, и буду рад если вы поделитесь своим опытом в комментариях :)
Упhавление светом c Openhab
Всем привет! прошу помощи, разобраться с логикой работы)))
Пытаюсь реализовать одну идею управления освещением используя raspberry pi + openhab. Имею контроллер с RS485, 3х контактными реле и цифровыми входами до 220В.
Схема (рис)
S1 - проходной выключатель. лампа, контроллер.
Принцип работы как в системе с 2мя проходными выключателями, только здесь вместо второго 3х контактное реле. Для контроля состояния лампы использую входы контроллера, если на них 220 то 1, если нет, то 0.
С openhab'ом взаимодействую с помощью питоновского скрипта и библиотеки openhab.
В openhab'е есть виртуальный переключатель switch (пример рис 2) с состояниями ON и OFF. который дублирует реле.
Соответственно в скрипте могу считать цифровой вход контроллера и проверить состояние лампы, так же могу получить состояние виртуального выключателя из Openhab.
Вот только ума не приложу как постоить код управления.
Получается после включения системы свет выключен и реле и выключатель s1 и виртуальный выключатель находятся в выключенном состоянии.
Если я нажимаю S1 в комнате свет загорается...но мне так же необходимо вместе с этим, чтобы в браузере обновилось состояние выключателя по состоянию цифрового входа (что тоже могу сделать) (если был включе свет из openhab, а потом выключен с S), но как только то в опенхабе ползунок автоматом вернется в состояние "выключено") я обновляю виртуальный выключатель,то у меня происходит событие по изменению его же состояния , а так как мне необходимо постоянно мониторить и его самого, то это вызывает обратное переключение реле в выключенное состояние...и в итоге все начинает мигать)) либо тупо не работает.
Если я не обновляю состояние виртуального выключателя, то все работает, но со стороны браузера выглядит не красиво. Так как например свет если включен , то виртуальный выключатель находится в состоянии выключено и наоборот.
Может кто подобное делал, подскажите что нибудь?
Проигрыватель на базе Raspberry Pi 3 модель B (часть 5)
Вот ещё пара небольших доработок.
Это продолжение, начало здесь: часть 1, часть 2, часть 3, часть 4.
1) Окончательный вариант разъёмов для вывода аналогового звука/изображения.
Разъём Jack, диаметр 3,5 мм, 4 контакта c клеммой колодкой:
розетки RCA:
Рамку для вставки Keystone я убрал и закрепил через втулки М3.
Для соединения использовал кабель многожильный МКЭШ 3*0.75. к сожалению 3*0.5 найти не смог...
2) Ещё я добавил Wi-Fi USB-адаптер TL-WN822N v.3
Он определяется так:
0bda:8178 Realtek Semiconductor Corp. RTL8192CU 802.11n WLAN Adapter
Он крепится к корпусу DVD привода на самоклеящиеся магниты.
Подробная техническая информация доступна здесь.
Домашние вкусняшки на Raspberry PI. Веб-морда робота /окончание/
Продолжение. Начало здесь. Для тех кто не читал первую часть - в ней речь шла о том, как на основе raspberry pi создать блок управления, скажем, роботом, задействуя в качестве выходных сигналов 4 дискретных выхода GPIO и с управляющим алгоритмом на языке SFC.
6. Теперь, собственно, сам веб-интерфейс.
Для начала разработки скачайте архив Inkscape и распакуйте его в любой удобной папке. Это портабельный, не требующий инсталляции редактор SVG-графики. Запускать надо файл inkscape.exe, для удобства можно сделать ярлык на рабочем столе.
Скачайте также библиотеку виджетов, при помощи которых будем оживлять нашу мнемосхему. Распакуйте в любом удобном месте.
Создайте целевую папку (назовём её web), в которой будет лежать вся веб-начинка, содержимое этой папки и будет заливаться в ПЛК в виде zip- архива. И скопируйте туда содержимое папки web из архива виджетов.
7. Запускаем inkscape:
Кнопками + и - выставляем масштаб. На экране появилось что-то несуразное. Но это только заготовка с тремя виджетами - кнопка(button), лампочка(led) и рамка(border). Каждый из этих виджетов находится внутри своей группы, или слоя. Их три:
- слой ввода (inp) - кнопки и поля ввода;
- слой динамических элементов (dyn) - лампочки, индикаторы;
- слой статики (stat) - рамки, шкалы плюс всё что нарисуете сами в качестве заднего плана;
Чтобы эти слои сразу обозначить, начальная страница-заготовка и содержит три этих элемента/виджета, вместо которых нужно будет разместить что-то своё. Чтобы войти в нужный слой, выбираем левой кнопкой элемент, затем по правой кнопке выбираем в выпадающем меню "Войти в группу #inp, #dyn или #stat".
В правой части экрана inkscape фрейм xml-редактора. Если у вас он не появился, жмите shift+ctrl+x или поищите соотв.кнопку на правом поле экрана. Редактор показывает содержимое SVG-файла, который в xml формате. И не только показывает, но и позволяет менять свойства виджетов, так что без него никуда.
8. Итак, заходим в слой inp и размещаем кнопки управления. Кнопки берём из папки виджетов, для этого не выходя из inkscape открываем файл buttons.mns.svg (он откроется в новом окне):
Берём так - в окне buttons.mns.svg заходим в слой inp, выделяем кнопку и копируем её в буфер (ctrl+c), в окне mns.svg заходим в слой inp и пастим (ctrl+v).
После копирования кнопки можно расставить и выровнять:
Здесь кроме выравнивания кнопок я удалил ненужную старую кнопку и добавил четыре стрелки, которые будут светиться зелёным цветом при движении. Стрелки берутся из arrows.mns.svg аналогично кнопкам, только вставлять их нужно в слой #dyn. Для поворачивания стрелок есть соотв. команда в меню Объект, либо это можно делать изменяя свойство transform через xml-редактор:
9. Теперь подпишем кнопки, делается это так:
А самое главное - изменить у кнопок свойство click так, чтобы мы потом в javascript-е смогли идентифицировать кнопку при её нажатии:
Соответственно, остальным кнопкам также нужно задать свойства onclick:
- кнопка ВЛЕВО: buttonclick('left')
- кнопка ВПРАВО: buttonclick('right')
- кнопка НАЗАД: buttonclick('revers')
- кнопка ВПЕРЁД: buttonclick('forward')
- кнопка СТОП: buttonclick('stop')
10. Теперь второстепенные дела - вместо прежней панели берём другую (взята из panels.mns.svg и немного растянута) и передвигаем лампочку на панель. Вот что получилось:
Проверьте - динамические виджеты (стрелки и лампочки) должны находиться с слое (группе) dyn. Прописываем следующие идентификаторы (св-во id виджета) :
- лампочка - led1
- стрелка вправо - ar
- стрелка влево - al
- стрелка назад - ab
- стрелка вперёд - af
По этим id мы будем обращаться к ним из программы javascript.
11. Осталось бросить последний камень в огород визуализации - оживить полученную мнемосхему. Код javascript (js) должен отправлять команды от кнопок на ПЛК и забирать оттуда данные - булевские переменные do_left, do_right, do_up, do_down и по их состоянию зажигать соответствующие стрелки.
11.1 Откроем текстовым редактором файл index.js . Именно в нём сосредоточена логика визуализации. Этот файл дан для примера и его нужно подправить под наше ТЗ. Начнём с начала:
var PlcIP = "http://192.168.0.179:1200";
// массив структур для ajax-запроса чтения
var InBuf = [
{"name": "ana1", "rw":"r"},
{"name": "prg1.bool1", "rw":"r"},
{"name": "prg2.msg1", "rw":"r"}
];
// массив структур для ajax-запроса записи
var OutBuf = [
{"name": "ana2", "rw":"w"},
{"name": "prg2.msg2", "rw":"w"},
{"name": "prg1.bool1", "rw":"w"}
];
// переменные для чтения из ПЛК
var glob_ana, prg1_bool, prg2_msg;
Скорректируем это под нашу задачу, переименовав фиктивные переменные в реальные:
var PlcIP = "http://192.168.0.179:1200";
// массив структур для ajax-запроса чтения
var InBuf = [
{"name": "do_left", "rw":"r"},
{"name": "do_right", "rw":"r"},
{"name": "do_down", "rw":"r"},
{"name": "do_up", "rw":"r"}
];
// массив структур для ajax-запроса записи
var OutBuf = [
{"name": "main.cmd", "rw":"w"}
];
// переменные для чтения из ПЛК
var do_up, do_down, do_left, do_right;
Как видите, доступ к локальным переменным изаграфа тоже возможен, только нужно указать имя программы main. IP-адрес ПЛК нужно будет поставить реальный, не изменяя порт 1200.
11.2 Далее:
// считывает ответ ПЛК
// эту функцию следует указать как аргумент f_ok для PlcIO()
function on_plc_read(data) {
InBuf = data; // не удаляйте эту строку, это сохранит кэш низкоуровневых адресов тэгов и
// ускорит их поиск на стороне ПЛК
glob_ana = data[0]["value"];
prg1_bool = data[1]["value"];
prg2_msg = data[2]["value"];
}
Это функция-обработчик события успешного чтения данных. Вытаскивает из ответа нужные данные и кладёт их в соотв.переменные. Снова прописываем реальные имена:
function on_plc_read(data) {
InBuf = data; // не удаляйте эту строку, это сохранит кэш низкоуровневых адресов тэгов и
// ускорит их поиск на стороне ПЛК
do_left = data[0]["value"];
do_right = data[1]["value"];
do_down = data[2]["value"];
do_up = data[3]["value"];
}
11.3 Вот этот код необходимо пояснить:
// точка входа программы
$(function() {
Mns.setup({
onRdy: init,
onBtnClick: click, // обработчик ввода от кнопок
onInput: input // обработчик ввода от InputText
});
});
// запускается из mns.js при завершении загрузки mns.svg
function init() {
setInterval(function() {cycle();}, 1000);
}
// срабатывает по нажатию кнопки
function click(id) {
alert("You press button " + id);
}
// срабатывает по вводу в inputText
function input(id) {
alert("You input '" + Mns.inp[id].get() + "' into " + id);
}
// рабочий чикл программы, настраивается в init()
function cycle() {
// опросить ПЛК
PlcIO(PlcIP, InBuf, on_plc_read, f_error);
// записать в ПЛК
OutBuf[0]["value"] = 123;
OutBuf[1]["value"] = "ok";
OutBuf[2]["value"] = true;
PlcIO(PlcIP, OutBuf, on_plc_write, f_error);
}
Строка $(function() {}) это точка входа в данный скрипт и отсюда всё начинает крутиться: вызывается библиотечная функция Mns.setup(), та вызывает init(), init() создаёт нить, запускающую функцию cycle() с интервалом 1000мС.
Немного модифицируем этот код, начиная с init():
// запускается из mns.js при завершении загрузки mns.svg
function init() {
setInterval(function() {cycle();}, 100);
}
// срабатывает по нажатию кнопки
function click(id) {
var cmd;
switch(id) {
case 'stop':
cmd = 0;
break;
case 'left':
cmd = 3;
break;
case 'right':
cmd = 4;
break;
case 'forward':
cmd = 2;
break;
case 'revers':
cmd = 1;
break;
default:
return;
}
OutBuf[0]["value"] = cmd;
PlcIO(PlcIP, OutBuf, on_plc_write, f_error);
}
// срабатывает по вводу в inputText
function input(id) {
alert("You input '" + Mns.inp[id].get() + "' into " + id);
}
// рабочий чикл программы, настраивается в init()
function cycle() {
// опросить ПЛК
PlcIO(PlcIP, InBuf, on_plc_read, f_error);
}Во-первых, увеличили частоту вызова cycle(), которая производит опрос ПЛК. Во-вторых, сделали обработку нажатия кнопок. Помните свойство onclick в виджете button, мы прописали там аргументы "left","right" и т.д? Теперь эти строковые значения прилетают сюда, мы преобразовываем их в код команды и посылаем в ПЛК. Ну и в-третьих, убрали из cycle() запись данных, т.к. запись в ПЛК будет теперь производиться по факту нажатия кнопок в функции click().
11.4 Ну и осталась только функция update_screen(), которая вызывается при успешном чтении:
Чтобы в целях отладки отвязаться от ПЛК, давайте приведём функции cycle() и update_screen() к такому виду:
// рабочий чикл программы, настраивается в init()
function cycle() {
// опросить ПЛК
PlcIO(PlcIP, InBuf, on_plc_read, f_error);
/* отладка ...*/
update_screen();
do_up = (OutBuf[0]["value"]==2)? true:false;
do_down = (OutBuf[0]["value"]==1)? true:false;
do_left = (OutBuf[0]["value"]==3)? true:false;
do_right = (OutBuf[0]["value"]==4)? true:false;
/* ... отладка */
}
function update_screen() {
Mns.dyn["led1"].set({f: do_left|do_right|do_up|do_down ? "green" : "black"} );
Mns.dyn["ar"].set({f: do_right? "green" : "gray"} );
Mns.dyn["al"].set({f: do_left? "green" : "gray"} );
Mns.dyn["ab"].set({f: do_down? "green" : "gray"} );
Mns.dyn["af"].set({f: do_up? "green" : "gray"} );
}
Строки между /* отладка */ временные, для отладки, затем их нужно будет поудалять. Отладочный код устанавливает значения переменных do_* в соответствии с нажатой кнопкой, чтобы увидеть это на мнемосхеме без подключения ПЛК.
Теперь щёлкните по файлу index.html и убедитесь в работоспособности интерфейса:
Если этого не произошло, то скорее всего по причине несовместимости браузера. Это точно не будет работать под ms explorer-ом. Я пользуюсь мозиллой, но тестировал также Opera и Chrome, всё работало. Если у вас и под ними не работает, то причиной может быть только устаревшая версия браузера. Если же и с новой версией что-то пошло не так, можно попытаться локализовать ошибку в отладчике браузера.
Теперь по содержимому update_screen().
Разработчик библиотеки все обращения к виджетам привёл к одному виду:
Mns.<слой>[].set({<свойство>: <значение>});
Свойства такие:
t - текст
v - числовое значение
f - цвет заливки
Если вам не понятны конструкции вида
do_left|do_right|do_up|do_down ? "green" : "black", то вместо таковых в своей работе можете использовать аналоги:
if(do_left==true || do_right==true || do_up==true || do_down==true ) {
Mns.dyn["led1"].set({f:"green"});else
Mns.dyn["led1"].set({f:"black"});
}Как видите, громоздко получается, поэтому лучше всё-таки продвинуть свой жабаскрипт.
12. Вот теперь веб-проект, можно сказать, готов. Уберите отладочные строки в index.js и загружайте проект изаграфа в контроллер, как это показано здесь. И не забудьте грузить в ПЛК не только tic-код, но и символы приложения, эта информация нужна html-шлюзу таргета для разрешения имён запрашиваемых тегов.
IP-адрес в index.js должен соответствовать вашему ПЛК. Кстати, таргет можно запустить и на ПК!
Если всё пошло по маслу, щёлкнув по index.html вы увидите полностью рабочий проект, пользуйтесь на здоровье!
13. Теперь осталось только запаковать папку web в zip-архив (в архиве должно быть содержимое каталога web, но не каталог web с содержимым!) и присоединить его в проекту nScada как ресурс. Делается это так:
- копируем web.zip в папку проекта nScada (например c:\IsaWin\Apl\nScada)
- открываем Создать->Ресурсы окна программ и вводим
BinaryFile 'web_zip'
BEGIN
AnyTarget
From 'web.zip'
To 'web.zip'
End
- создаём и загружаем проект в ПЛК
Ну вот и всё. Теперь набрав в браузере IP нашего ПЛК, получим то что видели в предыдущем шаге, но уже полностью размещённое в контроллере и доступное с любого другого подключенного устройства сети (включая wifi), будь то планшет или мобильник.
Если для наглядности подключать к задействованным каналам GPIO светодиоды, то желательно делать это через ограничивающие ток резисторы номиналом 200...300 ом.
P.S. Всё вышеописанное доступно в виде похожего готового проекта "nScada", входящего в состав архива библиотеки для ISaGRAF Workbench (архив здесь, описание здесь), т.е. скачав эту библиотеку можно вытащить оттуда данный проект. Веб-составляющие файлы находятся в архиве web.zip директории проекта.
P.S.2 Данный пример ни в коем случае не претендует на какую-либо практическую завершённость, просто здесь показан в действии иструмент, позволяющий разрабатывать вполне полезные вещи на базе вполне доступного железа и софта.
P.S.3 В следующем посте постараюсь изыскать и привести пример более близкий к тематике умного дома.
Когда у тебя есть датчик радиации и время
Как обещал в комменте к предыдущему посту, расскажу про наблюдения за радиационным фоном в течение года.
В общем сразу после начала работы датчика, стал наблюдать редкие всплески радиационного фона в 1,5 - 5 раз выше обычных 10мкЗв/ч. Сначала списал на какие-нибудь космические лучи или солнечную радиацию (в чем совсем не смыслю, потому допускаю возможность :) ), но через пару-тройку месяцев заметил некоторые закономерности. Субъективно всплески были в основном в четверг и в районе 14 часов дня. Ну что ж, база данных со значениями за год есть, надо как-то выяснять в чем дело.
Для анализа выбрал значения показаний датчика от 17 мкЗв/ч (в 1,7 раза выше фона) и выше за год, получилось 100 значений. Выгрузил значения в Excel и сделал графики:
График суммарных значений всплесков по времени суток
Казалось бы, вроде, похоже на влияние Солнца - четко дневное время. Однако, не тут-то было.
График суммарных значений по дням недели
Вряд ли Солнце позволяло себе отдыхать по воскресеньям и особо усердствовало по четвергам. Т.е. получается, что в дело вступает человеческий фактор. Ну, а тут уж можно дать волю фантазии:
- радиоактивный пенсионер-сосед выходит в течение дня покурить на соседний балкон;
- передвижная рентген-установка катается по улице;
- э/м наводки на схему датчика;
- скачки напряжения в сети;
Но и тут не все гладко: с февраля всплесков больше не было :). Сомневаюсь, что кончились наводки или скачки напряжения.
И бонус: пузырьковая диаграмма. Размер круга - сила всплеска, по горизонтали время, по вертикали день недели.
Кто разгадает причину всплесков - тому плюсик!
ПС: Попытался выложить статью на geektimes, оказалось она не достаточно интересна.() Как-нибудь через годик-другой еще раз попробую.



























