LINUX.ORG.RU

Сообщения KivApple

 

Django + FastCGI

Решил я ради расширения кругозора попробовать серверного питона, а именно - фреймворк Django. С самой разработкой под него проблем не возникало, но никак не могу запустить его в production-режиме.

У меня есть веб-сервер lighttpd, соответственно, как я понимаю, Django должен быть запущен в FastCGI режиме (так написано в официальной инструкции - https://docs.djangoproject.com/en/1.8/howto/deployment/fastcgi/), а он в этом режиме запускаться отказывается:

./manage.py runfcgi ...
Unknown command: 'runfcgi'
Type 'manage.py help' for usage.

Перед этим сделал pip install flup6 (просто flup не ставился, потому что он оказывается несовместим с Python3 и везде говорят ставить flup6).

ЧЯДНТ?

 

KivApple
()

Преобразование значение по таблице

Есть некая таблица преобразования, известная ещё на этапе компиляции. Содержит 10-20 значений типа int. Какого-либо математического закона преобразования нет, просто таблица.

Сейчас преобразование выглядит следующим образом:

int f(int a) {
    switch (a) {
        case X:
            return M;
        case Y:
            return N;
        case Z:
            return K;
        ... ещё 10-20 case'ов ...
        default:
            return -1;
    }
}

Выглядит громоздко. Как это можно реализовать лучше на plain C? Без привлечения сторонних библиотек. Можно запилить какую-нибудь самодельную реализацию хеш-таблицы (поскольку значения на этапе компиляции известны, запихнуть их в массив в отсортированном порядке, а затем в рантайме искать двоичным поиском). Таблиц преобразований несколько (но все по отдельности небольшие), так что на размере кода это должно сказаться благоприятно (ведь можно вынести поиск в отдельную функцию). Но будет ли это эффективнее по скорости, чем простой switch на небольшом объёме данных?

 ,

KivApple
()

Тулчайн CMake

Хочу попробовать использовать CMake для сборки прошивок для микроконтроллеров. Разумеется, для этого требуется другой тулчайн (arm-none-eabi) вместо системного. Как я понимаю, есть два варианта:

1) Тупой. Сделать SET(CMAKE_C_COMPILER «arm-none-eabi») внутри CMakeLists.txt проекта.

2) Умный. Сделать специальный файлик тулчайна, где прописать все необходимые опции. А затем подсунуть его в переменную CMAKE_TOOLCHAIN_FILE.

Проблема в том, что второй вариант рекомендуют делать с помощью опций запуска CMake. Типа cmake -DCMAKE_TOOLCHAIN_FILE=...

Однако в случае с прошивкой для микроконтроллера возможность лёгкого выбора целевой платформы не имеет смысла, так как весь код всё равно заточен под конкретный МК. Более того, попытка компиляции с нативным тулчайном гарантированно обломается. Соответственно, хотелось бы как-нибудь прописать тулчайн прямо внутри CMakeLists.txt, а не указывать его явно. Однако SET(CMAKE_TOOLCHAIN_FILE ...) не срабатывает. Вероятно, чтение этой переменной происходит раньше, чем исполнение команд из файла проекта.

Что делать? Как правильно сменить тулчайн и при этом по возможности как-то жёстко это зафиксировать, а не указывать в опциях командной строки при запуске CMake?

 , ,

KivApple
()

Широкие мониторы

Речь пойдёт не про стандартные широкоформатные мониторы, а про более продвинутые варианты - экраны 21:9. Да, фильмы будут без рамок и в каких-то играх обзор лучше. Но меня интересует в первую очередь не это.

Насколько такие мониторы удобны с точки зрения программиста? Вот я, например, иногда подрабатываю веб-разработкой. Можно будет, скажем, открыть на пол-экрана IDE и на пол-экрана браузер. По идее должно быть удобно.

Что лучше? Широкий монитор или два обычных? Широкий монитор в принципе выгоднее (я знаю вариант всего в 1.5 раза дороже, чем монитор с аналогичными характеристиками, но обычный Full HD IPS). Но, быть может, мне вообще не стоит переплачивать и взять один монитор, если я не геймер, не киноман и не дизайнер.

Есть тут обладатели широких мониторов, которые используют их для кодинга?

P. S. Испытываю нехватку места на своём ноутбучном 1366 х 768, поэтому задумался о покупке внешнего монитора.

 

KivApple
()

Организация небольшого проекта на Python

Запилил маленькую консольную утилиту для генерации заголовочных файлов с описанием регистров и прерываний (пример - http://pasted.co/31caec09), а также скрипта линковщика (а ещё выводит необходимые ключики компилятора). Полезно при программировании некоторых микроконтроллеров (в данный момент поддерживается лишь два семейства ARM).

Проект небольшой, но таки состоит из нескольких файлов. Хотел бы узнать как правильно его структурировать (или все py-файлы в корне это ок?). А также как облегчить его установку и опакечивание (в случае C/C++ проекта я бы добавил цели install/uninstall в Makefile).

Я не утверждаю, что этот проект архинужный, но просто хочу разобраться с тем как правильно организовывать питоньи проекты.

Ссылка: https://github.com/KivApple/mcu-info-util

 

KivApple
()

Предупреждения BTRFS

Пришёл долгожданный optibay и я вернул жёсткий диск в мой ноутбук, заменив им оптический дисковод (ранее я заменил HDD на SSD и накатил систему с нуля).

На диске была ext4 и файлы (в принципе, не сказать чтобы прямо совсем критичные, но не хотел их удалять). Я сконвертировал файловую систему жёсткого диска в btrfs, примонтировал, удалил резервную копию ext4 (это выражается в удалении субтома ext2_saved). Вроде всё работает.

Перенёс всё старое в каталог old-system в корне, также перенёс в корень домашний каталог своего пользователя. Смонтировал диск как /home, закрепив это в fstab. Перезагрузился. УМВР.

После этого рекомендуют выполнить дефрагментацию и ребалансировку древа.

# btrfs fi defrag -r /home && btrfs balance start /home
ERROR: defrag failed on /home/old-system/var/tmp/kdecache-kiv/icon-cache.kcache: Input/output error
ERROR: defrag failed on /home/kiv/.dropbox-dist/dropbox-lnx.x86_64-6.4.14/dropbox: Success
total 2 failures
# btrfs balance start /home
WARNING:

        Full balance without filters requested. This operation is very
        intense and takes potentially very long. It is recommended to
        use the balance filters to narrow down the balanced data.
        Use 'btrfs balance start --full-balance' option to skip this
        warning. The operation will start in 10 seconds.
        Use Ctrl-C to stop it.
10 9 8 7 6 5 4 3 2 1
Starting balance without any filters.
ERROR: error during balancing '/home': Input/output error
There may be more info in syslog - try dmesg | tail
[root@kiv-hp15r161nr ~]# dmesg | tail
[11397.780166] BTRFS info (device sdb2): found 511 extents
[11398.146912] BTRFS info (device sdb2): relocating block group 729213304832 flags 4
[11399.980078] BTRFS info (device sdb2): found 509 extents
[11400.791373] BTRFS info (device sdb2): relocating block group 729204916224 flags 4
[11402.324515] BTRFS info (device sdb2): found 511 extents
[11402.680300] BTRFS info (device sdb2): relocating block group 729196527616 flags 4
[11404.002392] BTRFS info (device sdb2): found 512 extents
[11404.247011] BTRFS info (device sdb2): relocating block group 729171361792 flags 1
[11404.438483] BTRFS warning (device sdb2): csum failed ino 824 off 1048576 csum 1775494736 expected csum 39867248
[11404.438680] BTRFS warning (device sdb2): csum failed ino 824 off 1048576 csum 1775494736 expected csum 39867248

Как я должен это понимать? Всё плохо и мне надо срочно копировать ценные данные обратно на SSD и пересоздавать ФС? Или это нормальная ситуация? Как мне её следует исправить?

 

KivApple
()

Стеганография в социальных сетях и прочих подобных публичных местах

После прочтения очередной новости про наказания для операторов мессенджеров у меня возникла идея (мне самому это, конечно не нужно, просто вольная фантазия на заданную тематику).

Ведь есть альтернатива использованию всяких Telegram, I2P и подобного.

1) Шифруем сообщение любыми средствами, переводим в base64, отправляем личным сообщением Facebook, ВКонтакте или любой другой соцсети. Ну а что, правилами же не запрещено, если второй собеседник не против, чтобы я слал ему бессмысленный набор букв (если против, то это уже спам будет). Разумеется, не обязательно это делать ручками, можно использовать специальный клиент, который будет логинится через API соцсети, но при получении и при отправке сообщений шифровать/дешифровать текст.

2) Проблема предыдущего способна в том, что факт обмена скрытой информацией на лицо. Но мы можем пойти дальше. Не шифровать текст, а превращать в шизофазию. В смысле, разработать алгоритм преобразования одного текста в другой. При этом новый текст не должен иметь никакой смысловой связи со старым и её должно быть проблематично восстановить, не зная какой-нибудь ключ. Писать всякий бред в личных сообщениях может быть запрещено ещё меньше, чем обмениваться base64-кодами.

3) Наконец апогей развития идеи. Программная генерация осмысленных бесед. Если оба собеседника пользуются одинаковым софтом, то чисто теоретически должно быть вполне реально генерировать не шизофазию, а связанную беседу на заданную тему. Это проще теста Тьюринга, потому что оба собеседника действуют за одно. Тут, кстати, получается интересная задача сходной тематики - программно сгенерировать диалог, который строннему наблюдателю покажется человеческим.

Последний вариант интересен ещё и тем, что можно использовать не только личные сообщения, но и публичные места вроде форумов и комментариев.

Да, я знаю про стеганографию в картинках. Однако любое преобразование картинки на стороне сервера уничтожает спрятанные данные. А наиболее популярные сервисы любят таким заниматься.

По-любому, я не первый кто до этого догадался. Интересно узнать, кто уже до этого доходил ранее. И да, суть именно в автоматизированном решении для соцсетей. А также какие подводные камни есть у этой идеи. Я пока не вижу способов защититься от этого. Даже если разрешить только официальные клиенты, ничто не мешает пользователю копипастить сообщения из программы и обратно в программу.

 , ,

KivApple
()

Производительность C++

Как насчёт производительности у C++ по сравнению с C? Мои предположения на текущий момент:

1) Код, не использующий возможности C++ (то есть по сути plain C), скомпилированный C++ компилятором будет иметь абсолютно ту же производительность, что и код на С.

2) Исключения и dynamic_cast медленные. Если нам важна производительность, лучше их не использовать.

3) Класс без виртуальных методов, должен быть по производительности эквивалентен сишной структуре и функциям, обрабатывающим её. Не считая копирования. Нужно везде, где можно использовать передачу по указателю или ссылке (собственно, если в Си делать memmove при передаче структуры в качестве аргумента, то это вызовет примерно такой же оверхед, как дефолтный конструктор копирования С++. Верно?).

4) Класс с виртуальными методами полностью аналогичен пункту 3, но при вызове виртуальных методов добавляется небольшой оверхед. Сишный эквивалент obj->vtable->func(obj, ...). Если сравнивать с plain C кодом, реализующим ООП в той же манере (каждая структура-объект имеет поле, указывающее на структуру, содержащую адреса функций работы с ней), то оверхеда по сравнению с plain C не должно быть.

5) При использовании атрибута класса final (если компилятор поддерживает соответствующий стандарт) даже при наличии виртуальных методов в нём, их вызов будет превращаться в прямые вызовы функций вместо обращения к vtable, если переменная имеет соответствующий тип, а не указатель/ссылка на его предка (который не final).

6) Шаблоны могут привести к разбуханию кода. Впрочем, #define-ы и inline-функции в C++ могут устроить то же самое. Вопрос: будет ли использование шаблона с одинаковыми параметрами создавать 2 копии реализации или же всё-таки компилятор догадается сделать её лишь один раз. А если шаблон используется с одинаковыми параметрами в нескольких объектных файлах? Будет ли реализация расшариваться между ними или у каждого своя?

7) Что насчёт inline-методов класса? (те, которые описываются прямо в момент определения самого класса, внутри блока class). Может ли их реализация расшариваться между модулями или в каждом будет своя копия (допустим, метод слишком длинный, чтобы инлайнится в момент вызова)?

Я не претендую на правоту, какие-то утверждения могут быть ложными. Хотел бы узнать, как обстоят дела на самом деле. А также какие подводные камни я ещё не знаю. Разумеется, речь идёт о последних версиях gcc/clang с включённой оптимизацией не ниже -O2.

 ,

KivApple
()

Падают некоторые приложения KDE

Я наконец-то купил себе SSD и воткнул в свой ноутбук вместо HDD (HDD верну в качестве /home раздела, когда придёт из Китая optibay). В связи с этим переустановил систему (Arch Linux x86_64).

И что же я получил? Пытаюсь удалить файл в Dolphin (не важно Shift + Del или просто Del или же выбрать пункт контекстного меню) - и Dolphin падает. Вылазит окошко обработчика ошибок KDE, которое радостно сообщает, что собранная о сбое информация «скорее всего бесполезна». Жмякую по ссылке «список необходимых файлов», чтобы поискать какие пакеты ещё поставить на packages.archlinux.org - и тут уже падает сам обработчик ошибок.

Также падает приложение системных настроек KDE иногда при применении изменений (изменения при этом применяются).

Зато плазма вообще не падает, да.

Что интересно - на старой системе такой фигни не было. Хотя там было точно также обновлённое всё. Возможно, сейчас я поставил чуть больше/чуть меньше пакетов. Ну либо за прошлую ночь вышло какое-то обновление, которое всё сломало.

В какую сторону вообще копать? Я могу смириться со падением утилиты настроек (изменения то применяются), но вылеты Dolphin при удалении файла - это уже выходит за все рамки.

UPD: http://pastebin.com/rt6icMrr - вот стеквызовов падения Dolphin при удалении файла.

 ,

KivApple
()

Проектирование печатной платы

Меня уже давно интересует тема создания самодельного нейроинтерфейса. И какое-то время назад я даже приобрёл микросхему АЦП ADS1298, которая должна отлично подойти для снятия сигналов без каких-либо предусилителей и фильтров (фильтровать шумы можно уже цифровым методом, потому что точности оцифровки хватит на всё).

Проблема в том, что я не уверен в себе, чтобы развести свою печатную плату для этой микросхемы. Не хотелось бы получить какие-нибудь паразитные шумы из-за ошибок в разводке платы. Тем более, что я скорее всего не смогу отпаять микросхему в таком корпусе обратно без повреждений (даже если не рассматривать физические повреждения ножек - сильный нагрев для прецизионных аналоговых деталей очень вреден), чтобы попробовать снова.

Итак, у меня есть сама микросхема, малощумящие линейные стабилизаторы TPS76933 (надо же чем-то сделать 3.3В из 3.7В от литий-полимерного аккумулятора), сборка 4 резисторов 2.2 кОм в едином корпусе (100 штук, может быть использовано для защиты входов от статики), защитные диоды TPD4E1B06 (совместно с резисторами - защита входов от статики), выкупленный лот (в смысле заказ оплачен, но Gerber-файлы не загружены) на сайте ITEAD Studio на изготовление 10 двухсторонних плат 5 х 5 см. Также есть принципиальная схема и разводка печатной платы моего авторства, выполненные в DipTrace. Однако есть два «но» - я ошибся и использовал не тот корпус для микросхемы (так что всё придётся переделывать) и я не уверен в качестве разводки и оптимальности схемы.

Требуется: проверить правильность схемы (исправить, если что) и спроектировать печатную плату, на которой бы была вся обвязка АЦП и с одной стороны на гребёнку 2х8 (8 каналов, каждый имеет входы + и -) были выведены входы АЦП, а с другой стороны на гребёнку - питание (3.5-5В, стабилизаторы должны быть размещены на самой плате, желательно сделать аналоговое и цифровое питание от разных стабилизаторов) и сигналы интерфейса SPI (выделенные пины RESET, SLEEP и т. д. мне не нужны, ибо эти режимы можно активировать и по SPI, нужны только SCK, MOSI, MISO, SS и выход прерывания DRDY). Плата должна иметь минимальный размер, при котором не испортятся параметры (всё-таки на голову вешать). Спаяю плату я сам.

Сколько это может стоить? Может ли кто-то из вас за такое взяться?

Возможно, кто-то может захотеть поучаствовать в проекте за «спасибо» (я таки студент-нищеброд)?

Все схемы, прошивки и программы выложу под OpenSource-лицензией.

 , нейроинтерфейс, ,

KivApple
()

Пьезоэлектрический датчик давления

Попросили меня помочь разобраться с пьезоэлектрическим датчиком давления.

Известны параметры:

Чувствительность: 20 пКл/бар

Измеряемый диапазон: 0.1-250 бар

Электрическая ёмкость: 7..12 пФ

Сопротивление изоляции: 10 ^ 10 Ом

Чувствительный элемент: кварц

Есть ещё другие параметры типа максимальной погрешности, рабочей температуры и т. д., однако это уже скорее забота того, кто будет датчик использовать, с электрической точки зрения должно быть пофиг на них.

Первым делом я вспомнил формулу ёмкости конденсатора из школьной программы: C = q/U => U = q/C. И после нехитрых расчётов (250 бар * 25 пКл/бар) / 12 пФ, получается, что датчик может выдавать сотни вольт. Что я не учитываю?

Вторым делом я нагуглил схему усилителя заряда. Точнее вот этот документ: http://phys.rsu.ru/web/petin/analog.pdf (начиная со страницы 43).

Рассчитал по формулам из этого документа номиналы компонентов цепи обратной связи. R=2 МОм, C = 2.2 нФ. Взлетит? С учётом того, что я собираюсь снимать данные с помощью АЦП STM32 (так что макс. напряжение 3.3В на выходе должно быть). Не совсем понял требования к ОУ. Скажем, в следующем разделе для «усилителей медленно меняющихся сигналов» есть требование, чтобы у ОУ был очень маленький входной ток (пикоамперы) и рекомендуют TL082, а вот к этой схеме рекомендаций нет. Туда можно воткнуть дешёвый LM358 или всё же есть какие-то требования кроме полосы пропускания?

 

KivApple
()

Вопрос по лицензии QBS

В составе проекта Qt есть система сборки QBS. Она достаточно гибкая и может быть использована для сборки отнюдь не только проектов, использующих библиотеку Qt.

Вопрос: можно ли собирать с помощью QBS проприретарщину (или просто что-то несовместимое по лицензии с Qt) не имея коммерческую лицензию Qt? При условии, что конечный продукт линковаться и как-либо использовать Qt не будет, только систему сборки и встроенные скрипты сборки для C++ (но, разумеется, от скриптов ничего не останется в исполняемом файле, они просто подёргают компилятор с нужными параметрами).

Второй вопрос: а если использовать QBS со своими собственными скриптами сборки - должны ли они обязательно быть под OpenSource?

Вообще, я хочу написать качественные скрипты для использования QBS для программирования различных микроконтроллеров и выложить их в паблик (сейчас я находил только более-менее костыльные решения «лишь бы работало», а я хочу сделать всё красиво и аккуратно - с генерацией скриптов линкера по имени МК, с поддержкой некоторых RTOS). Однако я хотел бы, чтобы если кто-нибудь будет их использовать, то он не был обязан публиковать исходники прошивки просто потому что использовал QBS для сборки.

А ещё интересно есть ли какие-то ограничения под какой лицензией я могу публиковать свои скрипты сборки.

 ,

KivApple
()

Небольшой вопрос про операционный усилитель

Имеется простая схема. ШИМ-сигнал 30 кГц 50% заполнение с микроконтроллера проходит через RC-цепь (15 кОм и 100 нФ), чтобы стать аналоговым (в итоге получается хороший постоянный сигнал с очень маленькими пульсациями). Затем он усиливается по току с помощью операционного усилителя LM358 в буферном включении (сигнал подан на неинвертирующий вход, выход ОУ и инвертирующий вход соединены напрямую). И на выходе ОУ присутствует тот же самый сигнал, плюс добавляются микроскопические (на грани возможностей осциллографа) ВЧ-помехи. Всё бы хорошо... но.

Подключаем между выходом ОУ и землёй конденсатор 100 нФ (типа для стабилизации значения на всякий случай). И получаем на выходе синусоиду с амплитудой где-то 0.5В. Ладно, не очень то нам и нужен этот конденсатор, убираем.

Вообще, данный ОУ подключен в буферным режиме не случайно, ибо данный сигнал используется дальше по схеме. И так получается, что он подключен в том числе к одному концу резистора 47 кОм, на другой контакт которого периодически подаются короткие (30 кГц 1% заполнение) импульсы 12В.

Я ожидаю, что эти импульсы никак не должны влиять на буферизованный сигнал. Ведь 12В / 47 кОм = 250 мкА. А в реальности там даже чуть меньше, ибо уровень сигнала ОУ около 1.5В, а не 0В, поэтому разность потенциалов, и как следствие ток, меньше. А они влияют. Не синусоида, конечно, как с конденсатором, но есть ярко выраженные сильные искажения сигнала в момент прихода импульсов (тоже примерно 0.5-1В амплитудой).

Если симулировать такую схему в Proteus (http://i.imgur.com/gxG5kcQ.png, тут сразу и конденсатор на выходе, и генератор импульсов 12В, пробовал и всё сразу, и что-то одно), то никаких проблем нет. Но, разумеется, данный софт может банально не учитывать какие-то физические законы, поэтому к нему претензий нет.

Вопрос знатокам - в чём проблема? Почему схема плохо себя ведёт? Как это можно исправить? Быть может, мне нужен другой ОУ, а я и не знаю? По какому принципу выбрать замену? Или я делаю что-то, что вообще не должно работать?

 операционный усилитель,

KivApple
()

Управление шаговым двигателем

Пытаюсь управлять шаговым двигателем FL57STH76-2804A. Для этого изготовил следующую схему управления - один конец каждой обмотки (A- и B-) подключен к средней точке питания (в настоящий момент биполярного БП у меня нет, поэтому используется конденсаторная средняя точка с резисторным делителем напряжения для защиты от уплывания средней точки). Второй конец каждой обмотки (A+ и B+) подключен к полумосту на двух IRFZ48N. Управляет каждым полумостом драйвер IR2104 (резисторы на затворах 10 ом). Драйвера же полумостов управляются с микроконтроллера STM32F103. Параллельно каждой обмотке шагового двигателя установлен конденсатор 330 нФ. Частота ШИМ 30 кГц. Питаю от БП 12В, то есть на обмотки реально идёт +-6В. Проверял осциллографом - просадки на средней точке во время работы не превышают +-200мВ.

Я успешно запустил шаговый двигатель как в полношаговом, так и в микрошаговом режиме, однако при вращении присутствует определённая неравномерность и вибрации. Хотелось бы от них избавиться.

Вот алгоритм управления двигателем:

static const int16_t sinTable[256] = {
   0, 6, 12, 18, 24, 31, 37, 43, 49, 55, 61, 68, 74, 79, 85, 91,
   97, 103, 109, 114, 120, 125, 131, 136, 141, 146, 151, 156, 161, 166, 171, 175,
   180, 184, 188, 193, 197, 201, 204, 208, 212, 215, 218, 221, 224, 227, 230, 233,
   235, 237, 240, 242, 244, 245, 247, 248, 250, 251, 252, 253, 253, 254, 254, 254,
   255, 254, 254, 254, 253, 253, 252, 251, 250, 248, 247, 245, 244, 242, 240, 237,
   235, 233, 230, 227, 224, 221, 218, 215, 212, 208, 204, 201, 197, 193, 188, 184,
   180, 175, 171, 166, 161, 156, 151, 146, 141, 136, 131, 125, 120, 114, 109, 103,
   97, 91, 85, 79, 74, 68, 61, 55, 49, 43, 37, 31, 24, 18, 12, 6,
   0, -6, -12, -18, -24, -31, -37, -43, -49, -55, -61, -68, -74, -79, -85, -91,
   -97, -103, -109, -114, -120, -125, -131, -136, -141, -146, -151, -156, -161, -166, -171, -175,
   -180, -184, -188, -193, -197, -201, -204, -208, -212, -215, -218, -221, -224, -227, -230, -233,
   -235, -237, -240, -242, -244, -245, -247, -248, -250, -251, -252, -253, -253, -254, -254, -254,
   -255, -254, -254, -254, -253, -253, -252, -251, -250, -248, -247, -245, -244, -242, -240, -237,
   -235, -233, -230, -227, -224, -221, -218, -215, -212, -208, -204, -201, -197, -193, -188, -184,
   -180, -175, -171, -166, -161, -156, -151, -146, -141, -136, -131, -125, -120, -114, -109, -103,
   -97, -91, -85, -79, -74, -68, -61, -55, -49, -43, -37, -31, -24, -18, -12, -6
};

void setStepperState(int curStep) {
   static const uint16_t microstepCount = sizeof(sinTable) / sizeof(sinTable[0]);
   uint16_t curMicrostep = curStep % microstepCount;
   int16_t phaseA = sinTable[curMicrostep];
   int16_t phaseB = -sinTable[(curMicrostep + 64) % microstepCount];
   uint32_t polarityA = (phaseA < 0) ? PAL_HIGH : PAL_LOW;
   uint32_t polarityB = (phaseB < 0) ? PAL_HIGH : PAL_LOW;
   palWritePad(GPIOB, 1, polarityA); // INA
   pwmEnableChannel(&PWMD3, 0, abs(phaseA)); // ENA
   palWritePad(GPIOB, 10, polarityB); // INB
   pwmEnableChannel(&PWMD3, 1, abs(phaseB)); // ENB
}

...

while (1) {
   for (int i = 0; i < 65536; i++) {
      setStepperState(i);
      chSysPolledDelayX(US2RTC(STM32_SYSCLK, 200));
   }
}

По идее ШИМ на обмотках при шагах должен изменяться следующим образом - http://i.imgur.com/kCMfHQP.png.

При низких скоростях, если режим не полношаговый (достигается умножением i на 64 при вызове setStepperState) двигатель перестаёт крутиться (дёргается на месте).

В чём может быть проблема? У меня ошибка в алгоритме переключения обмоток? Или проблема может быть лишь в силовой части схемы?

 , шаговый двигатель

KivApple
()

Обёртка над Posix Timers

Написал для своего небольшого проекта обёртку над таймерами Posix.

class VirtualTimer {
	private:
		pthread_mutex_t _mutex;
		
		timer_t _posixTimer;
		
		uint32_t _period;
		
		TimerCallback _callback;
		
		void *_callbackArg;
		
		volatile bool _armed;
		
		static void posixTimerCallback(union sigval val);
		
	public:
		VirtualTimer(uint32_t period = 0, TimerCallback callback = NULL, void *arg = NULL);
		
		~VirtualTimer();
		
		void setCallback(TimerCallback callback, void *arg);
		
		bool setPeriod(uint32_t period);
		
		uint32_t getPeriod() {
			return _period;
		}
		
		void start();
		
		void stop();
		
		bool isArmed() {
			return _armed;
		}
		
};

VirtualTimer::VirtualTimer(uint32_t period, TimerCallback callback, void *arg) {
	_period = period;
	_callback = callback;
	_callbackArg = arg;
	_armed = false;
	pthread_mutex_init(&(_mutex), NULL);
	struct sigevent sev;
	sev.sigev_notify = SIGEV_THREAD;
	sev.sigev_notify_function = posixTimerCallback;
	sev.sigev_value.sival_ptr = this;
	int r = timer_create(CLOCK_MONOTONIC, &sev, &(_posixTimer));
	assert(r == 0);
	if (_period > 0) {
		start();
	}
}

VirtualTimer::~VirtualTimer() {
	timer_delete(_posixTimer);
	pthread_mutex_lock(&(_mutex));	
	pthread_mutex_destroy(&(_mutex));
}

void VirtualTimer::posixTimerCallback(union sigval val) {
	VirtualTimer *timer = (VirtualTimer*)val.sival_ptr;
	pthread_mutex_lock(&(timer->_mutex));
	if ((timer->_callback != NULL) && (!timer->_callback(timer->_callbackArg))) {
		timer->stop();
	}
	pthread_mutex_unlock(&(timer->_mutex));
}

void VirtualTimer::setCallback(TimerCallback callback, void *arg) {
	_callback = callback;
	_callbackArg = arg;
}

bool VirtualTimer::setPeriod(uint32_t period) {
	_period = period;
	if (_armed) {
		start();
	}
	return true;
}

void VirtualTimer::start() {
	time_t sec = _period / 1000000;
	long nsec = (_period % 1000000) * 1000;
	struct itimerspec newValue = {
		.it_interval = {
			.tv_sec = sec,
			.tv_nsec = nsec
		},
		.it_value = {
			.tv_sec = sec,
			.tv_nsec = nsec
		}
	};
	int r = timer_settime(_posixTimer, 0, &newValue, NULL);
	assert(r == 0);
	_armed = true;
}

void VirtualTimer::stop() {
	struct itimerspec newValue = {};
	int r = timer_settime(_posixTimer, 0, &newValue, NULL);
	assert(r == 0);
	_armed = false;
}

Имеется проблема. Допустим, таймер срабатывает и вызывается callback. Однако в этот же момент поток, создавший таймер, решает, что хватит дожидаться его срабатывания и уничтожает объект. В итоге callback (с самого начала или на своей середине) будет работать с уничтоженным объектом и это может привести к печальным последствиям.

Сейчас это частично решается с помощью mutex. Если callback успеет захватить mutex, то деструктор будет терпеливо ждать, пока callback отработает (новый callback уже точно не вызовется, потому что таймер дизармится перед захватом mutex) и только потом уничтожит таймер. Однако если нет? Если деструктор успеет захватить mutex, затем будет вызван callback (callback уже может быть вызван, но таймерный поток ожидает своего кванта времени в очереди планировщика ОС, пока работает деструктор), который будет ждать mutex, который потом уничтожат (что уже само по себе будет плохо, и либо будет зависание таймерного потока, либо обращение к освобождённой области памяти)? Будет плохо.

Как эту ситуацию разрулить?

 ,

KivApple
()

Rust как язык для программирования микроконтроллеров

Собственно сабж. А то часто вижу всякие статьи, где Rust пиарится как «убийца сишечки». Вот даже недавно ОС на Rust вышла. А программирование микроконтроллеров - как раз одна из тех областей, где C на сегодняшний день практически не имеет конкурентов.

Ну так насколько он годен для этого? Сильно ли распухнет код? А что с производительностью? Как со всякими специфичными фичами (обработчики прерываний часто требуют иных прологов/эпилогов, также нужна возможность пихать функции и переменные в не стандартные секции линкера и т. д.)?

Насколько он юзабелен без кучи рантайма? Вот попробовал простую программу кросс-компилировать под STM32 с #![no_std] - так не собралось же. Требует как минимум библиотеку core (и в стабильной версии вроде как нет возможности её отрубить). Насколько эта библиотека жирна?

А что со всякими микроконтроллерами послабее типа всяких AVR, PIC, STM8, MSP430. Как я понимаю, тут уже всё зависит напрямую от LLVM. Для AVR порт есть, для MSP430 тоже (правда, экспериментальный). Вроде как запилить в случае чего LLVM-backend не очень сложно, но есть важный вопрос - насколько оно будет хорошо работать. Есть ли какие-то проигрыши по эффективности или размеру кода, если вместо прямой компиляции (с помощью gcc или sdcc) использовать llvm?

 , ,

KivApple
()

Инициализация глобальных переменных в C++

Допустим, есть такой код на C++:

ClassA a;
ClassB b(a);
ClassC c(a, b);

Насколько он корректен и нет ли тут UB? Я знаю, что если a, b и c находятся в разных compilation unit, то это будет UB (это логично - линковщик может слинковать файлы в произвольном порядке из каких-то своих соображений и особенности реализации). Но если речь идёт об одном файле? Интересует именно соответствие стандартам, а не только реальное поведение компиляторов (чтобы быть уверенным, что такой код не отвалится в будущем).

 

KivApple
()

Приложение для борьбы с прокрастинацией

Хочу такое приложение, чтобы там можно было создавать задачи и строить планы на будущее. При этом:

1) Можно создавать задачи на конкретную дату/время. Типа какой-то встречи. Также можно создавать периодические (ежедневные, еженедельные) задачи. Типа работы или учёбы.

2) Можно создавать задачи без привязки к конкретному времени. Возможно, с дедлайном (сделать в любое время, но не позднее такого-то дня), возможно, без него.

3) Задачи могут иметь подзадачи. И вообще всё это ещё может иметь приоритеты («важность» - «срочность» определяется и так исходя из даты дедлайна). При этом на подзадачи влияет важность родительской задачи.

Приложение должно анализировать все эти задачи и пытаться их распланировать так, чтобы я всё успел.

То есть я должен открывать телефон/доставать ноутбук и приложение радостно встречает меня текстом «Привет %username%. Сейчас такая-то дата, такое-то время. Через два часа тебе надо идти в универ, а сейчас тебе стоило бы заняться доработкой проекта по фрилансу».

Разумеется, задачи должно быть можно пропускать. Типа позанимался чем-то полчаса-час, нажал кнопку и приложение предложило новую задачу. Как советуют - делать смену деятельности, сначала фигачишь сложную и важную задачу, когда устал переключаешься на простые и неважные для отдыха, затем возвращаешься к важной.

Также было бы забавно, если бы приложение ещё планировано сон, в том числе с применение полифазной техники (несколько кусков в разное время суток), но это уже совсем опцианально. К тому же надо как-то рассчитать, чтобы я в это время хотел спать и быстро заснул, а то лишь время зря будет потеряно. Разве что тут прикрутить какое-то машинное обучение...

Есть что-нибудь готовое на эту тему?

 

KivApple
()

Идея для стартапа

Помните панику насчёт уязвимости Bad USB? Тогда никто не догадался до очевидного решения, предлагали ввести цифровые подписи устройств и прочие банальные ограничения.

Что вы думаете про коробочку, которая одним концом втыкается в компьютер, а другим в флешку (точнее флешка втыкается в неё)? А эта коробочка анализирует все USB-пакеты, проходящие через неё, по заложенным в себя правилам и производит их модификацию или даже отказ передачи, если захочет. Разумеется, производитель предоставляет пресеты для всех популярных вариантов фильтров, возможность быстро их переключать (возможно, даже залить в коробочку несколько профилей и менять их тумблером на корпусе) и т. д.

С ходу вижу три возможных сценария:

  1. Защита от классического Bad USB. Два пресета — «порт для флешек» и «порт для HID-устройств». В первом случае коробочка портит все попытки девайса прикинуться клавиатурой или мышкой (достаточно анализировать SETUP-пакет запроса дескриптора и банить устройство, если это дескриптор HID). Во втором случае коробочка портит все попытки девайса прикинуться флешкой. В идеале составное устройство не должно полностью отваливаться, а только то, что заблокировано (можно просто подпортить кусок дескриптора, чтобы лишние конечные точки не определились хостом, но в целом устройство успешно прошло енумерацию).
  2. Защита наоборот. Доверенной флешки от недоверенного хоста. Самое банальное — перевод флешки в read only. Перехватываем все команды записи и возвращаем хосту какую-нибудь ошибку. Ведь очень часто бывают ситуации, когда на флешку писать нафиг не нужно. Например, если вы хотите показать с неё презентацию или распечатать документ. А компьютеры в общественных местах очень часто заражены целым зоопарком вирусов (самое неприятное — вирус, который заменяет все папки ярлыками на вирус, а сами папки скрывает).
  3. Немного притянуто за уши. Допустим, мы хотим разрешить мыши и клавиатуры, но запретить флешки, модемы и т. д. Или разрешить только по белым спискам серийников. Понятное дело, что это можно сделать средствами ОС. Но так то прикольнее. Засунуть в системник такую коробочку и вывести все USB-порты через неё. Системник опечатать. Поскольку ПО такой коробочки значительно проще целой ОС, то и шанс что там есть уязвимость меньше.

Возможны другие варианты, но они не пришли мне в голову.

Техническую сторону вопроса я и так знаю, про неё особо не интересно. 2 USB PHY + FPGA на первом этапе, ASIC на втором. Кстати, себестоимость вроде выходит в пределах 1000 рублей даже в первом случае. Интересно мнение с точки зрения потребителей.

 badusb,

KivApple
()

Реализация очередей и не только

Допустим, есть структура очереди. В неё можно читать и из неё писать. Объём памяти, выделенный под очередь, фиксированный (задаётся при создании). Очередь в себе хранит указатели на первый и последний элемент (при этом если мы доходим до конца массива во время чтения или записи, то переходим к его началу). Всё хорошо работает, однако возможна ситуация, когда в очереди кончится свободное место. В этом случае надо дождаться, пока оно появиться. Аналогично мы можем хотеть считать из очереди N байт, а если их не хватает, то дождаться их появления.

Busy loop это не круто. Однако у меня есть специальный примитив синхронизации - EventSource. Он поддерживает две основные операции - ожидание сигнала и отправка сигнала. Если поток ждёт сигнал, он не потребляет ресурсы. Отправка сигнала пробуждает все ждущие потоки.

На Linux реализуется этот примитив через pthread_condvar (параметр mutex не используем, передавая свежий mutex, который уничтожаем сразу же после вызова). Под моей личной RTOS реализуется нативно.

Теперь поступаем просто - после каждой записи или чтения посылаем соответственно сигнал о записи или о чтении. Если записали/прочитали не всё, что хотели, то ждём противоположный сигнал (если хотим записать, ждём пока кто-то прочитает, если хотим прочитать, то ждём, пока кто-нибудь запишет).

Возникает логичная проблема. А что если мы отправим сигнал о, скажем, записи. В этот момент нас нагло прервёт проснувшийся поток, который ждал, пока появятся данные в очереди (и мы его разбудили), вытащит из очереди все данные, пошлёт сигнал чтения, а затем снова уснёт от их недостатка. И только теперь к нам возвращается управление и мы начинаем ждать событие чтения. А оно не придёт! Потому что тот кто хотел уже всё прочитал и ждёт, пока нового события записи, которое мы отправили ранее и больше не отправим, пока не запишем ещё.

И что с этим делать? Надо как-то научиться принимать сигналы из прошлого. Скажем, заведём флаг и будем сбрасывать его в false в начале каждой записи/чтения, а после окончания записи (либо если кончилось место/данные в очереди) устанавливаем в true флаг противоположного действия помимо отправки сигнала. В ожидание переходим лишь если флаг остался в false. Но это не поможет - нас могут прервать внутри самой функции ожидания, до того как она собственно начнёт ждать. И она точно также пропустит сигнал.

Конечно, в своей RTOS я могу что-то нахимичить (сделать проверку флага и переход в ожидание, если его нет, атомарным), но не в pthread же.

Как вообще такое надо делать?

Моя кривая реализация очереди, если что - https://github.com/KivApple/controllerFramework/blob/master/libraries/platfor...

 

KivApple
()

RSS подписка на новые темы