Программирование на Python

Подготовка рабочего окружения для программирования на Python. #

Для выполнения программ на Python потребуется установить на компьютер интерпретатор Python и IDE.

Установка интерпретатора #

Загрузка файла инсталлятора Python #

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

Для этого необходимо перейти по ссылке https://www.python.org/downloads/, и кликнуть по кнопке Download Python 3.13.3 (версия может со временем измениться) (см. рисунок 1).

После клика по кнопке, которая выделена красным цветом на рисунке 1, начнётся загрузка файла инсталлятора Python. Загрузка выполняется по пути, указанному в настройках браузера.

По-умолчанию это будет C:\Users\_имя_пользователя_ОС_\Downloads.

Установка интерпретатора. #

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

Для старта процесса установки необходимо убедиться, что установлен флаг Add python.exe to PATH (внизу на рисунке 2), и кликнуть по кнопке Install Now (вверху на рисунке 2). Если не установить флаг Add python.exe to PATH, то после установки интерпретатора потребуется путь к нему в переменную окружения PATH задавать вручную. После клика по кнопке Install Now появится диалоговое окно с подтверждением начала процесса установки. Необходимо нажать “Да”. Начнётся процесс установки интерпретатора, который обычно занимает несколько минут.

После завершения установки появится окно с подтверждением. Необходимо нажать кнопку Close (см. рисунок 4).

На этом окне размещено несколько полезных ссылок на документацию по Python. Если на первом экране Вы не установили флаг Add python.exe to PATH (см. рисунок 1), то следует перейти к разделу “Настройка переменных окружения для Python”. В противном случае можно этот раздел пропустить.

Настройка переменных окружения для Python #

Если на этапе установки интерпретатора Вы не установили флаг Add python.exe to PATH (см. рисунок 1), то в процессе не были автоматически заданы переменные окружения, необходимые для корректного выполнения программ на Python. В этом разделе инструкции Вы найдёте, как установить требуемые переменные окружения вручную.

Внимание! Если Вы установили флаг python.exe to PATH на первом экране окна установки интерпретатора, то данный раздел инструкции необходимо пропустить.

Для начала нажмите “Пуск”, и кликните по иконке “Параметры” (см. рисунок 5).

Откроется модальное окно параметров операционной системы. На этом окне необходимо выбрать раздел “Система” (см. рисунок 6).

После перехода в раздел “Система” откроется окно, представленное на рисунке 7. Необходимо перейти в раздел “О программе” (1), затем кликнуть по ссылке “Дополнительные параметры системы” (2), и в открывшемся модальном окне кликнуть по кнопке “Переменные среды” (3).

На открывшемся модальном окне редактирования переменных окружения необходимо выбрать переменную Path в разделе переменных для пользователя, и нажать кнопку “Изменить” (см. рисунок 8)

После выбора переменной Path и клика по кнопке “Изменить” откроется модальное окно редактирования переменной (см. рисунок 9). С помощью кнопки “Создать” необходимо добавить в Path два значения: путь к корневой директории с интерпретатором Python, и путь к внутренним скриптам Python.

Первая - это обычно C:\Users\_имя_пользователя_ОС_\AppData\Local\Programs\Python\Python310\

а вторая - это

C:\Users\_имя_пользователя_ОС_\AppData\Local\Programs\Python\Python310\Scripts\

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

Установка IDE #

Для написания исходного кода можно применять любой текстовый редактор, но обычно используют специальные “интегрированные среды разработки”, integrated development environment, то есть IDE. От простых редакторов IDE отличается тем, что предоставляет программисту не только редактор текста, но и подсветку синтаксиса, средства отладки, средства работы с системами контроля версий, и многое другое.

Так как эта инструкция предназначена для “новичков”, то и IDE будет использоваться начального уровня

- IDLE (Integrated Development and Learning Environment), которая поставляется вместе с Python.

Запуск IDE IDLE #

После установки Python IDLE в Windows находится в меню "Пуск" → "Python 3.x" → "IDLE". Также можно быстро найти его через "Поиск" около меню "Пуск", набрав в поле поиска "IDLE" (см. рисунок 10).

В Unix-подобных операционных системах (Linux, MacOS), IDLE запускается через терминал командой idle. Если программа не запустилась, поищите idle в каталоге tools/idle дистрибутива Python. Если idle отсутствует в вашей системе, установите его командой:

sudo apt-get install idle3

Интерактивный режим IDLE #

Изначально программа запускается в интерактивном режиме. По другому его называют REPL. Все что вы напишете в интерактивном режиме после ">>>" будет сразу же выполнено построчно. Традиционный "Hello world!" будет выглядеть так: см. рисунок 11.

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

Режим редактирования файлов #

В IDLE есть возможность полноценно работать с файлами — просматривать, редактировать, создавать новые. Чтобы создать новый файл, выберите "File" -> "New File" (или Ctrl + N). Откроется новое окно, которое можно увидеть на рисунке 12.

В новом окне доступен тот же функционал, что и в интерактивном режиме. Однако разница все же есть — в режиме редактирования файлов используется 4 пробела для отступа, в отличие от интерактивного режима (там используется 8 пробелов).

Для примера, напишем простой код и сохраним его под именем “test.py” с помощью "File" → "Save" (или Ctrl + S). После того как файл сохранен, IDLE начнет понимать что этот файл имеет расширение ".py" и подсветит синтаксис (см. рисунок 13).

Теперь, чтобы запустить код, выберите "Run" → "Run Module" (или F5). Откроется новое окно Python Shell с результатом выполнения нашего кода (см. рисунок 14).

Внимание! Версия Python и IDE IDLE, указанные в этой инструкции или приведенные на рисунках, могут отличаться от версий ПО, установленных на Вашем компьютере.

Установка RI SDK #

Высокоуровневое программирование робототехнических устройств возможно благодаря использованию расширяемой библиотеки RI SDK. RI SDK предоставляет простой и понятный программный интерфейс (API) для функционального управления компонентами робота. API включает в себя функции для управления сервоприводами (вращение, поворот, и т.д.), светодиодами (мигание, мерцание, и пр.), и датчиком тока (чтение текущих электрических характеристик РТУ).

RI SDK устанавливается вместе с программным обеспечением робота, которое можно скачать по ссылке.

Установка программного обеспечения роборуки #

Установить ПО для роборуки, включая RI SDK можно, пройдя по ссылке https://robointellect.ru/download (см. рисунок 15).

![](https://robointellect.ru/blog/files/2025/04/1745403895048988_.png Рисунок 15. Страница для загрузки ПО роборуки и документации к нему* Для этого необходимо кликнуть по кнопке скачивания версии для установленной у Вас операционной системы в разделе “Пульт управления РТУ” (1). После клика по кнопке, начнётся загрузка файла инсталлятора ПО роборуки. Загрузка выполняется по пути, указанному в настройках браузера. По- умолчанию это будет C:\Users\_имя_пользователя_ОС_\Downloads.

Инструкция по установке ПО роборуки доступна при клике по ссылкам, находящимся под разделом “Пульт управления РТУ” (2)

Запуск примеров готовых программ #

В составе ПО роборуки поставляется примеры готовых программ на различных языках, в том числе на Python. Это программы размещены в директории C:\Program Files (x86)\RoboIntellect\ri_sdk\examples (см. рисунок 16)

Сама расширяемая библиотека хранится по адресу C:\Program Files (x86)\RoboIntellect\ri_sdk\ri_sdk_x64.

Внимание! для запуска примера программы на Python необходимо скопировать содержимое директории с RI_SDK в директорию C:\Program Files (x86)\RoboIntellect\ri_sdk\examples\python (см. рисунок 17).

Запуск программы - пример №1 (не helloworld) #

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

Во-вторых, необходимо открыть исходный код готового примера через IDE IDLE, используя проводник ОС, или навигатор интерфейса самой IDE. Исходный код примера на Python - это файл C:\Program Files (x86)\RoboIntellect\ri_sdk\examples\python\example_1. Обратите внимание на то, что в разных моделях роботов могут использоваться разные модели контроллеров, и поэтому необходимо задавать разные параметры инициализации I2C адаптеров - cp2112, если у вас робот RM001 и ch341, если у вас робот RM001M2 или RM001M3.

import sys
from ctypes import *

def main():

    # Подключение библиотеки ri_sdk
    lib = cdll.LoadLibrary("./librisdk.dll")
    
    # Далее необходимо указать типы аргументов 
    # для функций библиотеки, которые будут использоваться
    lib.RI_SDK_InitSDK.argtypes = [c_int, c_char_p]
    lib.RI_SDK_CreateModelComponent.argtypes = [c_char_p, c_char_p, c_char_p, POINTER(c_int), c_char_p]
    lib.RI_SDK_LinkPWMToController.argtypes = [c_int, c_int, c_uint8, c_char_p]
    lib.RI_SDK_LinkLedToController.argtypes = [c_int, c_int, c_int, c_int, c_int, c_char_p]
    lib.RI_SDK_LinkServodriveToController.argtypes = [c_int, c_int, c_int, c_char_p]
    lib.RI_SDK_exec_RGB_LED_SinglePulse.argtypes = [c_int, c_int, c_int, c_int, c_int, c_bool, c_char_p]
    lib.RI_SDK_exec_ServoDrive_TurnByPulse.argtypes = [c_int, c_int, c_char_p]
    lib.RI_SDK_DestroyComponent.argtypes = [c_int, c_char_p]
    lib.RI_SDK_exec_RGB_LED_Stop.argtypes = [c_int, c_char_p]
    lib.RI_SDK_sigmod_PWM_ResetAll.argtypes = [c_int, c_char_p]
    lib.RI_SDK_DestroySDK.argtypes = [c_bool, c_char_p]
    lib.RI_SDK_exec_RGB_LED_FlashingWithFrequency.argtypes = [c_int, c_int, c_int, c_int, c_int, c_int, c_bool,
                                                            c_char_p]
    lib.RI_SDK_exec_RGB_LED_Flicker.argtypes = [c_int, c_int, c_int, c_int, c_int, c_int, c_bool, c_char_p]
    lib.RI_SDK_exec_ServoDrive_Turn.argtypes = [c_int, c_int, c_int, c_bool, c_char_p]
    lib.RI_SDK_exec_ServoDrive_Rotate.argtypes = [c_int, c_int, c_int, c_bool, c_char_p]
    lib.RI_SDK_exec_ServoDrive_MinStepRotate.argtypes = [c_int, c_int, c_int, c_bool, c_char_p]

    
    errTextC = create_string_buffer(1000)   # Перменная, в которую будет записываться текст ошибки
    errCode = c_int() # Переменная, в которую будет записываться код ошибки
    i2c = c_int() # Переменная, в которой будет храниться дескриптор на объект i2c адаптера
    pwm = c_int() # Переменная, в которой будет храниться дескриптор на объект pwm модулятора
    servo_1 = c_int() # Переменная, в которой будет храниться дескриптор на объект управления первым сервоприводом
    servo_2 = c_int() # Переменная, в которой будет храниться дескриптор на объект управления вторым сервоприводом
    servo_3 = c_int() # Переменная, в которой будет храниться дескриптор на объект управления третьим сервоприводом
    servo_4 = c_int() # Переменная, в которой будет храниться дескриптор на объект управления четвертым сервоприводом
    led = c_int() # Переменная, в которой будет храниться дескриптор на объект управления светодиодом

    # В начале необходмио вызвать функцию инициализации библиотеки
    # В качестве парметра необходимо указать уровень логирования
    # (0 - только верхний уровень, 1, 2, 3 - более подробная трассировка)
    # Здесь указан 2 уровень логирования
    errCode = lib.RI_SDK_InitSDK(2, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    # Инициализация i2c адаптера 
    # Для создания i2c адаптера можно использовать функцию RI_SDK_CreateModelComponent 
    # Эта функция создаст компонент устройства конкретной модели 
    # В качестве аргументов необходимо указать группу устройств, название устройства и его модель 
    # В нашем случае - это группа коннекторов(connector), устройство i2c-адаптер(i2c_adapter) модели ch341. 
    # Так же необходимо передать перменную, в которой будет храниться дескриптор этого компонента 
    # Он необходим для того чтобы указывать функциям библиотеки, какой именно компонент должен выполнить команду 

    errCode = lib.RI_SDK_CreateModelComponent("connector".encode(), "i2c_adapter".encode(), "ch341".encode(),
                                              i2c, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    # Инициализация шим-модулятора
    # Для создания шим-модулятора адаптера можно использовать функцию RI_SDK_CreateModelComponent 
    # Эта функция создаст компонент устройства конкретной модели 
    # В качестве аргументов необходимо указать группу устройств, название устройства и его модель 
    # В нашем случае - это группа коннекторов(connector), устройство широтно-импульсный модулятор модели pca9685 
    # Так же необходимо передать перменную, в которой будет храниться дескриптор этого компонента 
    # Он необходим, для того чтобы указывать функциям библиотеки, какой именно компонент должен выполнить команду 
    errCode = lib.RI_SDK_CreateModelComponent("connector".encode(), "pwm".encode(), "pca9685".encode(), pwm,
                                              errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 


    # Подключение i2c адаптера к шим-модулятору 
    # Для дальейшей работы, необходимо подключить шим-модулятор к i2c-адаптеру 
    # Для этого нужно использовать функцию RI_SDK_LinkPWMToController 
    # В нее в качестве аргументов необходимо передать дескрипторы шим-модулятора и i2c-фдаптера 
    # Также необходимо указать адрес, по которому будет сохдано подключение 
    # Он задается в байтовом формате. В данном случае подключение осуществляется по адресу 0x40  
    
    errCode = lib.RI_SDK_LinkPWMToController(pwm, i2c, c_uint8(0x40), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    # Инициализация 4-х сервоприводов
    # Для создания сервопривода можно использовать функцию RI_SDK_CreateModelComponent 
    # Эта функция создаст компонент устройства конкретной модели 
    # В качестве аргументов необходимо указать группу устройств, название устройства и его модель 
    # В нашем случае - это группа исполнителей(executor), устройство сервопривод(servodrive) модели mg90s(mg90s) 
    # Так же необходимо передать перменную, в которой будет храниться дескриптор этого компонента 
    # Он необходим, для того чтобы указывать функциям библиотеки, какой именно компонент должен выполнить команду 
    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "servodrive".encode(), "mg90s".encode(),
                                                  servo_1, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 
    
    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "servodrive".encode(), "mg90s".encode(),
                                                  servo_2, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 
    
    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "servodrive".encode(), "mg90s".encode(),
                                                  servo_3, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "servodrive".encode(), "mg90s".encode(),
                                                  servo_4, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    # Подключение 4-х сервоприводов к шим модулятору
    # Для дальейшей работы, необходимо подключить сервоприводы к шим-модулятору 
    # Для этого нужно использовать функцию RI_SDK_LinkServodriveToController 
    # В нее в качестве аргументов необходимо передать дескрипторы сервопривода и шим-модулятора 
    # Также необходимо указать номер порта, к которому подключен сервопривод 
    # В данном случае подключение осуществляется по портам от 0 до 3  

    errCode = lib.RI_SDK_LinkServodriveToController(servo_1, pwm, 0, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 
    
    errCode = lib.RI_SDK_LinkServodriveToController(servo_2, pwm, 1, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 
    
    errCode = lib.RI_SDK_LinkServodriveToController(servo_3, pwm, 2, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    
    errCode = lib.RI_SDK_LinkServodriveToController(servo_4, pwm, 3, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 

    # Инициализация светодиода
    # Для создания светодиода можно использовать функцию RI_SDK_CreateModelComponent 
    # Эта функция создаст компонент устройства конкретной модели 
    # В качестве аргументов необходимо указать группу устройств, название устройства и его модель 
    # В нашем случае - это группа исполнителей(executor), устройство светодиод(led) модели ky016(ky016) 
    # Так же необходимо передать перменную, в которой будет храниться дескриптор этого компонента 
    # Он необходим, для того чтобы указывать функциям библиотеки, какой именно компонент должен выполнить команду 
    errCode = lib.RI_SDK_CreateModelComponent("executor".encode(), "led".encode(), "ky016".encode(), led,
                                              errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2) 
    
    # Подключение светодиода к шим модулятору
    # Для дальейшей работы, необходимо подключить сервоприводы к шим-модулятору 
    # Для этого нужно использовать функцию RI_SDK_LinkLedToController 
    # В нее в качестве аргументов необходимо передать дескрипторы светодиода и шим-модулятора 
    # Также необходимо указать номера портов для каждого из 3-х основных цветов (красный, зеленый, синий), к которым подключен светодиод 
    # В данном случае подключение осуществляется по портам 15(красный), 14(зеленый), 13(синий) 
    errCode = lib.RI_SDK_LinkLedToController(led, pwm, 15, 14, 13, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)


    # Поворот сервопривода на заданный угол с заданной угловой скоростью 
    # Для поворота сервопривода на заданный угол нужно использовать функцию RI_SDK_exec_ServoDrive_Turn 
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того сервопривода, который будет соуществлять движение 
    # 2 - угол на который нужно повернуть 
    # (если число положительное, то движение будет происходить на увеличение угла, если отрицательный, то на уменьшение)
    # 3 - скорость вращения (углов в секунду)
    # 4 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    errCode = lib.RI_SDK_exec_ServoDrive_Turn(servo_1, 90, 100, c_bool(False), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)
    
    # Вращение сервопривода с заданной угловой скорость и направлением 
    # Для вращения сервопривода нужно использовать функцию RI_SDK_exec_ServoDrive_Rotate 
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того сервопривода, который будет соуществлять движение 
    # 2 - направление движения 
    # (0 - движение будет происходить на увеличение угла, 1 - на уменьшение)
    # 3 - скорость вращения (углов в секунду)
    # 4 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    errCode = lib.RI_SDK_exec_ServoDrive_Rotate(servo_2, 0, 100, c_bool(False), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Поворот сервопривода на минимальный шаг
    # Для поворота сервопривода на минимальный шаг сервопривода нужно использовать функцию RI_SDK_exec_ServoDrive_MinStepRotate 
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того сервопривода, который будет соуществлять движение 
    # 2 - направление движения 
    # (0 - движение будет происходить на увеличение угла, 1 - на уменьшение)
    # 3 - скорость вращения (углов в секунду)
    # 4 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    i = 0
    while i < 100:
        errCode = lib.RI_SDK_exec_ServoDrive_MinStepRotate(servo_3, 0, 50, c_bool(False), errTextC)
        if errCode != 0:
            print(errCode, errTextC.raw.decode())
            sys.exit(2)
        i = i + 1

    
    
    # Абсолютный моментальный поворот сервопривода, на позицию полученную в длине управляющего импульса (мкс)
    # Существует функция RI_SDK_exec_ServoDrive_TurnByPulse для низкоуровневого управления
    # Она позволяет задать сервоприводу позицию, которую сервопривод займет моментально, через длину управляющего импульса 
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того сервопривода, который будет соуществлять движение 
    # 2 - длина управляющего импульса 

    errCode = lib.RI_SDK_exec_ServoDrive_TurnByPulse(servo_4, 400, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Мигание светодиода красным цветом
    # Для мигания светодиода можно использовать функцию  RI_SDK_exec_RGB_LED_FlashingWithFrequency
    # Через нее можно задать частоту миганий (Гц) и количество миганий
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того светодиода, который будет соуществлять движение 
    # 2 - яркость красного цвета (0-255)
    # 3 = яркость зеленого цвета (0-255)
    # 4 - яркость синего цвета (0-255)
    # 5 - частота миганий (миганий в секунду)
    # 6 - количество миганий
    # 7 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    errCode = lib.RI_SDK_exec_RGB_LED_FlashingWithFrequency(led, 255, 0, 0, 5, 10, c_bool(False), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)
    
    # Мерцание свтодиода зеленым цветом
    # Для мерцания светодиода можно использовать функцию  RI_SDK_exec_RGB_LED_Flicker
    # Через нее можно задать продолжительность изменения яркости от 0 до максимальной и количество актов 
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того светодиода, который будет соуществлять движение 
    # 2 - максимальная яркость красного цвета (0-255)
    # 3 = максимальная яркость зеленого цвета (0-255)
    # 4 - максимальная яркость синего цвета (0-255)
    # 5 - продолжительность изменения яркости от 0 до максимальной (мс)
    # 6 - количество миганий
    # 7 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    errCode = lib.RI_SDK_exec_RGB_LED_Flicker(led, 0, 255, 0, 300, 3, c_bool(False), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Одиночный световой импульса
    # Для простого свечения можно использовать функцию  RI_SDK_exec_RGB_LED_SinglePulse
    # Через нее можно задать продолжительность свечения  
    # В качестве аргументов необходмио в нее передать 
    # 1 - дескриптор того светодиода, который будет соуществлять движение 
    # 2 - яркость красного цвета (0-255)
    # 3 = яркость зеленого цвета (0-255)
    # 4 - яркость синего цвета (0-255)
    # 5 - продолжительность свечения (мс)
    # 6 - флаг асинхронного режима: true - двигаться асинхронно, false - синхронно 

    errCode = lib.RI_SDK_exec_RGB_LED_SinglePulse(led, 0, 0, 255, 10000, c_bool(False), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # После завршения работы необходимо удалить завршить все опреации, удалить компоненты и объект библиотеки
    # В данном случае необходмио сперва сбросить сигналы со всех портов шим-модулятора
    # Это необходимо для исключения возможности прегорания устройств, подключенных к нему
    # Для сброса всех портов можно воспользоваться функцией RI_SDK_sigmod_PWM_ResetAll
    # В нее достаточно передать дескриптор шим-модулятора, посрты которого необходимо сбросить 

    errCode = lib.RI_SDK_sigmod_PWM_ResetAll(pwm, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Для удаления компонентов можно использовать метод RI_SDK_DestroyComponent
    # В него достаточно передать дескрипотор компонента, который необходимо удалить  

    # Удаление сервоприводов
    errCode = lib.RI_SDK_DestroyComponent(servo_1, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    errCode = lib.RI_SDK_DestroyComponent(servo_2, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    errCode = lib.RI_SDK_DestroyComponent(servo_3, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    errCode = lib.RI_SDK_DestroyComponent(servo_4, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Удаление светодиода

    errCode = lib.RI_SDK_DestroyComponent(led, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Удаление шим-модулятора
    
    errCode = lib.RI_SDK_DestroyComponent(pwm, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Удаление i2c-адаптера

    errCode = lib.RI_SDK_DestroyComponent(i2c, errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)

    # Удаление библиотеки
    # Для удаления библиотеки можно всопользоваться функцией RI_SDK_DestroySDK 
    # в нее необходимо передать значение флага полной очистки реестра (true - полностью)

    errCode = lib.RI_SDK_DestroySDK(c_bool(True), errTextC)
    if errCode != 0:
        print(errCode, errTextC.raw.decode())
        sys.exit(2)
    
    print("Success")



main()

И, наконец, после открытия исходного кода примера можно выбрать в меню пункт “Выполнить текущий скрипт” (горячая клавиша F5), что приведёт к выполнению примера программы.

Внимание! Особенность работы I2C адаптера CH341 заключается в том, что он не поддерживает одновременную работу нескольких подключений. Поэтому, перед выполнением примеров или собственных программ необходимо отключить приложение “Пульт управления РТУ”. Для этого нужно в меню “Пуск” найти папку RoboIntellect, и кликнуть по ярлыку “Остановка пульта управления РТУ”. После этого можно выполнить пример. Если не отключить предварительно пульт, то пример выполнится с ошибкой. В данный момент ведутся работы по обеспечению одновременного программного подключения по I2C для адаптеров ch341.

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

Программа начинается с подключения библиотеки RI SDK и объявления типов аргументов функций RI SDK, которые будут вызываться в примере.

Затем инициализируются объекты I2C адаптера и ШИМ, которые связываются друг с другом.

После этого инициализируются объекты сервоприводов модели mg90s, которые связываются с ШИМ на указанных портах. Аналогичные действия выполняются для светодиода. Ниже приведён пример инициализации компонента.

После выполнения инициализации всех компонентов, поочередно вызываются функции сервоприводов - поворот, вращение, поворот на минимальный шаг, поворот с заданным импульсом. Ниже приведен примерповорота сервопривода на заданный угол. Особого внимания заслуживает параметр ряда функций async (на рисунке ниже в функцию передаётся значение False). Он отвечает за асинхронное выполнение вызываемой ункции. Это позволяет выполнять несколько действий одновременно и параллельно для нескольких компонентов. Например, одновременно вращать несколько сервоприводов. В первом примере все действия выполняются синхронно для упрощения понимания.

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

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

И, наконец, выполняется удаление внутренних системных компонентов библиотеки RI SDK/

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

130001 error in binding PWM to adapter: Connection creation error: Error creating I2C connection: Operation HidSmbus_Open failed

- ошибка возникает, если запускать программу при включенном пульте управления. Решение - временно отключить пульт управления (см. предупреждение выше в этом разделе). Кроме того, такая ошибка возникает, если робот не подключен к компьютеру, или I2C адаптер неправильно подключен к ШИМ.

Запуск программы, написанной с помощью функций - пример №2. #

На примере №2 ознакомимся с концепцией использования функций в различных языках программирования, и в том числе в Python.

Функция в программировании - это объявленный с помощью специального синтаксиса фрагмент исходного кода, который можно неоднократно использовать в различных участках программы с помощью оператора вызова функции. Это позволяет, во-первых, избежать дублирования кода, а во-вторых лучшим образом структурировать программу для упрощения написания кода и его последующей отладки. Функции - это “кирпичи” из которых строятся большинство программ. Более того, механизм импорта модулей Python позволяет функции, написанные для одной программы, использовать в других программах, где требуется схожая функциональность. Для объявления функции применяется оператор def, после которого следует сигнатура функции. Сигнатура функции - это сочетание имени функции, и аргументов, которые она принимает. Если к сигнатуре функции приписать оператор вызова, то есть круглые скобки “()” сразу после имени функции, то произойдет вызов функции, то есть она выполнится. При этом в круглых скобках передаются параметры функции, которые внутри тела функции доступны по именам аргументов, которые описаны в сигнатуре.

Для демонстрации необходимо открыть файл с исходным кодом C:\Program Files(x86)\RoboIntellect\ri_sdk\examples\python\example_2_1_cp2112.py.

В этом примере сначала объявляются необходимые для работы переменные, затем инициализируются RI SDK и ряд компонентов, после чего выполняется движение сервопривода башни из стороны в сторону. В завершение выполняется освобождение выделенной для компонентов из этого примера памяти. Для реализации движения из стороны в сторону используется функция

RI_SDK_exec_ServoDrive_Turn(),

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

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

Дублирования кода можно избежать, если перенести код вызова RI SDK и обработку ошибок в отдельную функцию. Рассмотрим пример C:\Program Files(x86)\RoboIntellect\ri_sdk\examples\python\example_2_2_cp2112.py (или C:\Program Files (x86)\RoboIntellect\ri_sdk\examples\python\example_2_2_ch341.py, если у вас RM001M2). В нём поворот сервопривода и обработка ошибки вынесены в отдельную функцию.

Это позволило сократить повороты башни из стороны в сторону всего до нескольких строчек кода:

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

Запуск более сложной программы - пример №3 #

Для запуска этой программы необходимо открыть исходный код готового примера через IDE IDLE, используя проводник ОС, или навигатор интерфейса самой IDE. Исходный код примера на Python - это файл

C:\Program Files(x86)\RoboIntellect\ri_sdk\examples\python\example_3_cp2112.py.

Третий пример программы для роборуки на Python является более сложным, так как является интерактивной программой, то есть подразумевается взаимодействие с пользователем для управления устройством. Кроме того, программа структурирована особым образом с помощью функций.

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

В примере, который приводится в этом разделе “сплошной” код работы с компонентами устройства разбит на несколько функций, что позволило сократить объем кода, и повторно использовать однажды написанный код. Например, в примере №1 много раз встречается вызов функции создания компонента (см. рисунок ниже).

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

Это позволило, например, не писать проверку ошибки вызова функции RI SDK для каждого компонента в отдельности (см. рисунок ниже).

Программа из примера №3 состоит из трёх файлов исходного кода. В первом, example_3_cp2112.py хранится исходный код базового алгоритма программы, и содержит в себе точку входа в программу - функцию main().

Все функции используемые в этом исходном коде объявлены в отдельном файле, robohand.py, который импортируется в программу в качестве модуля. Модулем в Python является любой файл исходного кода, который подключается в программу с помощью оператора import. Модуль предоставляет все свои функции, переменные и объекты для повторного использования в программе. И, наконец, постоянные величины, используемые в example_3_cp2112.py и robohand.py, то есть так называемые константы, вынесены в третий файл - constants.py. Важное отличие примера №3 - это наличие некоторой, пусть и примитивной, интерактивности. То есть программа взаимодействует с пользователем и ожидает принятия решения от него. Пользователь может сообщить программе свой выбор с помощью ввода управляющих символов в терминале (большинство IDE, в том числе и IDLE, интегрирует в себя терминал операционной системы).

Программа начинает свою работу с того, что задает роборуке исходное положение. Затем роборука демонстрирует точку, в которую необходимо установить кубики, поставляющиеся вместе с конструктором. Пользователь устанавливает два кубика друг на друга. Пользователь может ввести символ “1” с клавиатуры, и нажать enter, чтобы роборука начала перемещение кубиков в целевую точку, или ввести “2”, если хочет ещё раз увидеть, в какую позицию необходимо поставить кубики. Программа выполняет перемещение кубиков в целевую точку, после чего “просит” пользователя выбрать, хочет ли он повторить упражнение, для чего нужно ввести символ “2”, или завершает свое выполнение, если пользователь просто нажал “enter”. В процессе выполнения программа сигнализирует о выполняемых действиях с помощью светодиода. Он загорается красным, когда работают сервоприводы, и горит зелёным цветом, когда программа ожидает действия пользователя. Для того, чтобы свечение светодиода не препятствовало работе сервоприводов, функция свечения светодиода запускается в асинхронном режиме, то есть параметр async передаётся в функцию со значением True.

Краткое перечисление функций RI SDK. #

Подробную информацию по функциям внешнего API RI SDK, параметрам вызова с примерами использования следует искать в документации на официальном сайте проекта - https://robointellect.ru/docs/155.


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

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

Для участия в обсуждении Вы должны быть авторизованным пользователем
Разделы

Навигация

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