Создадим 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;
}