Русский
Русский
English
Статистика
Реклама

Canny

Морзянка сэр или обзор составных функциональных блоков в CannyLab 2

07.01.2021 22:18:40 | Автор: admin
Год назад, мне подарили мой первый контроллер Canny 3 tiny, о чем я написал статью, из которой со временем вырос целый небольшой цикл.

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

Но зайдя на сайт разработчика, чтобы полистать документацию, я обнаружил, что с момента моего последнего визита, среда разработки кардинально обновилась (на момент написания статьи до версии 2.7, если быть точным).

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

Так что я решил отложить обзор нового контроллера и потратить время на описание примера работы с составными функциональными блоками.

В этот раз мы запрограммируем контроллер моргать морзянкой число 2021.

Статья рассчитана в первую очередь на новичков, люди опытные легко разберутся самостоятельно прочитав документацию.





Оглавление:
Часть I: Введение
Часть II: Запускаем CannyLab 2
Часть III: Создаем составной блок
Часть IV: Применяем блок в контроллерах
Часть V: Заключение


Введение



Другие статьи цикла
  1. Раз, два, три ёлочка гори! или мой первый взгляд на контроллер CANNY 3 tiny в этой статье мы разбирали что из себя представляет контроллер, а также азы работы в среде разработки CannyLab.
  2. У Предназначения масса обличий... или автоматизируем управление автолампой с помощью CANNY 3 tiny и фоторезистора в этой статье мы разбирали работу с USB Virtual COM-port, подключение датчиков к АЦП, а также высокочастотный ШИМ на выходах контроллера.
  3. Как зеницу ока... или делаем простенькую охранную систему на базе микроконтроллера (CANNY или Arduino) и Raspberry PI в этой статье мы разбирали работу с UART, а также повторили ранее пройденное.
  4. Как зеницу ока... Каких Марин? или управляем контроллером через bluetooth с помощью мобильного приложения на Xamarin (Android).



В этой статье я буду ориентироваться на Canny 3 tiny, а также я покажу, как адаптировать код диаграммы для контроллера Canny 5 nano, но думаю, на любом другом контроллере этой фирмы принцип работы диаграммы будет аналогичен.

Прежде чем начать, два небольших дисклеймера:

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



Часть II: Запускаем CannyLab 2



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

Но покончим с лирическими отступлениями. Чтобы приступить к работе нам необходимо скачать среду разработки CannyLab 2.X. На момент написания статьи я использовал версию 2.7, но думаю, что диаграмма будет работать и в других версиях CannyLab 2.X. Программу можно скачать с официального сайта разработчика, ссылка на скачивание будет в разделе Поддержка -> Загрузки.

О том как работать со средой разработки и как подключать к ней контроллеры, я рассказал в самой первой статье цикла. Правда, там все применительно к версии CannyLab 1.41. Отличия конечно небольшие, но на всякий случай в этой статье я тоже дам краткие инструкции.

Порядок установки:

1. скачиваем архив;
2. распаковываем в любую папку (установка не требуется);
3. находим в папке файл cannylab.exe;
4. в Windows 10 SmartScreen может ругаться на файл, разрешите ему запуск;
5. выберите язык;
6. одобрите лицензионное соглашение;
7. если спросит про восстановление настроек из прошлой версии IDE, можете смело восстановить. В крайнем случае всегда есть кнопка сброса настроек по умолчанию.
8. Выберите контроллер, я выбирал Canny3 Tiny.

Обратите внимание! Диаграмму созданную для Canny 3 tiny, нельзя будет напрямую записать в другой редактор, об этом я расскажу чуть подробней в разделе IV.

Если все нормально, то при настройках по умолчанию на шаге 8 вы увидите примерно такую картину:




Часть III: Создаем составной блок



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

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

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

Ну вот и всё можем создавать наш первый функциональный блок.

Создать его можно несколькими способами

  1. нажать ПКМ в рабочей области и выбрать соответствующую команду;
  2. Зажать ЛКМ и перетащить иконку блока в рабочую область




Отлично, если кликнуть ПКМ на шапку составного блока, появится контекстное меню.



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

Команда
Описание
Войти в блок
Откроет функциональную диаграмму составного блока.
Переименовать блок
Заменит название составной блок_Х, на новое стильное, модное и молодежное.
Изменить номер
Изменит номер в правом углу блока на тот, что вы введете. Я могу ошибаться, но никакой функции кроме декоративной я в этом не обнаружил (если не прав поправьте).
Изменить ширину
Изменит ширину составного блока. Удобно если у вас очень длинное (короткое) название.
Добавить вход EN
А вот это вторая полезная фишка составных блоков. Если добавить блоку вход EN и подать на него 1, то он будет выполняться, если подать 0 то нет.
Это помогает экономить ресурсы контроллера. Блоки, которые не нужны в определенный момент времени можно выключать. Эта возможность уменьшает время выполнения цикла функциональной диаграммы. Эта функция должно быть особенно полезна на младших братьях (например, Canny 3 tiny) или в случае очень больших и сложных диаграмм, а также при необходимости энергосбережения.
Запрет изменений
Запрещает изменение начинки блока, а также добавление и удаление входов (выходов). Удобно в тех случаях, когда диаграмма разрослась, снижает риск при случайном перетаскивании блока что-то в нем изменить.


Если кликнуть правой кнопкой на надпись Вход 0 или Выход 0, то покажется контекстное меню, для управления входами и выходами составного блока.



Входы (выходы) можно:
  • переименовывать;
  • добавлять (один и несколько);
  • удалять (один и несколько);


Важно помнить, что у составного блока может не быть входов, но должен быть хотя бы 1 выход.

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

Увеличьте ширину блока до 320, добавьте входы / выходы и перемеривайте их, а также сам составной блок как на картинке ниже:



Перейдите внутрь функционального блока, двойным кликом ЛКМ или через контекстное меню.

И воспроизведите диаграмму, как на рисунке ниже:



Ну или просто диаграмму с GitHub.

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

Наша составной функциональный блок будет циклически моргать светодиодом числа поступающие на вход, предварительно переведя их в код Морзе.

Вот краткое описание алгоритма.

  1. На вход составного блока Цифра поступает цифра, которую мы будем в данном этапе цикла моргать светодиодом.
  2. Цифра переключает сигнал на соответствующий вход коммутатора 8:1
  3. На входах коммутатора в бинарном представлении закодированы числа в азбуке Морзе. Тире единица, точка ноль. Обрабатываться наш код будет справа налево.
  4. Конвертер 1:8 позволит нам отрабатывать каждый бит кода индивидуально во внутреннем цикле моргания светодиодом.
  5. По идее далее мы должны были бы соединить выход 0 Конвертера 1:8 со входом 0 Коммутатора 1:8. Однако той схеме, что у меня получилась, нулевой этап цикла после сброса счетчика был очень коротким. Можно было усложнить диаграмму и сделать, так чтобы нулевой цикл был положенной длины. Однако, я решил, что мы тут не ракеты в космос запускаем, поэтому не стал усложнять диаграмму и просто игнорирую ну девой цикл, его продолжительность всего доли секунды и я решил пренебречь неопределенностью, которая возникает при обнулении счетчика.
  6. Сигнал с коммутатора управляет периодом заполнения ШИМ генератора (продолжительностью включения светодиода внутри цикла ШИМ). Если на выходе коммутатора 1 (тире), то мы получим долгое время горения светодиода, если на выходе 0, то мы получим короткое моргание и большую паузу.
  7. С ШИМ генератора сигнал поступает на выход Сигнал составного блока. Этот выход мы позже подключим непосредственно к регистру управления светодиодом. Вторая ветвь уходит на счетчик. Поскольку каждая цифра в коде морзе состоит из 5 знаков, мы отсчитываем в малом цикле 5 итераций, после чего переходим к следующей цифре. Как только счетчик, связанный с выходом этап цикла превысит значение со входа Количество цифр цикл начнется по новой. Таким образом светодиод контроллера будет бесконечно моргать цифры: 2,0,2,1.


Если вы хотите потренироваться, то можете улучшить эту диаграмму. Например, добавьте поддержку всех 10 цифр из азбуки Морзе, для этого вам понадобится коммутатор 1:16 и коды оставшихся чисел.

Чтобы вернуться на уровень выше, нажмите на его название в хлебных крошках.



Часть IV: Применяем блок в контроллерах




Теперь применим наш составной блок в так сказать боевых условиях.

Начнем с Canny 3 tiny.

Воспроизведите на домашнем уровне следующую диаграмму:



Как я уже говорил раньше, выход Сигнал функционального блока мы подключим к регистру записи Регистр включения зеленого светодиода (напомню, что его легко найти с помощью фильтра).
Коммутатор 8:1 мы будем использовать для циклической подачи нужных нам цифр.

Прежде чем записывать диаграммы в контроллер, вы можете её проверить и отладить в режиме Симулятор. Это своего рода дебаггер для функциональных диаграмм.

Причем с появлением составных блогов в Cannylab в режиме симулятора появились новые команды Шаг в и Шаг через.

Команда Шаг в в процессе отладки заходить внутрь составного блога, аналогично заходу внутрь процедуры в текстовых языках программирования. Команда Шаг через не будет заходить в блок, а сразу выдаст результат его работы.



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

Также напомню, что в симуляторе есть возможность устанавливать точки останова на блоки и на сеть (красное на схеме), а также принудительно устанавливать значения (черное на схеме).



Давайте запишем программу в контроллер.

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

Для этого в меню Устройство выберите команду Подключить. Далее в меню Устройство -> Системное ПО выберите команду Записать.

В открывшемся диалоговом окне в папке с программой найдите .ccx файл для вашего устройства, например как на рисунке ниже:



Теперь запишем саму диаграмму

Для этого в меню Устройство -> Диаграмма выберите команду Записать. Или найдите аналогичную кнопку на панели инструментов.

Напомню, что если вы не проводили никаких манипуляций с перемычкой для программирования, то по умолчанию при подключению к ПК, Canny 3 tiny всегда переходит в режим для программирования.

Есть три способа запустить контроллер в режиме выполнения диаграммы, мы пойдем от сложного к простому:

  1. Напаять перемычку для управления режимами (см. документацию, на сайте разработчика)
  2. Подключить контроллер не к компьютеру, а к блоку питания, ну или подключить через провод, у которого распаяны только разъемы для питания.
  3. И наконец самый простой способ в CannyLab в меню Устройство выберите команду Запустить (см. рисунок ниже). Правда, чтобы потом снова перевести контроллер в режим программирования, его надо будет повторно подключить к USB компьютера.


Убеждаемся, что всё работает:



Теперь, давайте попробуем применить наш составной блок, для контроллера Canny 5 Nano.
Как я уже говорил раньше, нельзя просто так взять и записать диаграмму.

Откройте еще одно окно CannyLab 2, создайте файл для CannyLab 5 Nano.
Затем скопируйте в буфер обмена диаграмму для Canny 3 tiny (Ctral+A, Ctrl+C) и вставьте её в окно с диаграммой для Canny 5 Nano.

Должно получиться, как на картинке ниже:



Эта диаграмма также есть на GitHub.

Обратите внимание, регистр Зеленый светодиод выделен красным.

Это потому, что у контроллера Canny 5 Nano, за моргание светодиодом отвечает совсем другой регистра.

При этом наш составной блок, перенесся без каких-либо ошибок, потому что внутри у него нет элементов, зависимых от специфики контроллера.

Поправьте диаграмму, как на картинке:

У Canny 5 Nano за управление светодиодом, отвечает канал 4, сконфигурированный определенным образом.

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

Убедимся, что и у Canny 5 Nano светодиод моргает как надо:



Часть V: Заключение




Составные функциональные CannyLab 2, на мой взгляд, одно из наиболее весомых улучшений в новой версии среды разработки. Безусловно, другие полезные мелочи, тоже хороши, работать со средой разработки стало намного приятней, но именно составные блоки, на мой взгляд это главная фича новой версии. Их применение может кардинально изменить подходы к составлению функциональных диаграмм. Можно например, сделать, мини-библиотеку с различными составными блоками для их повторного использования.

Если я что-то, недостаточно детально расписал или сделал явные ошибки, буду рад обратной связи.

P.S. Поздравляю всех со всевозможными зимними праздниками!
Подробнее..

Перетягивание диода или устраиваем соревнование между CANNY 3 TINY PRO и Arduino

08.06.2021 02:17:27 | Автор: admin
Arduino vs CANNY перетягивание диодаArduino vs CANNY перетягивание диода

В предыдущей статье, посвящённой моим попыткам погрузится в увлекательный мир программирования микроконтроллеров, я грозился сделать обзор на "обновку". К сожалению, мне сейчас не хватает навыков и времени чтобы сделать, что-то достойное полноценного обзора. Однако, я всё-таки решил подготовить забавы ради, короткую статью на тему игрушечного соревнования CANNY 3 TINY PRO и неоригинальной Arduino Nano. Соревноваться контроллеры будут в своеобразном аналоге перетягивания каната, на роль которого был выбран двухцветный светодиод марки BL-L2519EGW.

Итак в сегодняшнем материале мы подключим оба контроллера к светодиоду и будем подавать случайный сигнал на его выводы. Правила простые кто большее напряжение подаст у того и кристалл в светодиоде загорится ярче. Попутно мы воспользуемся ЦАП на контроллере CANNY и доработаем стандартный ГСЧ с помощью составного функционального блока.

В статье не будет сложной электроники или мудрёного программирования, так что она вполне подойдет новичкам.

Оглавление:

  1. Введение

  2. Схема

  3. Программа

  4. Заключение

Введение

Я намерено не буду разбирать технические характеристики нового (для меня) контроллера CANNY. Скажу только одну вещь. Несмотря на то, что они оба контроллера внешне чем-то похожи сравнивать их совершенно не уместно и мы этого делать не будем.

Для того, чтобы повторить "дуэль века" вам потребуется:

  1. Двухцветный светодиод - я использовал BL-L2519EGW, но марка не особо критична.

  2. Контроллер CANNY 3 TINY PRO именно у этого контроллера есть ЦАП, к тому же он самый доступный по цене в линейке контроллеров CANNY.

  3. Совместимый с Arduino контроллер - я использовал неоригинальную Nano, но можно было и UNO.

  4. Пара резисторов 100 Ом, - я не силен в электронике, но решил подстраховаться и использовать их как ограничители тока (может это и неверное решение). В любом случае думаю, что у контроллеров есть свои встроенные ограничители тока и схема может работать и без резисторов.

  5. Соединительные провода и макетная плата.

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

Предвосхищая некоторую критику, сразу скажу, что само собой раз контролеры Кэнни стоят в "Дакаровских" Камазах, наверное и CANNY 3 TINY PRO явно предназначен для чего-то большего, чем просто моргать светодиодом. Собственно Arduino Nano тоже может намного больше. Просто я ничего сложнее в этот раз собрать не смог, а поделится впечатлением хотелось.

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

Другие статьи цикла

Схема

Схема соединенийСхема соединений

Питать контроллеры мы будем через USB-порты, поскольку оба контроллера имеют USB-VCP мы при необходимости сможем еще и передавать данные. Но в принципе контроллеры можно питать и от двух USB зарядных устройств, схема всё равно будет работать.

Первым делом объединим "Землю" у двух контроллеров соединив выводы "GND".

Затем, от каждого из контроллеров "подведем" к светодиоду выводы от канала ЦАП.
У Arduino - "D5", у CANNY - "C2" (это единственный выход с ЦАП).
В нашем случае светодиод имеет два вывода и работает он примерно так: если на левой ноге напряжение больше, чем на правой то загорается красный кристалл. Чем больше разница потенциалов, тем ярче он загорится. И наоборот, если на правой ноге напряжение больше, чем на левой, то загорится зеленый. При примерном равенстве потенциалов светодиод вообще не будет светится.

Мы будем "перетягивать канат" 2.5 секунды, нам важно, чтобы контроллеры подали сигнал более-менее синхронно. Для этого (а также для нашей тренировки) контроллеры подадут друг другу сигналы. Выход "D7" Arduino подаст логическую единицу на вход "C6" CANNY. В свою очередь, CANNY с выхода "C4" подаст логическую единицу на вход "D3" Arduino. В программе каждого из контроллеров предусмотрим проверку наличия сигнала, при успешном прохождении которой подается напряжение на светодиод.

Для того, чтобы узнать какое напряжение подали оба контроллера, мы с помощью АЦП CANNY померим напряжение поданное Arduino. Для этого подсоединим выход "C10" CANNY к резистору.

Кстати лично я очень рад что у Canny 3 TINY PRO для того, чтобы включить режим АЦП канала не нужно паять перемычку, как в случае с обычным CANNY 3 TINY.

В итоге должно получится примерно вот-так:

Фото схемыФото схемы

Я правда использовал специальные резисторы из набора, но в остальном схема как на картинке.

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

Перейдем к программной части.

Программа

Обе программы можно скачать с GitHub.

Программа для Arduino очень простая, думаю нет смысле её комментировать:

/*Synhronized Randomize DAC.See more http://personeltest.ru/aways/habr.com/ru/post/561148/*/int ADC_pin = 5;int input_pin = 3;int output_pin = 7;int synch_signa = 0;int v_min = 10;int v_max = 2550;int synch_signal = 0;float rand_voltage = 0;// the setup function runs once when you press reset or power the boardvoid setup() {  pinMode(ADC_pin, OUTPUT);  pinMode(output_pin, OUTPUT);  digitalWrite(output_pin,HIGH);  pinMode(input_pin, INPUT);  Serial.begin(9600);}// the loop function runs over and over again forevervoid loop() {synch_signal = digitalRead(input_pin);      // read signal from another deviceif (synch_signal) { rand_voltage=random(v_min, v_max) / 10; analogWrite(ADC_pin, rand_voltage); Serial.println(rand_voltage);  delay(2500);   // wait for seconds}else{ delay(500);   // wait for seconds}                }

Программа для контроллера CANNY:

Функциональная диаграммаФункциональная диаграмма
  • При включении контроллер устанавливает на выходе "С4" логическую "1" для синхронизации с Arduino.

  • Канал "C10" в режиме АЦП измеряет напряжение от Arduinio и с помощью функции MAP переводит его в удобный для чтения вид.

  • ШИМ-генератор в сочетании с детектором переднего фронта раз в 2.5 секунды дают сигнал для записи случайного значения в канал "C2".

    • Значение при этом запишется, только если на входе "С6" есть логическая "1" от Arduino.

    • Значение напряжения для подачи на светодиод генерируется случайным образом. Поскольку у CANNY нет встроенного блока для сброса ГСЦ, "случайность" сигнала обеспечивается, сложением "истории" сигналов, поступивших от Arduino.

    • Для уменьшения количества элементов на основной диаграмме, реализация функции "Random" перенесена в одноименный составной блок (об этом чуть позже).

  • Значения напряжений на выводах светодиода от обоих контроллеров передается в виртуальный COM-порт ПК. Данный порт мы можем мониторить в любой программе, например в Hterm, но я для простоты решил использовать Arduino IDE.

    • Чтобы не "заморачиваться" с лишними символами, напряжение контроллеров выводится без точки, например, "c=45" значит, что напряжение на выводе ЦАП CANNY = 4.5В, соответственно "a=27" значит, что на ЦАП выводе Arduino = 2.7В.

Рассмотрим составной блок "Random (min...max)":

Составной блокСоставной блок

В данном блоге мы используем встроенный ГСЧ и функцию MAP для того чтобы выводить не просто числа от 0 до 65000, а в нужном нам диапазоне. Данный блок можно использовать, как библиотечный элемент и повторно использовать в других схемах. Более подробно о том, как работать с составными функциональными блоками, я писал в этой статье.

Примечание: когда вы загружаете программу в один из контроллеров, второй лучше отсоединять от ПК.

Заключение

Если вы все собрали верно, то получится примерно такой результат:

Различные варианты поданного на СИД напряженияРазличные варианты поданного на СИД напряжения

Слева направо:

  1. У контроллеров ничья, напряжение примерно равно.

  2. CANNY немножко выигрывает.

  3. CANNY ощутимо выигрывает.

  4. Arduino ощутимо выигрывает.

Пример вывода данных из монитора COM-порта (несвязанный с картинкой выше):

Монитор COM-портаМонитор COM-порта

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

Ну и еще под конец хочу сказать, что чертовски любопытно иногда погрузится в другую парадигму программирования. Я получил удовольствие, когда своими руками из функциональных блоков собрал простенький аналог функции "Random". Сейчас подумываю сделать еще несколько "библиотечных" элементов реализующих распространенные функции, которых порой не хватает среди готовых блоков CANNY и набросать об этом статью.

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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru