149 выпуск журнала MagPi
скачать
Сообщения pi
-
Raspberry Pi 5 16 Gb RAM
Первые версии Raspberry Pi 5, появившиеся осенью 2023 года, были представлены двумя модификациями - c 4 и 8Гб оперативной памяти. Летом 2024 года к ним добавилась модификация с 2Гб оперативной памяти.
Сегодня начинаются продажи модели Raspberry Pi 5 с 16Gb оперативной памяти,
официальная цена - 120$Трехкратный прирост производительности между Raspberry Pi 4 и Raspberry Pi 5 открывает возможности для таких приложений, как большие языковые модели и вычислительная гидродинамика, которые выигрывают от большего объема памяти на ядро. И хотя Raspberry Pi OS оптимизирована для низких базовых требований к памяти, тяжелые дистрибутивы, такие как Ubuntu, получают значительное преимущество от увеличенной емкости памяти при использовании в качестве настольной системы.
Появление 16Гб версии Raspberry Pi 5 стало возможным благодаря новой ревизии (D0) процессора Broadcom BCM2712, который теперь поддерживает работу с чипами оперативной памяти объёмом более 8Gb
-
Установка
Образ операционной системы для записи на SD-карту
https://updates.volumio.org/pi/volumio/3.785/Volumio-3.785-2024-12-16-pi.zipVolumio — это операционная система, созданная специально для воспроизведения музыки. Она:
- Поддерживает аудиофайлы высокого разрешения (FLAC, WAV, DSD и т. д.).
- Работает как медиасервер и аудиоплеер.
- Имеет удобный веб-интерфейс для управления (с любого устройства через браузер или приложение).
- Поддерживает стриминговые сервисы, такие как Spotify, TIDAL, Qobuz и интернет-радио.
- Легко интегрируется с аудиофильскими USB-ЦАПами (цифро-аналоговыми преобразователями) для максимального качества звука.
-
Raspberry Pi и умный дом
Многие пытаются собрать «Умный дом» своими руками. При выборе системы стоит учитывать не только ассортимент и стоимость конечных устройств, но и возможности контроллера.
Большинство контроллеров сразу готовы к работе «из коробки», но представляют ограниченные возможности. Однако нередко именно гибкость и возможность лёгкой интеграции является основополагающим критерием при выборе. И вот, появился долгожданный «кубик Lego» для систем автоматизации на базе технологии Z-Wave, который обладает желаемой гибкостью и в то же время большим функционалом и низкой ценой. Плата расширения RaZberry для Raspberry Pi, превращает самый популярный и дешёвый мини-компьютер в Z-Wave контроллер домашней автоматизации.
RaZberry — это решение три в одном:- плата с трансивером Z-Wave ZM3102
- прошивка для ZM3102, расширяющая возможности стандартных прошивок для стиков
- ПО Z-Way
Железо
В ОС Linux RaZberry виден как com-порт /dev/ttyAMA0. Плата по сути состоит из
- трансивера ZM3102,
- памяти EEPROM для хранения данных сети Z-Wave,
- PCBA антенны
- коннектора ножек UART для GPIO Raspberry Pi.
Реально используется только ножки Vcc, Gnd, TX и RX. Остальные ножки не используется для работы платы и лишь помогают её крепче зафиксировать. В теории эти ножки можно использовать для других нужд.
Прошивка
Плата предоставляет интерфейс полностью совместимый с Sigma Designs Serial API, что даёт возможность использовать не только прилагаемое ПО Z-Way, но и любое другое ПО для Z-Wave (Open Z-Wave, LinuxMCE, FHEM или самописное), а также облачный сервис Z-Cloud (см. инструкцию).
Плата также предоставляет расширение протокола Sigma Designs Serial API от Z-Wave.Me, которое необходимо для работы ПО Z-Way.
Прошивка также позволяет обновлять себя по UART, что позволит не только исправить возможные баги в будущем, но и сменить версию прошивки с той, что установлена по умолчанию (SDK 4.54.01) на более старую 5.03, не имеющую полезных функций NWI, Explorer Frame и Random HomeId, но включающую функционал SUC/SIS. (Для внимательных: да, я не ошибся, 4 > 5Программное обеспечение
Z-Way устанавливается поверх Raspbian wheezy путём запуска команды
wget ‐q ‐O ‐ http://razberry.z-wave.me/install | sudo bash
Скрипт установки
- поставит Z-Way в /opt/z-way-server
- пропишет в /etc/init.d/Z-Way скрипт для запуска,
- добавит его в авто запуск и настроит порт ttyAMA0.
После перезагрузки (для применения настроек ядра для ttyAMA0 — по умолчанию Raspbian использует UART для консоли) сервер готов к работе.
В браузере откройте http://IP_OF_RASPBERRY:8083 и начните строить сеть Z-Wave.
Рассмотрим подробней поставляемое в комплекте с RaZberry ПО Z-Way.
Оно состоит из нескольких частей:- библиотека libzway — основа движка Z-Wave, предоставляющая C API для простой работы с Z-Wave (зависит от pthreads, zlib, openssl)
- библиотека libzwayjs — биндинг между C и JavaScript движком Google V8. Предоставляет простое JS API для работы с сетью Z-Wave (зависит от libv8 и libzway)
- библиотека libzwayhttp — HTTP сервис для обслуживания внешних клиентов, в том числе пользовательские интерфейсы. Предоставляет JSON API (зависит от libmicrohttpd, openssl, libzwayjs и libzway)
- main.cpp — обвязка для запуска всех сервисов вместе, чтения конфигов и параметров командной строки
Такая структура позволяет использовать разные уровни интеграции с составными частями Z-Way.
Для проектов, где важна производительность, доступен API уровня C (в комплекте есть заголовочные .h файлы для libzway), для проектов, где нужна оперативная разработка, проще использовать JS API.
Важно, что оба интерфейса имеют сходную структуру, что позволяет просто портировать код с JavaScript на C после быстрого прототипирования.Далее я опишу API уровня JavaScript и покажу, как создавать простые правила автоматизации. Интерфейс уровня C останется за рамками данной статьи.
Стоит заметить, что синтаксис в движке JavaScript Z-Way на стороне сервера сделан по аналогии с тем, что было реализовано для Z-Cloud на стороне клиента — см. описание API Z-Cloud.
Для дальнейшего чтива предполагается, что читатель уже знаком с особенностями протокола Z-Wave (см.подробное описание протокола Z-Wave).
Всё относящееся к Z-Wave в пространстве имён JavaScript находится в глобальном объекте zway, который предоставляет полное дерево данных и методов над устройствами Z-Wave.
Дочерний объект controller, содержит данные специфические для контроллера Z-Wave, а также список устройств devices.
Каждое устройство содержит структуру данных (data), а также список каналов устройства (instances).
Каждый канал имеет список Классов Команд Z-Wave, поддерживаемых устройством. На Классе Команд имеются методы для вызова функций (Set, Get, ...), а также дерево данных (data), где хранится вся информация о Классе.
Графически это можно иллюстрировать примерно так (картинка из документации):
Структура API асинхронна и делится на две части:
- отправка команд и запросов
- получение событий изменения состояний
Отправка команд осуществляется запросами вида
zway.devices[2].instances[0].commandClasses.Basic.Set(0)
(этот пример выключит свет).
Функция .Get() отправит запрос значения устройству.zway.devices[2].RequestNodeNeighbourUpdate() попросит устройство обновить соседей, а командаzway.AddNodeToNetwork(1) запустит процесс добавления нового устройства к сети.
Более подробно все команды описаны в документации на странице документации проекта RaZberry.
Каждому запросу можно добавить два дополнительных параметра: callback-функции для успешной и неудачной отправки.
Команды ставят в очередь на отправку соответствующие пакеты. Отправка осуществляется через Sigma Designs Serial API, реализованную на плате расширения RaZberry. Вся магия Z-Wave скрыта под этим уровнем абстракции: для устройств на батарейках эти пакеты помечаются как ожидающие пробуждения, для шифрования идёт предварительный обмен ключами, для экономии заряда батареек и времени в эфире некоторые пакеты стыкуются вместе и многое другое…
Как и в любом протоколе, в Z-Wave много своих тараканов, которые все находятся под ковром API Z-Way и не вылезают оттуда.
Все полученные от устройств данные записываются в дерево data, относящееся к устройству или Классу Команд.
Каждый элемент дерева data имеет атрибуты value (значение элемента), updateTime и invalidateTime (timestamp дат обновления и устаревания значения), name (имя). Структура дерева тоже подробно описана в документации.
Для получения уведомлений об изменении значений дерева существует система подписок на события. Функция bind для каждого элемента дерева позволяет привязать callback функцию к изменению данных.
zway.devices[2].instances[0].commandClasses.Basic.data.level.bind(function (type[, arg]) {}, [arg, [watchChildren=false]]);Опциональный аргумент arg, передаваемый bind будет передан в callback функцию и пригодится для передачи дополнительных параметров для разделения разных событий, имеющих общий callback-обработчик. Параметр watchChildren (true или false) позволяет отслеживать не только изменения данного элемента дерева, но и дочерних. Объект this в callback функции — это элемент дерева data, на котором запускается bind: this.value — значение, this.updateTime — дата последнего обовления и т.д. Аргумент type содержит битовую маску типа изменения (изменён, обновлён, удалён, устарел,… — подробно все значения описаны в ZDefsPublic.h, который входит в комплект ПО).Аналогично есть функция bind на глобальном объекте zway, которая позволяет отслеживать изменения в массивах devices, instances и commandClasses:zway.bind(function(type, nodeId, instanceId, commandClassId) {}, [mask = 0xffff])Аргумент type указывает на характер изменения (добавлено/удалено устройство/канал/класс команд или сохранён файл с деревом данных на диск (ZDDX-файл). Триплет nodeId, instanceId, commandClassId указывает на изенённый объект.Отписаться от событий можно функцией unbind.Для упрощения синтаксиса можно опускать слова commandClasses, instances[0] (именно нулевой канал!), .value(level == 0 аналогично level.value == 0, но при JSON-сериализации без .value будет сериализован весь элемент дерева с его атрибутами, а только значение).
Стоит обратить внимание, что глобальный объект zway является нативным в v8, т.е. это не обычный JavaScript объект: у него можно лишь менять данные элементов дерева. Все остальные изменения в дереве игнорируются.Приведём несколько примеров:Запуск shell-команд при получении контроллером событий Basic Set от других устройств сети (например, выключатель ассоциирован с контроллером с каналом 1 при помощи MultiChannelAssociation)var instanceId = 1; var ctrlNodeId = zway.controller.data.nodeId.value; // Get controler Node Id if (zway.devices[ctrlNodeId] && zway.devices[ctrlNodeId].instances[instanceId]) { // Check that instance object exists var basicCC = zway.devices[ctrlNodeId].instances[instanceId].Basic; if (basicCC) { // check that Basic exists basicCC.data.level.bind(function() { // bind to Basic level value system("echo " + this.value); }); } }
Автоматическое отключение диммера света через 10 секунд после включения (для реле используйте SwitchBinary вместо SwitchMultilevel). (Здесь предполагается, что устройство умеет отправлять отчёты и ассоциировано с контроллером)
var nodeId = 2; var instanceId = 0; var _tmr = null zway.devices[nodeId].instances[instanceId].SwitchMultilevel.data.level.bind(function() { var node = args[0]; var instance = args[1]; if (_tmr) { clearTimeout(_tmr); } _tmr = null; if (this.value > 0) { _tmr = setTimeout(function () { zway.devices[nodeId].instances[instanceId].SwitchMultilevel.Set(0); _tmr = null; }, 10*1000); } });
тут стоит обратить внимание, что для запуска данного кода несколько раз нужно вводить массив _tmr для каждого устройства/канаоа)
Выполнение JavaScript кода
Куда вставлять этот JavaScript код? Есть несколько способов выполнить данный код:Записать код в файл и положить его на SD-карту Raspberry Pi в папку /opt/z-way-server/[ваша папка]. Далее этот код можно исполнить из automation/main.js: executeFile(pathToJavaScriptFile).Вы также можете прописать ваш собственный JavaScript файл в config.xml вместо родного файла RaZberry.Отправить его по HTTP через Z-Way JSON API
Теперь опишем Z-Way HTTP/JSON API
Данный интерфейс взаимодействия с сервером Z-Way использует протокол HTTP и формат JSON для передачи данных. С его помощью не сложно создать графические интерфейс для сервера автоматизации.Команды кодируются прямо в URL запроса, а ответы приходят в привычном аяксерам JSON формате.Запрос
/ZWaveAPI/Data/ предоставляет JSON структуру полного дерева обновлений с момента времени . Она имеет вид{ path1: object1, path2: object2, ... updateTime: }
- Здесь pathN — это путь к изменившемуся элементу дерева,
- objectN — новое значение этого элемента.
- updateTime — время формирования обновлений (его нужно указать в следующем запросе, чтоб получить обновления)
Если запросить /ZWaveAPI/Data/0, то сервер вернёт полную структуру данных.
Запрос /ZWaveAPI/Run/ запускает JavaScript код zway..
Этот запрос аналогичен более общему /JS/Run/ и создан для совместимости с API сервиса Z-Cloud.
Запрос /JS/Run/ выполняет в v8 движке и возвращает в виде JSON результат выполнения этой команды.
Другие команды описаны в документации.
Несколько примеров:http://localhost:8083/ZWaveAPI/Run/devices[2].SwitchMultilvel.data.level.value
— возвращает последний полученный от устройства уровень яркости (стоит перед чтением послать
SwitchMultilevel.Get())http://localhost:8083/ZWaveAPI/Run/devices[3].instances[1].SensorMultilvel.data.level.value
— возвращает последнее полученный от устройства значение датчика (стоит перед чтением послать
SensorMultilevel.Get())http://localhost:8083/ZWaveAPI/Run/devices[2].Basic.Set(0)
— выключает устройство
Напомним, instances[0], commandClasses и value можно опустить.!Не забывайте, что некоторые символы требуется явно кодировать перед отправкой (url encode): например, + { }.
Вместе с софтом поставляется базовый интерфейс для браузера. Он тоже использует Z-Way JSON API для взаимодействия с сервером. Его код удобно использовать для изучения работы API. Также может оказаться полезным расширение для jQuery для отслеживания обновлений дерева, полученных запросом/ZWaveAPI/Data/Вот так выглядит взаимодействие разных слоёв системы (картинка из документации):
Через некоторое время планируется написание JS скриптов для автоматизации, предназначенных для простых пользователей (кривые заготовки уже лежат в папке automation). Их можно будет использовать совместно с собственными скриптами пользователя, т.е. собственные скрипты можно уже начинать писать и использовать в ваших проектах.
Где взять?
Raspberry Pi продаются на сайтах RS components или Farnell.Плата RaZberry и другое Z-Wave оборудование доступно в интернет-магазине Z-Wave.Me и других.
Пора автоматизировать!
Уверен, RaZberry станет удобным решением для построения бюджетных систем автоматизации на базе Z-Wav
-
Установка
Операционная система для домашнего кинотеатра с плеером Kodi (XBMC), продолжение ОС OpenELEC, разработка которой была остановлена
-
Установка К - Офиса
Запутался я с пакетами К-Офиса и поэтому решил поставитьсразу по сети с инета. Запустил на Raspy с консоли:
sudo apt-get install koffice
С первой попытки не удалось. Половина пакетов не находилась, либо не ставилась. В конце установки была рекомендация обновиться либо повторить попытку.
Обновился:
sudo apt-get update
Запустил опять установку:
sudo apt-get install koffice
Через десять минут примерно офис был установлен.
Впечатления: есть всё что надо, но тормозит конкретно при открытии приложений.
С графикой работать не вариант. Полный тормоз.
Вывод: на Распи применять проблематично.
-
Raspberry Pi подключение GPS USB приемника
Недавно нашел у себя USB-GPS приемник, если не ошибаюсь модель от GlobalSat BU 353. Вот и решил его подключить к Raspberry Pi. После подключения он обнаружился хорошо , проблем вообще не было никаких:
#lsusb Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. Bus 001 Device 004: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial PortBus 001 Device 005: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Вот наш девайс: Prolific Technology, Inc. PL2303 Serial Port
В /dev/ появилось новое устройство ttyUSB0, к нему и будем подключаться, насколько я помню, у большинства подобных девайсов скорость 4800. Ниже скрипт на PHP с использованием свободной библиотеки php_serial.class.php, с ней довольно просто работать.
#!/usr/bin/php5 // подключаем библиотеку require("php_serial.class.php"); $serial=new phpSerial(); // выбираем порт $serial->deviceSet("/dev/ttyUSB0"); // скорость $serial->confBaudRate(4800); // ниже параметры как правило стандартные $serial->confParity("none"); $serial->confCharacterLength(8); $serial->confStopBits(1); $serial->confFlowControl("none"); // открываем порт $serial->deviceOpen(); $loop=1; while($loop==1){ $get=$serial->readPort(); // если включить print , то будут все строки NMEA протокола // print $get; if(substr($get,1,5) == "GPGGA") { // если включить print , то будет только $GPGGA //print $get; // парсим строку list($gga,$time,$lat,$NS,$lng,$EW,$state)=explode(",",$get); /* расшифровка строки $GPGGA,155004.000,4253.9372,N,04108.1511,E,1,08,1.2,18.4,M,27.4,M,,0000*68$GPGGA -- название пакета 155004.000 -- время гринвич 4253.9372,N,-- широта 04108.1511,E,-- доолгота 1-- если 1 то данные достоверны , если 0 то данные сомнительные в данном случае это переменная $state остальное можно прочитать в справочниках по NMEA протоколу,08,1.2,18.4,M,27.4,M,,0000*68*/ if($state == "1") { /* сохраняем в текстовый файл , но не обязательно, можно закомментировать и использовать перенаправление через print, типа #./gps.php > куда то, или #./gps.php | proga.sh */ // путь куда положить файл $fp=fopen('/h/pi/robot/gps/gga.txt','wt'); if($fp) { fputs($fp,$get); // print $get; } fclose($fp); //ставим задержку 10 секунд , но реально лучше ставить минуты 3-5 , зависит от задачи sleep(10); } }} $serial->deviceClose();?>
Это был простой пример , как получить данные из GPS приемника, обработку полученных данных можно реализовать разными способами, равно как и запуск скрипта. Я поставил периодичность запросов 10 секунд чисто для примера, хотя можно убрать sleep(10) и запускаться через cron.
Ниже рабочий пример скрипта для отображения координат на картах Google.
// получим данные из текстового файла $gga=shell_exec("cat /home/pi/robot/gps/gga.txt"); // пропарсим строку list($gga,$time,$lat,$NS,$lng,$EW,$state)=explode(",",$gga); // показываем полученные данные print "Time: ".$time." Lat: ".$lat." Lang: ".$lng." State: ".$state; // преобразуем широту и долготу к формату Google $Lat=round(floor($lat/100)+(($lat/100)-floor($lat/100))/0.6,6); $Lng=round(floor($lng/100)+(($lng/100)-floor($lng/100))/0.6,6); // диаметр круга $Acc="20"; // дальше обработка данных средствами Google API 3 print " Google Maps JavaScript API v3(Street View) function initialize() { var moscow = new google.maps.LatLng(".$Lat.",".$Lng."); var mapOptions = {center: moscow,zoom: 18,mapTypeId: google.maps.MapTypeId.SATELLITE,panControl: false,zoomControl: true,mapTypeControl: false,scaleControl: false}; var map = new google.maps.Map(document.getElementById(\"map_canvas\"), mapOptions); var circle = new google.maps.Circle({radius: ".$Acc.",map: map, center: moscow,fillOpacity: 0.2,strokeOpacity: 0.5,strokeColor: '#00CCCC', fillColor: '#33CCFF', strokeWeight: 1 }); var marker = new google.maps.Marker({position: moscow,map: map,title:\"Lat:".$Lat." Long:".$Lng." Acc:".$Acc." \" }); } "; ?>
-
Управление рабочим столом Raspberry Pi.
Для управления нам нужно скачать файл xrdp вот здесь http://www.xrdp.org/ далее закинуть файл на Raspberry Pi и ввести в консольной меню
sudo apt-get install xrdp
потом заходим Подключение к удаленно рабочему столу искать у виндовсе и вуаля у нас есть рабочий стол Raspberry Pi.Вот здесь можете глянуть на моё видео
-
Raspberry Pi. Расширяем дисковое пространство
Одноименная публикация находится у меня в блоге. Там более подробно это расписано.А здесь -- для продвинутых я перечисляю только основные шаги.
- Заводим на Яндекс-Диске аккаунт. Как это сделать -- читайте тут http://disk.yandex.ru/how-to/2. Устанавливаем модуль для работы с удаленной файловой системой (со своей "удаленной помойкой"):
$ sudo apt-get install davfs2
- Создаем директорий, куда будет проецироваться содержимое "помойки":
$ mkdir yandex.disk
- Подключаем "помойку" командой:
$ sudo mount -t davfs \ -o uid=alex,gid=alex \ # Здесь вы должны подставить имя своей учетной записи https://webdav.yandex.ru \ # Это ссылка на ресурс удаленной помойки /home/alex/yandex.disk # А это указатель на локальный директорий
Можно прописать эту команду в.profile или занести параметры в /etc/fstab. Тогда при загрузке Малинукса все сразу само срастается.- Если вы предпочетаете юзать графическую консоль, то лучше зайдите ко мне в блог. Там есть и описание, и имеются скриншоты. http://zhevak.wordpress.com/2013/08/27/raspberry-pi-расширяем-дисковое-пространство/
Я приношу всем свои извинения -- я потратил полчаса времени, но так и не смог осилить форматирование.
-
RE: Основы GPS навигации на Raspberry Pi
ответ
Отлично. То что нужно. Как только приедет, сразу буду пробовать, про JSON и сокеты порадовало, планирую получать данные прямо на php. -
RE: Основы GPS навигации на Raspberry Pi
Небольшое дополнение: в Raspbian Jessie нет файла inittab. Чтобы убрать терминал с UART интерфейса нужно выполнить команду:
sudo systemctl stop serial-getty@ttyAMA0.service
и запретить запуск при последующих загрузках системы:
sudo systemctl disable serial-getty@ttyAMA0.service
-
Основы GPS навигации на Raspberry Pi
Привет. Сегодня будем рассматривать вопрос использования gps навигации на Raspberry Pi. Для того, чтобы превратить Raspberry Pi в gps навигатор потребуется:
GPS приёмник
Существует 2 варианта:
-
USB gps приёмник (подключается к USB порту, http://raspberrypi.ru/220-raspberry-pi-podklyuchenie-gps-usb-priemnika - вот есть небольшая статья по использованию USB GPS)
-
UART GPS модуль (подключается к линиям GPIO: 5v, GND, RX, TX). Мне больше нравится второй вариант, т.к он дешевле и меньше по размеру. Я использую GPS модуль на базе чипа u-Blox Neo 6M с подключаемой внешней антенной (покупал тут)
Подключается очень просто:
VCC-5V GND-GND RXD-TXD TXD-RXD.
На модуле 2 светодиода - зелёный (включается при подаче питания), синий (включается при подаче питания, начинает мигать когда установлено соединение со спутниками). GPS сигнал сам по себе очень слабый, поэтому в помещении антенну нужно вынести как можно ближе к окну и направить в небо (если вы находитесь в помещении)
В ОС Raspbian UART интерфейс представлен устройством /dev/ttyAMA0 (UPD: в новых моделях, начиная с Raspberry Pi 3 - /dev/tty/S0 ). Если вы используете Raspbian, то там на UART'е висит терминал. Чтобы освободить UART интерфейс для GPS приёмника выполняем следующие процедуры:
1 . В /etc/inittab эту строчку закоментить или удалитьT0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
2 . В /boot/cmdline.txt console=ttyAMA0,115200 заменить на console=tty1 После того, как модуль подключён устанавливаем скорость UART 9600kbit/s
stty -F 9600 /dev/ttyAMA0
Теперь, если всё правильно подключено, и в консоли набрать команду cat /dev/ttyAMA0 , то в выводе побегут сообщения в форматеNMEA, которые GPS приёмник передаёт на RasPi.
2. Навигационное программное обеспечение
gpsd - служба, которая принимает данные в NMEA формате от GPS модуля и "расшаривает" доступ к ним для стороннего программного обеспечения. Один из вариантов получения данных от gpsd - это получение их от сокет-сервера, который gpsd поднимает на порту 2947 (по умолчанию), в "человеческом" JSON формате. Значительная часть навигационного ПО требует наличия gpsd, установить можно из репозитория: sudo apt-get install gpsd После установки запускаем службу: gpsd /dev/ttyAMA0
Navit
К сожалению, качественного навигационного программного обеспечения (Navitel, iGo и т.д) для Linux'а практически не существует. Navit - единственное достойное навигационное ПО, которое мне удалось найти. Рассмотрим настройку Navit'а. В первую очередь нам нужно достать для него карты. Самый простой способ получения карт - вырезать нужную область из карты Open Street при помощи сервиса http://maps5.navit-project.org/. На этом сайте слева карта мира, справа панель управления. Выбираем справа пункт "Select" в блоке "Map controls" и мышкой на карте выделяем область, карту которой нужно получить, далее нажимаем кнопку "Get Map" и векторная карта в формате *.img начинается скачиваться. Главный минус таких карт - невозможность поиска точки по адресу. Navit поддерживает также карты Garmin, там такая возможность есть, но до прикручивания гарминовских карт руки у меня пока не дошли. Когда Open Street карта скачена, нужно прописать её в конфиг Navit'a ( /etc/navit/navit.xml Остальным блокам mapset в конфиге поставить параметр enabled=no Ну вот собственно всё. В следующих статьях, попробую рассказать про более детальное конфигурирование Navit'а
7 дорог
Лучшее навигационное ПО для gps навигации от Navikey
Скачать можно отсюда - https://navikey.org/7ways/download
-
-
Компактная ОС для Raspberry Pi
Товарищи, расскажите, кто знает, поэтапно - как собрать собрать через buildroot образ системы для RPi?!
Интересует полный процесс конфигурирования перед сборкой, наличие busybox(полный со всеми сим линками) и иксов.Пакеты планируется собирать в rpm, т.к. в busybox встроен этот менеджер пакетов, но на другой машине, по этому ничего лишнего в системе ни будет нужно, за исключением автоматического подцепления usb-устройств и файловых систем.
Хочется собрать свою ОС, в которой все будет по минимуму, но то, что нужно, ведь с такой малой мощностью, каждый бит ОЗУ важен.
-
Установка Python 3.4 и OpenCV 3.0 на Raspbian
Решил освоить raspberry, при этом не использовать компилируемые языки, выбор невольно остановился на Python 3. Поскольку изначально планировалось задействовать OpenCV, то на текущий момент это возможно только с OpenCV 3.0 beta которая рекомендует использовать с ней Python 3.4. Ни того ни другого в репозитории нет и пришлось собирать из исходников, по пути осваивая данный процесс. Идущим по моим следам посвящается:
Установка Python 3.4
Устанавливаем пакеты необходимые для Python:
sudo apt-get install zlib1g-dev libbz2-dev libncurses5-dev libreadline6-dev libsqlite3-dev libssl-dev libgdbm-dev liblzma-dev tk-dev
Качаем и распаковываем исходники:
wget https://www.python.org/ftp/python/3.4.2/Python-3.4.2.tgz tar -zxvf ./Python-3.4.2.tgz cd ./Python-3.4.2/
Более свежие исходники можно взять с оф.сайта
Готовим к компиляции
./configure --prefix=/usr/local
Компилируем
make
Ближе к концу компиляции может появится сообщение о том что каких-то пакетов не хватает: "the necessary bits to build these modules were not found:" их можно до установить если они вам нужны, после чего повторить процедуру.
Cобираем пакет
sudo make install
По правильному надо собирать при помощи checkinstall, но не получилось как ни старался. setup_tools и pip ставятся автоматически
Создаем удобные симлинки в системе:
rm /usr/bin/python3 ln -s /usr/local/bin/python3 /usr/bin/ ln -s /usr/local/bin/pip3 /usr/bin/
OpenCV необходим питоновский модуль numpy - ставим
pip3 install numpy
Устанавливаем необходимые OpenCV пакеты (поставил все что просил)
sudo apt-get install cmake git build-essential pkg-config libpng12-0 libpng12-dev libpng++-dev libpng3 libpnglite-dev \ zlib1g-dbg zlib1g zlib1g-dev pngtools libtiff4-dev libtiff4 libtiffxx0c2 libtiff-tools libeigen3-dev libjpeg8 \ libjpeg8-dev libjpeg8-dbg libjpeg-progs ffmpeg libavcodec-dev libavcodec53 libavformat53 libavformat-dev \ libgstreamer0.10-0-dbg libgstreamer0.10-0 libgstreamer0.10-dev libxine1-ffmpeg libxine-dev libxine1-bin \ libunicap2 libunicap2-dev swig libv4l-0 libv4l-dev python-numpy libpython2.7 python-dev python2.7-dev libgtk2.0-dev
Скачиваем исходники
wget https://github.com/Itseez/opencv/archive/3.0.0-beta.zip unzip 3.0.0-beta.zip cd opencv-3.0.0-beta
Собираем (поскольку на raspbian несколько питонов, необходимо указать какой из них где)
sudo cmake \ -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local/ \ -D PYTHON2_EXECUTABLE=/usr/bin/python2 \ -D PYTHON2_INCLUDE_PATH=/usr/include/python2.7/ \ -D PYTHON2_LIBRARIES=/usr/lib/python2.7 \ -D PYTHON2_PACKAGES_PATH=/usr/local/lib/python2.7/site-packages/ \ -D PYTHON2_NUMPY_INCLUDE_DIRS=/usr/local/lib/python2.7/dist-packages/numpy/core/include \ -D PYTHON3_EXECUTABLE=/usr/local/bin/python3 \ -D PYTHON3_INCLUDE_PATH=/usr/local/include/python3.4m/ \ -D PYTHON3_LIBRARIES=/usr/local/lib/python3.4/ \ -D PYTHON3_PACKAGES_PATH=/usr/local/lib/python3.4/site-packages/ \ -D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python3.4/dist-packages/numpy/core/include/ . sudo make sudo make install
Cборка на raspberry занимает порядка 10-12 часов. checkinstall как и в случае с питоном работать отказался.
Чтобы Raspberry Camera стала стандартным V4L устройством /dev/video0, нужно выполнить:
sudo modprobe bcm2835-v4l2
RASPBIAN
PYTHON
OPENCV -
Простая установка Windows 10 на Raspberry pi 2
В официальной инструкции Microsoft ( http://ms-iot.github.io/content/win10/SetupRPI.htm )запись образа с Windows 10 IoT для Raspberry Pi 2 на карту памяти (IoT - Internet of Things "интернет вещей") должна производиться с компьютера, на котором установлена Windows 10, что не очень удобно.
В этой статье, я расскажу как можно обойти это ограничение и записать образ с Windows 10 IoT с любой современной версии Windows.-
Регистрируемся на https://connect.microsoft.com/
-
После регистрации переходим сюда - https://connect.microsoft.com/directory/ и нажимаем Join в строке "Windows Embedded Pre-Release Programs Windows Developer Program for IoT", далее переходим в раздел Surveys (https://connect.microsoft.com/windowsembeddedIoT/Surveys) и принимаем 2 лицензионных соглашения, после этого в разделе загрузок (https://connect.microsoft.com/windowsembeddedIoT/Downloads) скачиваем образ Windows 10 (Windows 10 IoT Core Insider Preview Image for Raspberry Pi 2)
-
Распаковываем архив в папку, например С:/Win10ForPi2 4. Скачиваем ISO образ Windows 10 для x32/x64 с рутрекера (например Windows 10 Pro Insider Preview Build 10102 X64)
-
После скачивания открываем образ WinRar'ом и распаковываем содержимое (все файлы кроме вложенных папок и файлов boot.wim и install.win, можно конечно всё распаковать, но ради экономии времени выбираем самое нужное) папки sources в папку с образом Win10 для Raspberry Pi.
-
Запускаем консоль (cmd.exe) c правами администратора. Заходим из консоли в папку с образом Windows 10 IoT для Raspberry Pi 2 и записываем образ утилитой dism.exe, которая оказалась в папке после 4-го шага:
dism.exe /Apply-Image /ImageFile:flash.ffu /ApplyDrive:\\.\PhysicalDriveN /SkipPlatformCheck
, в PhysicalDriveN "N" меняем на номер SD карты в системе дисков. Чтобы узнать номер (у большинства это будет 1), запускаем из командной строки diskpart и выполняем команду
list disk
После записи образа, вставляем карту памяти в Raspberry Pi 2, загружаемся
-
-
Удаленное управление. I2C. Сломаный акселерометр.
Приветствую!
Сегодня я расскажу, как на ferro_remote удаленно сделать i2cdump. i2cdump это мелкая утилита, которая берет номер шины I2C, адрес устройства и дампит на консоль значения всех его регистров.
Для примера я возьму акселерометр на чипе mma7660fc. К большому сожалению девайс издох, и поэтому показывает всякую хрень вместо нормальных значений. Хотя есть вариант, что я что-то не так сделал с подключением. Но так как раньше он работал исправно, считаю, что он сломан. Но не важно. Сломаность акселерометра не мешает показать работу i2cdump.
Я уже его воткнул, включил (установка 7 регистра в значение 1) и делаю штатный вызов на самой распберри: 0x4c - адрес устройства (можно получить при помощи i2cdetect, например)
$ sudo i2cdump -y 1 0x4c No size specified (using byte-data access) 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 18 18 18 18 18 18 18 18 18 18 18 18 57 17 17 17 ????????????W??? 10: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ???????????????? 20: 17 17 17 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? 30: 18 18 18 18 18 18 18 18 18 18 18 18 17 17 17 17 ???????????????? 40: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ???????????????? 50: 17 17 17 17 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? 60: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? 70: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? 80: 18 18 18 18 18 18 18 19 19 19 19 19 19 19 19 19 ???????????????? 90: 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 ???????????????? a0: 19 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? b0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? c0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ???????????????? d0: 18 58 17 17 17 17 17 17 17 17 17 17 17 19 19 19 ?X?????????????? e0: 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 ???????????????? f0: 19 19 19 19 18 18 18 18 18 18 18 18 18 18 18 18 ????????????????
Как видно в регистрах мусор. А раньше там были вполне годные данные.
Вот теперь такую же картинку я получу при помощи lua_client с малины.
И так скрипт, который считает данные с устройства
i2c = fr.client.smbus -- алиас function main( ) local dev = assert(i2c.open(1, 0x4c)) -- откроем шину и установим адрес 0x4c local request = { } -- таблица с запросом. См. пояснение после кода. for i=0, 255 do table.insert( request, i ) -- таблица просто содержит значения от 0 до 255 end local dump = assert(dev:read_bytes( request )) -- вызов. если он успешен, -- в dump мы получим таблицу, в которой будут записаны значения каждого регистра. while i < 256 do -- просто выведем все значения print( i, " = ", dump[i] ) i = i + 1 end end
Про таблицу в запросе read_bytes.
Так как вызов у меня не локальный (я читаю с удаленной системы), у меня есть возможность запросить сразу несколько значений регистров устройства за один вызов, чтоб делать меньше запросов к удаленной системе. Можно спрашивать по одному, но это будет медленнее.
Данный, не слишком длинный и сложный код, читает и выводит значения всех регистров устройства.
$ ./lua_client -s 192.168.1.11:12345 -e i2cdump.lua 0 = 23 1 = 23 2 = 23 ......... skipped ....... 254 = 24 255 = 24
Собственно это все, что от него требовалось, но, немного прикрутив форматирование:
i2c = fr.client.smbus function main( ) local dev = assert(i2c.open(1, 0x4c)) local request = {} for i=0, 255 do table.insert( request, i ) end local dump = assert(dev:read_bytes( request )) -- выведем красивую табличку с hex значениями io.write( " 0 1 2 3 4 5 6 7 8 9 a b c d e f", " 0123456789abcdef\n") local i, r, str = 0, 0, "" io.write( "00: " ) while i < 256 do local b = dump[i] io.write( string.format('%02X ', b ) ) str = str..string.char(b) i = i + 1 if i % 16 == 0 then r = r + 16 io.write( ' ', str:gsub('%c','.'), '\n' ) str = "" if i < 256 then io.write( string.format('%02X: ', r ) ) end end end end
Всё! Получили почти аналог i2cdump.
PS:
$ ./lua_client -s 192.168.1.11:12345 -e i2cdump.lua 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ................ 10: 18 18 18 16 16 16 16 16 16 16 16 16 16 16 16 16 ................ 20: 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 ................ 30: 16 16 16 16 16 57 17 17 17 17 17 17 17 17 17 17 .....W.......... 40: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ................ 50: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ................ 60: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ................ 70: 17 17 17 17 17 17 17 17 17 17 19 19 19 19 19 19 ................ 80: 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 ................ 90: 19 19 19 19 19 19 19 19 19 19 19 19 17 17 17 17 ................ A0: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 ................ B0: 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 18 ................ C0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ................ D0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ................ E0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ................ F0: 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 ................
-
Удаленное управление. SPI. spidev-test
Всем привет, кто тут есть.
Всем, наверняка, известна утилита spidev_test, которой обычно проверяют правильность работы SPI на малине или других железках с линуксами. Скачать ее можно, например, тут.
После скачивания и удачной сборки, можно включить SPI на raspberry (через raspi-config) и замкнуть 2 пина SPI_MOSI и SPI_SOMI (Master Out Slave In и Slave Out Master In) и выполнить то, что собралось в предыдущем шаге.
Должно получиться что-то типа
./spidev_test -D /dev/spidev0.0 spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz) FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DE AD BE EF BA AD F0 0D
Это же самое можно сделать на ferro_remote.
Для начала открою spi
spi = fr.client.spi -- alias local dev = assert(spi.open(0, 1)) -- откроем устройство Теперь нужно передать в устройство какие-то данные. Я возьму кусок, прям из spidev_test local inbuf = "\xFF\xFF\xFF\xFF\xFF\xFF\x40\x00".. "\x00\x00\x00\x95\xFF\xFF\xFF\xFF".. "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF".. "\xFF\xFF\xFF\xFF\xFF\xFF\xF0\x0D"
И далее просто сделаю вызов transfer из таблицы dev
local res = dev:transfer( inbuf )
В res придет уже то, что вернула железка. Если все правильно настроено, то результат должен быть ровно тем же, что и у spidev_test. Для этого добавил функцию hex_dump, которая возьмет строку и выведет ее в красивый вид на консоль.
Итого получилось:
spi = fr.client.spi function hex_dump(buf) for i=1,math.ceil(#buf/16) * 16 do if (i-1) % 16 == 0 then io.write(string.format('%08X ', i-1)) end io.write( i > #buf and ' ' or string.format('%02X ', buf:byte(i)) ) if i % 8 == 0 then io.write(' ') end if i % 16 == 0 then io.write( buf:sub(i-16+1, i):gsub('%c','.'), '\n' ) end end end
function main( ) local inbuf = "\xFF\xFF\xFF\xFF\xFF\xFF\x40\x00".. "\x00\x00\x00\x95\xFF\xFF\xFF\xFF".. "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF".. "\xFF\xFF\xFF\xFF\xFF\xFF\xF0\x0D" local dev = assert(spi.open(0, 1)) local res = dev:transfer( inbuf ) print( "Input: " ) hex_dump( inbuf ) print( "Result:" ) hex_dump( res ) end
Это весь код.
Теперь подключимся к агенту, который запущен на малине и посмотрим. Пины разомкнуты:
$ ./lua_client -s 192.168.3.1:12345 -e spidev-test.lua Input: 00000000 FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF ������@....����� 00000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D ���������������. Result: 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
А теперь замкнуты:
$ ./lua_client -s 192.168.3.1:12345 -e spidev-test.lua Input: 00000000 FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF ������@....����� 00000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D ���������������. Result: 00000000 FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF ������@....����� 00000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D ���������������.
Все как и должно быть.
-
Удаленное управление. I2C. Гироскоп.
И снова здравствуйте.Раз уже сайт совсем умер, то напишу, пожалуй, ещё...А ну, как оживет.
По случаю достал гироскоп на чипе L3G4200D, которым можно управлять как по I2C, так и по SPI. Даташит приводить на него, думаю, не стоит, потому как это легко гуглится. При помощи интерфейса i2c буду получить от него какие-нибудь сведения. Например значения по x, y и z. Что ж еще нужно от гироскопа?
Сначала некоторые константы:
адрес по-умолчанию = 0x69 (можно обнаружить прямо на малине при помощи, например i2cdetect)
5 контрольных регистров 0x20..0x24
Регистры значений X, Y, Z соответственно (0х28, 0х29), (0х2A, 0х2B), (0х2C, 0х2D). Значения занимают каждый по 2 байта в таком виде (Low, High).
Lua:
device_address = 0x69 ctrl_regs = { 0x20, 0x21, 0x22, 0x23, 0x24 } R_xL = 0x28 R_xH = 0x29 R_yL = 0x2A R_yH = 0x2B R_zL = 0x2C R_zH = 0x2D
Чтоб было интереснее сделаем метатаблицу lua для работы с данным чипом. Чтоб работать с гироскопом, как с отдельным объектом.
i2c = fr.client.smbus -- псевдоним для клиента smbus -- пустая таблица без ничего. L3G4200D = { } -- метод new, который вернут новый экземпляр таблицы L3G4200D.new = function( ) inst = { } for k, v in pairs(L3G4200D) do inst[k] = v end -- откроем девайс и сохраним его в нашей таблице. inst.i = assert(i2c.open( 1, device_address )) -- это метатаблица setmetatable( inst, L3G4200D ) return inst end
теперь можно сделать что-то типа
local r = L3G4200D.new( )
Код создаст экземпляр таблицы, откроет девайс и если все нормально, с ним можно работать.
для того, чтоб настроить на работу устройство, добавлю функцию setup
-- настройка состоит в том, чтоб записать нужные регистры нужными значениями. L3G4200D.setup = function( self, scale ) -- настроим таблицу. write_bytes ожидает таблицу, в которой указано [регистр]=значение local data = { [ctrl_regs[1]] = 15, -- включим [ctrl_regs[2]] = 0, -- нормальный режим. По-умолчанию [ctrl_regs[3]] = 8, [ctrl_regs[4]] = scale_values[scale], -- установка scale [ctrl_regs[5]] = 0 -- по-умолчанию } -- запишем. assert(self.i:write_bytes(data)) end
Если не сработал assert, то гироскоп будет включен и готов к чтению данных. Функция для чтения тоже довольно проста
-- табица для чтения. read_bytes ожидает в таблице номера регистров для чтения. read_xyz_data = { R_xL, R_xH, R_yL, R_yH, R_zL, R_zH } L3G4200D.read_xyz = function( self ) -- читаем local res = assert(self.i:read_bytes( read_xyz_data )) -- возвращаем таблицу с уже поправленными значениями { x = ..,y = .., z = .. } return { x = res[R_xH] << 8 | res[R_xL], y = res[R_yH] << 8 | res[R_yL], z = res[R_zH] << 8 | res[R_zL] } end
Теперь есть полный инструмент для получения данных с гироскопа. Далее я приведу скрипт, который раз в 100 миллисекунд вычитывает данные и выбрасывает их на консоль.
i2c = fr.client.smbus eq = fr.client.event_queue -- для работы с очередью событий клиента eqt = eq.timer -- таймеры клиента device_address = 0x69 ctrl_regs = { 0x20, 0x21, 0x22, 0x23, 0x24 } scale_values = { [250]=0, [500]=16, [2000]=48 } R_xL = 0x28 R_xH = 0x29 R_yL = 0x2A R_yH = 0x2B R_zL = 0x2C R_zH = 0x2D read_xyz_data = { R_xL, R_xH, R_yL, R_yH, R_zL, R_zH } L3G4200D = { } L3G4200D.new = function( ) inst = { } for k, v in pairs(L3G4200D) do inst[k] = v end inst.i = assert(i2c.open( 1, device_address )) setmetatable( inst, L3G4200D ) return inst end L3G4200D.setup = function( self, scale ) -- setup table for write local data = { [ctrl_regs[1]] = 15, [ctrl_regs[2]] = 0, [ctrl_regs[3]] = 8, [ctrl_regs[4]] = scale_values[scale], [ctrl_regs[5]] = 0 } -- write registry assert(self.i:write_bytes(data)) end L3G4200D.read_xyz = function( self ) local res = assert(self.i:read_bytes( read_xyz_data )) return { x = res[R_xH] << 8 | res[R_xL], y = res[R_yH] << 8 | res[R_yL], z = res[R_zH] << 8 | res[R_zL] } end -- функция таймера, которая вычитает данные и выведет их на консоль function show_values( err, dev ) -- первый параметр - ошибка таймера. при нормальной работе err=nil if nil == err then local values = dev:read_xyz( ) -- вычитаем print( "X:", values.x, "Y:", values.y, "Z:", values.z ) -- ... и выведем eqt.post( show_values, {milli=100}, dev ) -- поставим новое задание в таймер на 100 milliсекунд else -- если ошибка fr.exit(err) -- завершимся. fr.exit( ) остановит очередь end end function main( ) fr.run( ) -- запустим очередь событий local r = L3G4200D.new( ) -- откроем устройство r:setup(2000) -- настроем устройство show_values( nil, r ) -- запустим вывод. end
теперь можно проверить: 192.168.1.3:12345 - адрес и порт агента на малине. Запущу и подвигаю железку немного.
$ ./lua_client -s 192.168.1.3:12345 -e L3G4200D.lua X: 129 Y: 500 Z: 65489 X: 50 Y: 65468 Z: 65508 X: 26 Y: 4 Z: 14 ............... X: 34869 Y: 37125 Z: 21348 X: 57781 Y: 65259 Z: 3636 X: 32752 Y: 32752 Z: 32832 ............... X: 76 Y: 78 Z: 23 X: 73 Y: 7 Z: 11 X: 78 Y: 62 Z: 65519 X: 48 Y: 65495 Z: 45 X: 14 Y: 4 Z: 6 ^C
На этом все, спасибо за внимание.
PS: скрипт можно взять тут
PPS: Добавил в пример получение значения температурного регистра: 0x26
-
Windows приложения на Raspberry Pi 2
Доброе утро!
Мы разработчики ОС для тонких клиентов WTware.
Недавно выпустили бесплатную версию WTware для Raspberry Pi 2. Теперь малину можно использовать как тонкий клиент, подключать к терминальному серверу Windows и работать с Windows-приложениями на Raspberry Pi 2 как на обычном x86 компьютере.
Предлагаем попробовать: http://winterminal.com/ru/