Взлом узлов с помощью 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 и поделитесь своим проектом или получите помощь от сообщества. Также продолжайте следовать вместе с руководством по созданию беспилотного робота, чтобы узнать, как использовать этот узел для программирования автономного робота.