Программирование на Blockly
Документация по RoboIntellect SDK (RI SDK)
Функциональный RI SDK API исполнительных устройств

C

Создадим C файл

  • Windows
type nul > shared_client.c
  • Linux
touch shared_client.c

Структура проекта

. workspace/
    --- > shared_client.c
    --- > librisdk.h
    --- > librisdk.so/.dll
    --- > libusb-1.0.so/.dll

Подключим библиотеку

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "librisdk.h"

int main() {
    printf("Success\n");

    return 0;
}

Для запуска скрипта выполним в терминале следующие команды:
Укажем компилятору gcc что динамические библиотеки можно искать в текущей директории.

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

Выполним компиляцию

  • Windows
gcc shared_client.c -o c_shared_client.exe -lrisdk -L.
  • Linux
gcc shared_client.c -o c_shared_client.bin -lrisdk -L.

Значение shared_client.c указывает на файл, который необходимо собрать.
Значение -o c_shared_client.bin/.exe указывает на путь к скомпиленному файлу.
Значение -lrisdk указывает на путь к динамической библиотеке (В данном случае на librisdk.so).
Значение -L. указывает в какой директории относительно LD_LIBRARY_PATH искать библиотеку (В данном случае в текущей).

Получим результат выполнения собранной программы

./c_shared_client.bin

Создадим компонент внутри функции main

int logLevel = 2;
int errCode;
char errorText[1000];

// Инициализируем SDK
errCode = RI_SDK_InitSDK(logLevel, errorText);
if (errCode) {
    // Выведем текст и код ошибки в терминал, при возникновении
    printf("RI_SDK_InitSDK errorText:%s; errorCode:%s--\n", errorText, errCode);
    return;
}

int descriptor;

// Создаем базовый компонент
errCode = RI_SDK_CreateBasic(&descriptor, errorText);
if (errCode) {
    // Выведем текст и код ошибки в терминал, при возникновении
    printf("RI_SDK_CreateBasic errorText:%s; errorCode:%s--\n", errorText, errCode);
    return;
}

// Выведем полученный дескриптор компонента
printf("descriptor:%d--\n", descriptor);

Скомпилируем и запустим скрипт

./c_shared_client.bin

Результат успешной работы должен выглядеть следующим образом:

descriptor:1--
Success

Пример программы на C, использующий RISDK

Описание

Данная программа является примером, использования библиотеки. Она реализует простой сценарий поведения робота. Сперва все сервоприводы встают в условное стартовое положение. После робот берет кубик с позиции слева и перемещает его на позицию справа. После сервоприводы возвращаются в первоначальное положение.
Одновременно с движением робота, происходит свечение светодиода. Светодиод горит красным цветом пока сервоприводы приводятся к стартовому положению, после загорается зеленым. Далее светодиоды моргает зеленым при передвижении тела робота и мерцает синим, пока робот кладет/берет кубик.

Структура проекта

. workspace/
    --- > demo.c
    --- > librisdk.h
    --- > librisdk.dll/.so
    --- > CH341DLL.DLL/ CH341DLLA64.DLL
    --- > SLABHIDDevice.dll
    --- > SLABHIDtoSMBus.dll
    --- > libusb-1.0.dll/.so

Реализация

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
#include <unistd.h>
#include "./librisdk.h"

char errorText[1000]; // текст ошибки. Передается как входной параметр,при возникновении ошибки в эту переменную будет записан текст ошибки

int body_start_pulse = 1500;        // стартовая позиция тела
int arrowR_start_pulse = 2000;      // стартовая возиция правой стрелы
int arrowL_start_pulse = 1000;      // стартовая позиция левой стрелы
int claw_start_pulse = 1000;        // стартовая позиция клешни
int claw_rotate_start_pulse = 1500; // стартовая позиция поворота клешни

int arrowR_over_cube_position = -30; // позиция правой стрелы над кубиком
int arrowL_over_cube_position = -10; // позиция левой стрелы над кубиком
int claw_unclenched_position = 60;   // позиция открытой клешни
int arrowR_cube_position = -75;      // позиция правой стрелы на месте кубика
int arrowL_cube_position = 55;       // позиция левой стрелы на месте кубика

int logLevel = 2; // уровень логирования
int speed = 100;  // скорость в градусах в секунду

// структура дескрипторов устройства
struct device
{
    int i2c;        // дескриптор i2c
    int pwm;        // дескриптор pwm
    int body;       // дескриптор сервопривода тела
    int claw;       // дескриптор сервопривода клешни
    int arrowR;     // дескриптор сервопривода правой стрелы
    int arrowL;     // дескриптор сервопривода левой стрелы
    int clawRotate; // дескриптор сервопривода поворота клешни
    int led;        // дескриптор светодиода
};

// инициализация структуры устройства
struct device robohand;

struct servo
{
    int *descriptor;    // дескриптор сервопривода
    int *startPosition; // стартовая позиция сервопривода
};

// массив дескрипторов сервоприводов
struct servo servos[5] = {
    &robohand.body,
    &body_start_pulse,
    &robohand.claw,
    &claw_start_pulse,
    &robohand.arrowR,
    &arrowR_start_pulse,
    &robohand.arrowL,
    &arrowL_start_pulse,
    &robohand.clawRotate,
    &claw_rotate_start_pulse,
};

// initServos - создает сервоприводы и линкует их
int initServos()
{
    int errCode; // код ошибки

    //создаем 5 сервоприводов и линкуем их к пинам 0-4
    for (int i = 0; i < 5; i++)
    {
        // создаем компонент сервопривода с конкретной моделью как исполняемое устройство и получаем дескриптор сервопривода
        errCode = RI_SDK_CreateModelComponent("executor", "servodrive", "mg90s", servos[i].descriptor, errorText);
        if (errCode)
        {
            return;
        }

        //связываем сервопривод с ШИМ,передаем дескриптор сервопривода и ШИМ
        errCode = RI_SDK_LinkServodriveToController(*servos[i].descriptor, robohand.pwm, i, errorText);
        if (errCode)
        {
            return;
        }
    }

    return 0;
}

// initDevice - инициализация библиотеки и устройств
int initDevice()
{
    int errCode;

    // Инициализируем SDK
    errCode = RI_SDK_InitSDK(logLevel, errorText);
    if (errCode)
    {
        return;
    }

    // создаем компонент ШИМ с конкретной моделью как соединитель и получаем дескриптор компонента
    errCode = RI_SDK_CreateModelComponent("connector", "pwm", "pca9685", &robohand.pwm, errorText);
    if (errCode)
    {
        return;
    }

    // создаем компонент i2c адаптера
    // Здесь осуществлен примитивное определение подключенной модели адаптера
    // Сначала пробуем создать i2c адаптер модели ch341 и связать с ним ШИМ
    errCode = RI_SDK_CreateModelComponent("connector", "i2c_adapter", "ch341", &robohand.i2c, errorText);
    if (errCode)
    {
        return;
    }

    //связываем i2c адаптер с ШИМ по адресу 0x40
    errCode = RI_SDK_LinkPWMToController(robohand.pwm, robohand.i2c, 0x40, errorText);
    if (errCode)
    {
        // Если не получается то пробуем создать i2c адаптер модели cp2112
        errCode = RI_SDK_CreateModelComponent("connector", "i2c_adapter", "cp2112", &robohand.i2c, errorText);
        if (errCode)
        {
            return;
        }

        //связываем i2c адаптер с ШИМ по адресу 0x40
        errCode = RI_SDK_LinkPWMToController(robohand.pwm, robohand.i2c, 0x40, errorText);
        if (errCode)
        {
            return;
        }
    }

    // создаем компонент светодиода с конкретной моделью (ky016) как исполняемое устройство и получаем дескриптор светодиода
    errCode = RI_SDK_CreateModelComponent("executor", "led", "ky016", &robohand.led, errorText);
    if (errCode)
    {
        return;
    }

    //связываем светодиод адаптер с ШИМ,передаем значения трех пинов к которым подключен светодиод
    errCode = RI_SDK_LinkLedToController(robohand.led, robohand.pwm, 15, 14, 13, errorText);
    if (errCode)
    {
        return;
    }

    //инициализируем сервоприводы
    errCode = initServos();
    if (errCode)
    {
        return;
    }

    return 0;
}

// startPosition - переводит сервопривод в стартовое положение
int startPosition(struct servo s)
{
    int errCode;
    //выполняем поворот сервопривода в заданный угол,передаем дескриптор сервопривода,значение угла
    errCode = RI_SDK_exec_ServoDrive_TurnByPulse(*s.descriptor, *s.startPosition, errorText);
    if (errCode)
    {
        return;
    }

    //небольшая пауза для последовательного движения
    Sleep(500);
    return 0;
}

// startPositionAllServo - переводит все сервоприводы в стартовую позицию
int startPositionAllServo()
{
    int errCode; //код ошибки
                 //выполняем одиночное свечение светодиодом,передаем дескриптор светодиода,3 параметра цвета(RGB), и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_SinglePulse(robohand.led, 255, 0, 0, 0, true, errorText);
    if (errCode)
    {
        return;
    }

    //приводим сервоприводы в стартовое положение
    for (int i = 0; i < 5; i++)
    {
        errCode = startPosition(servos[i]);
        if (errCode)
        {
            return;
        }
    }

    //выполняем одиночное свечение светодиодом,передаем дескриптор светодиода,3 параметра цвета(RGB), и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_SinglePulse(robohand.led, 0, 255, 0, 0, true, errorText);
    if (errCode)
    {
        return;
    }
    //небольшая пауза для последовательного движения
    Sleep(500);
    return 0;
}

// roteteBody - вращение тела в указанный угол
int roteteBody(int angle, int speed)
{

    int errCode; //код ошибки

    //выполняем мигание с заданной частотой,передаем дескриптор светодиода,3 параметра цвета(RGB),частоту,продолжительность и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_FlashingWithFrequency(robohand.led, 0, 255, 0, 5, 0, true, errorText);
    if (errCode)
    {
        return;
    }
    //выполняем поворот на заданный угол,передаем дескриптор тела,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.body, angle, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.clawRotate, 45, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.clawRotate, -45, speed, false, errorText);
    if (errCode)
    {
        return;
    }
    return 0;
}

// get - берет кубик
int get()
{
    int errCode; //код ошибки
    //выполняем мерцание светодиодом,передаем дескриптор светодиода,3 параметра цвета(RGB),продолжительность,кол-во повторений и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_Flicker(robohand.led, 0, 0, 255, 500, 0, true, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowR, arrowR_over_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowL, arrowL_over_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.claw, claw_unclenched_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowR, (arrowR_cube_position - arrowR_over_cube_position), speed,
                                          false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowL, (arrowL_cube_position - arrowL_over_cube_position), speed,
                                          false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.claw, (-1) * claw_unclenched_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowR, (-1) * arrowR_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowL, (-1) * arrowL_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    return 0;
}

// put - кладет кубик
int put()
{
    int errCode; //код ошибки
    //выполняем мерцание светодиодом,передаем дескриптор светодиода,3 параметра цвета(RGB),продолжительность,кол-во повторений и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_Flicker(robohand.led, 0, 0, 255, 500, 0, true, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowR, arrowR_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowL, arrowL_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.claw, claw_unclenched_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowR, (-1) * arrowR_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор стрелы,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.arrowL, (-1) * arrowL_cube_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    //выполняем поворот на заданный угол,передаем дескриптор клешни,угол,скорость и асинхронный режим работы
    errCode = RI_SDK_exec_ServoDrive_Turn(robohand.claw, (-1) * claw_unclenched_position, speed, false, errorText);
    if (errCode)
    {
        return;
    }

    return 0;
}

// destructServos - уничтожает сервоприводы
int destructServos()
{
    int errCode; //код ошибки

    for (int i = 0; i < 5; i++)
    {
        errCode = RI_SDK_DestroyComponent(*servos[i].descriptor, errorText);
        if (errCode)
        {
            return;
        }
    }

    return 0;
}

// destruct - уничтожает все окомпоненты и библиотеку
int destruct()
{

    int errCode; //код ошибки

    //выполняем одиночное свечение светодиодом,передаем дескриптор светодиода,3 параметра цвета(RGB), и включаем асинхронный режим работы
    errCode = RI_SDK_exec_RGB_LED_SinglePulse(robohand.led, 255, 0, 0, 0, true, errorText);
    if (errCode)
    {
        return;
    }

    //уничтожаем сервоприводы
    errCode = destructServos();
    if (errCode)
    {
        return;
    }
    //останавливаем свечение светодиода с определенным дескриптором
    errCode = RI_SDK_exec_RGB_LED_Stop(robohand.led, errorText);
    if (errCode)
    {
        return;
    }

    //удаляем компонент светодиода по дескриптору
    errCode = RI_SDK_DestroyComponent(robohand.led, errorText);
    if (errCode)
    {
        return;
    }

    //сбрасываем все порты на ШИМ
    errCode = RI_SDK_sigmod_PWM_ResetAll(robohand.pwm, errorText);
    if (errCode)
    {
        return;
    }

    //удаляем компонент ШИМ
    errCode = RI_SDK_DestroyComponent(robohand.pwm, errorText);
    if (errCode)
    {
        return;
    }
    //удаляем компонент i2c
    errCode = RI_SDK_DestroyComponent(robohand.i2c, errorText);
    if (errCode)
    {
        return;
    }

    //удаляем sdk со всеми компонентами в реестре компонентов
    errCode = RI_SDK_DestroySDK(true, errorText);
    if (errCode)
    {
        return;
    }
    return 0;
}

// start - запускает демо программу
int start()
{
    int errCode;

    // Инициализируем библиотеку и компоненты
    errCode = initDevice();
    if (errCode)
    {
        return;
    }

    // Приводим сервоприводы к стартовой позиции
    errCode = startPositionAllServo();
    if (errCode)
    {
        return;
    }

    // Двигаем тело к местонахождению кубика
    errCode = roteteBody(45, speed);
    if (errCode)
    {
        return;
    }

    // Берем кубик
    errCode = get();
    if (errCode)
    {
        return;
    }

    //Двигаем тело к новому местонахождению кубика
    errCode = roteteBody(-90, speed);
    if (errCode)
    {
        return;
    }

    //Кладем кубик
    errCode = put();
    if (errCode)
    {
        return;
    }

    // Возвращаем тело в стартовое положение
    errCode = roteteBody(45, speed);
    if (errCode)
    {
        return;
    }

    // Уничтожаем компоненты и библиотеку
    errCode = destruct();
    if (errCode)
    {
        return;
    }
}

int main()
{

    int errCode; //код ошибки

    //запускаем программу
    errCode = start();
    if (errCode)
    {
        printf("errorText:%s\n", errorText);
        return;
    }

    return 0;
}


35 просмотров0 комментариев

Комментарии (0)

Для участия в обсуждении вы должны быть авторизованным пользователем
Разделы
Программирование на Blockly
Документация по RoboIntellect SDK (RI SDK)
Функциональный RI SDK API исполнительных устройств

Навигация

ВойтиРегистрация