Взлом узлов с помощью C ++ - Часть четвертая
Если вы следовали предыдущим урокам, вы во многом убедились в мощи XOD - языка программирования, основанного на визуальном потоке. Не имея опыта программирования, мы смогли легко проектировать состояния и управлять оборудованием. Еще один интересный инструмент - это возможность создавать полностью настраиваемые узлы на C ++. Если есть что-то, что вы хотите настроить или изменить, этот раздел покажет вам, как это сделать.
Примечание. Если вас не интересует C ++ и вы хотите продолжить работу с XOD, вы можете пропустить это руководство и установить библиотеку gweimer / servo и получить все необходимые функции, чтобы продолжать разработку автономного робота.
Для тех, кто хочет увидеть расширенные функции XOD, мы погрузимся в код, который управляет узлами. До сих пор в этом руководстве мы работали над созданием состояний для управления оборудованием, таким как двигатели и сервоприводы. Наша текущая задача - добавить дополнительную опцию для функциональности сервопривода по умолчанию. Патч сервопривода автоматически подключает сервопривод и поворачивает его в определенное положение. Функциональность, которую мы добавим в это руководство, - это добавление дополнительного входа, чтобы сервопривод был подключен только тогда, когда мы сочтем нужным. Это позволит нам управлять сервоприводами в нескольких состояниях. Эта статья предназначена для работы в тандеме с частью 3 серии руководств, и вы можете ссылаться на нее, чтобы узнать об используемом оборудовании и испытательной схеме.
Создание пользовательского патча
Давайте начнем с создания нового патча (Ctrl + N) и назовем его «enable-servo». Также дважды щелкните сервоузел в одном из ваших состояний, чтобы увидеть за занавеской, что происходит внутри сервоузла. Мы будем использовать структуру узла серво для создания нашего модифицированного узла enable-servo.
Скопируйте «внутреннюю часть» узла серво в наш только что созданный узел enable-servo в качестве отправной точки. Ваш экран должен выглядеть как на изображении выше.
Давайте добавим еще один вход к этому узлу, который активирует этот узел из-за нашей задержки. Назначение этого узла - включить сервопривод, поэтому мы назовем его En.
Дважды щелкните, чтобы добавить новый узел, и выполните поиск input-boolean, чтобы выбрать узел xod / patch-nodes / input-boolean. В инспекторе измените имя входа на En. Обратите внимание, что цветовая кодировка входов изменилась, чтобы соответствовать разным типам. Мы можем видеть входы PORT и VAL по умолчанию как зеленые числа, а недавно добавленное En как логическое значение, которое имеет розовый цвет.
Настройка узлов с помощью C ++
Следующий шаг - немного глубже погрузиться в процесс управления сервоприводом; Давайте посмотрим, как код C ++ взаимодействует с внутренней работой каждого патча. Дважды щелкните патч «not-implementation-in-xod», чтобы открыть код C ++. Также вернитесь к патчу сервопривода по умолчанию и ознакомьтесь с его кодом «not-implementation-in-xod».
На снимках экрана выше показана реализация C ++ для enable-servo и servo. Обратите внимание, что даже несмотря на то, что мы скопировали структуру патча серво, код C ++ не копируется. Идите вперед и выберите весь серво код (Ctrl + a), скопируйте его (Ctrl + c) и вставьте (Ctrl + v) в серво-включение, заменив существующий код.
Структура ввода XOD
Сначала мы рассмотрим структуру XOD и то, как вводимые данные обрабатываются в C ++, чтобы мы могли добавить код для нашего недавно обработанного ввода.
Обратите внимание на обведенные кружки части кода, которые указывают getValue<input_PORT>(ctx)
. Это часть кода, которая обрабатывает наши текущие входные данные, PORT
и VAL
. Как видите, вот как мы подключаем входные узлы к логике нашей программы. В конечном итоге нам нужно будет добавить еще немного кода для обработки нашего вновь созданного ввода, En
.
Сервокоманды
Также мы хотим взглянуть на то, как сервоприводы управляются в C ++. Для этого нам нужно понять часть кода, который управляет сервоприводами. Мы рассмотрим две функции в коде: присоединение и запись.
Здесь мы видим две важные функции, обведенные выше servo.attach()
и servo.write()
. Attach используется, чтобы определить, к какому выводу на контроллере подключен сервопривод. Позже мы также добавим еще одну аналогичную функцию, которая выполняет противоположную servo.detach()
и позволяет нам перемещаться между состояниями. Вторая функция - servo.write()
. Это говорит сервоприводу, на какой угол двигаться, и это показание с нашего входа VAL
.
Структура программы
Следующий шаг - подумать о том, как мы можем структурировать нашу логику так, чтобы сервопривод был подключен и записывал только в том случае, если наш вход разрешения - истина. Основной поток нашей программы состоит в том, чтобы делать три вещи:
1) Получите значения из всех наших входных данных
2) Если enable истинно, прикрепите и напишите
3) В противном случае, если разрешено ложное отключение (чтобы разрешить другим состояниям управлять сервоприводом)
Мы начнем с шага 1: получение значений из входных данных.
auto port = (int)getValue<input_PORT>(ctx); auto En = getValue<input_En>(ctx);
В приведенном выше коде используется некоторый синтаксис C ++ вместе с функцией getValue
, которая была выделена выше. Мы будем использовать эти две строки кода для чтения наших входных данных состояния PORT
и En
.
Теперь мы перейдем к шагу 2: проверьте, истинно ли значение enable, и если да, подключите сервопривод и запишите значение.
if (En) { state->servo.attach(port); state->servo.write(getValue<input_VAL>(ctx) * 180); }
Обратите внимание, что вы увидите оператор if, проверяющий, истинно ли En, и наши функции servo.attach()
и servo.write()
в фигурных скобках оператора if.
Наконец, мы рассмотрим третий шаг по пути. Если enable неверно, мы хотим отсоединить сервопривод.
else { state->servo.detach(); }
Здесь мы видим логику else, означающую, что En
ложно, что указывает на то, что наше состояние неактивно. В этом случае мы будем использовать функцию servo.detach()
, заключенную в фигурные скобки оператора else
.
Последнее, что стоит отметить, это то, что мы фактически удаляем переменную configuredPort
все вместе, потому что мы каждый раз настраиваем порт. Поэтому вы можете удалить этот код в верхней части файла.
struct State { Servo servo; };
Единственная строка кода внутри struct State
фигурных скобок должна быть той, которая определяет сервопривод.
Здесь вы можете увидеть весь код, который вы можете просмотреть вместе, скопировать и вставить в свой проект.
{{#global}} #include <Servo.h> {{/global}} struct State { Servo servo; }; {{ GENERATED_CODE }} void evaluate(Context ctx) { State* state = getState(ctx); auto port = (int)getValue<input_PORT>(ctx); auto En = getValue<input_En>(ctx); if (En) { state->servo.attach(port); state->servo.write(getValue<input_VAL>(ctx) * 180); } else { state->servo.detach(); } }
Теперь, когда у вас есть код, ваш недавно написанный узел not-implementation-in-xod в состоянии enable-servo должен быть завершен. Код на вашем экране должен точно совпадать с приведенным выше кодом.
Тестирование
Теперь у нас есть только что созданный сервоузел, который будет присоединяться и записывать только в определенную позицию, в то время как для входа En установлено значение TRUE. Мы можем написать простую программу для проверки нашей настройки.
В приведенной выше программе показана структура, которая сообщает сервоприводу на штыре 9 перейти в положение 0,25 на 3 секунды. После 3-секундной задержки сервопривод должен отсоединиться и свободно вращаться. Загрузите его в Arduino, выбрав Deploy → Upload to Arduino.
Здесь мы можем увидеть нашу предполагаемую функцию прикрепления → записи → отсоединения. Вы можете видеть, когда сервопривод прикреплен, он фиксируется в этом положении. После отсоединения он может свободно вращаться.
Прочитав это, вы сможете создавать собственные узлы C ++ для управления сервоприводами и, надеюсь, иметь некоторые идеи о том, как это может помочь в вашем проекте. Если вы создали крутой проект и хотите поделиться им, обязательно зайдите на forum.xod.io и поделитесь своим проектом или получите помощь от сообщества. Также продолжайте следовать вместе с руководством по созданию беспилотного робота, чтобы узнать, как использовать этот узел для программирования автономного робота.