Ваш браузер устарел. Рекомендуем обновить его до последней версии.

Программирование модуля UMM01 на примере управления сервоприводами "Dynamixel" 

        Этой статьей начинается цикл примеров по использованию универсального микропроцессорного модуля UMM01.

        В первой статье будут рассмотрены основные подходы к программированию модуля. В качестве примера программы приводится библиотека функций для управления цифровыми сервоприводами Dynamixel. Предполагается, что читатель хотя бы немного знаком с микроконтроллерами (не обязательно с PIC, но желательно) и с языком Си. Пример можно использовать в качестве шаблона для любых процессоров PIC24F, однако,  далее, в тексте статьи и в комментариях к программе, автор ссылается на схему модуля.

        Проект сделан под среду разработки MPLAB X и новый компилятор xc16, которые свободно распространяются с официального сайта Microchip. Компилятор можно устанавливать в “Lite” версии, от платной он отличается только степенью оптимизации.

        Загрузить проект.

Проект включает в себя следующие файлы:

  1. «Main.c» - текст основной программы.
  2. «Main.h» - определения.
  3. «Dynamixel.c» - текст функций библиотеки.
  4. «Dynamixel.h» - определения библиотеки.

Для подключения библиотеки к проекту в файле «Main.c» имеется строка #include "Dynamixel.h".

Режимы работы линий ввода/вывода процессоров семейства PIC24FJ256GB210

        Первой задачей при разработке программы обычно является инициализация линий ввода/вывода. В простейшем случае необходимо только определить, должна ли быть заданная линия входом или выходом. Это выполняется записью значений в регистр TRIS. На Си это выглядит так:

TRISCbits.TRISC2=0;          //Линию управления светодиодом HL1 задаем как выход

Задание выходных уровней осуществляется так:

LATCbits.LATC2=1;             //Включить светодиод

Еще можно задать выход любой линии как выход с открытым стоком. Это производится записью единицы в регистр ODC:

ODCCbits.ODC2=1;

        Данная функция полезна при стыковке этого процессора, который питается от 3-х вольт, с 5-ти вольтовой логикой. У PIC24FJ256GB210 есть набор так называемых толерантных к 5-ти вольтам линий. В pdf на процессор на «Pin diagram» они обозначены серым цветом. На эти линии можно подавать 5-ти вольтовый уровень. Если необходимо выдать уровень 5В, то соответствующая линия программируется как выход с открытым стоком, к ней подключается подтягивающий резистор, на который в свою очередь подается 5В. Эта функция работает и с периферией. Некоторые подтягивающие резисторы установлены на плате модуля (см. схему).

        После сброса, те линии, на которые заведены входа АЦП (их всего 24 шт.), будут аналоговыми входами. Если такую линию требуется использовать в качестве цифровой, вход АЦП нужно отключить регистром ANS.

    ANSBbits.ANSB2=0;      //линия RB2 – цифровая

        Так же у процессора есть большое число переназначаемых линий, к которым можно подключать почти все периферийные модули (кроме модулей I2C и АЦП). Эта возможность процессора, на взгляд автора, является чрезвычайно удобной при использования модуля UMM01. Благодаря ей пользователи получают множество вариантов подключения широкого спектра внешних устройств. Эти линии обозначены в документации на процессор как RPx и RPIx (RPI – линии только на вход).

        Назначение линий входам и выходам периферийных модулей производится по разному.

        Для назначения входа необходимо открыть таблицу 10-3 (TABLE 10-3) в pdfи выбрать требуемый вход. Из колонки "Register" берем название регистра, из колонки “Function mapping bits” берем название битов, имеющих отношение к данному входу. Затем этим битам присваиваем номер RPx или RPIx линии. Если присваивается линия RPIx, то в дополнение через регистр TRIS необходимо задать эту линию входом. Допустим, требуется присвоить входу UART1 линию RPI43/RD14 (это делается в примере программы). В колонке "Input Name" находим вход UART1: UART1 Receive. Затем в колонке "Register" находим регистр “RPINR18”, в колонке “Function mapping bits” биты “U1RXR”.  Получим:

RPINR18bits.U1RXR=43;   //Ко входу Rx порта UART1 подключаем линию RPI43  (RD14)

TRISDbits.TRISD14=1;       //RD14 – вход

        Для назначения выхода нужно открыть таблицу 10-4 3 (TABLE 10-4) в pdf и выбрать требуемый выход. Для UART1 выбираем U1TX. Далее, из колонки “Output Function Number” берем соответствующий номер функции (в данном примере - 3). Далее открываем таблицу 4-30 (TABLE 4-30) и ищем там биты требуемой линии. В примере выход UART1 нужно подключить к линии RP5. Через поиск находим биты RP5R в регистре RPOR2. Далее этим битам нужно присвоить найденный ранее номер функции:

   RPOR2bits.RP5R=3;        //К линии RP5 (RD15) подключаем выход Tx порта UART1

 

Краткое описание Dynamixel

        Для того, что бы понять логику работы программы, нужно знать принцип обмена данными с сервоприводами Dynamixel. Ниже приводится краткое описание их работы, полная тех. информация находится в pdf на конкретный двигатель. Для примера на сайте размещен pdf на двигатели DX113, DX116, DX117.

        Сервоприводы Dynamixel – это полностью цифровые двигатели компании ROBOTIS, сконструированные специально для робототехники. Управление ими осуществляется по последовательному каналу с адресацией, поэтому к одной шине можно подключать несколько сервоприводов. Подача команд управления осуществляется записью требуемых значений в ячейки внутренней памяти двигателя. Например, для установки ротора двигателя в позицию 300 необходимо записать двухбайтовое значение 300 по адресу внутренней памяти 0x1E. Далее, внутренний процессор двигателя самостоятельно обеспечит выполнение заданных изменений. Помимо целевой позиции можно задавать достаточно большое число параметров – скорость поворота, максимальную нагрузку и т.д. Считывание состояния сервопривода производится аналогично – чтением ячеек памяти. Распределение памяти у всех моделей практически одинаковое. Поэтому создав программу для одной модели двигателя, ее можно будет использовать и для другой модели.

        Сервоприводы Dynamixel управляются по последовательному каналу типа UART, однако электрические интерфейсы у них разные (не RS232). Они выпускаются с двумя типами интерфейсов – 4-х проводный (он же RS485) и 3-х проводный (более новые модели). С программной точки зрения они работают одинаково, но электрически – это разные схемы. Поэтому в модуле UMM01 подключение 4-х проводного интерфейса осуществляется через микросхему D7 (MAX485) и разъемы X29, X30, а подключение 3-х проводного – через микросхему D2 (D2A и D2B, 74HC125) и разъемы X6, X7.

        Небольшое отступление:  схема модуля достаточно громоздка и визуально искать что-то на ней неудобно. Однако, она размещена в формате PDF, поэтому можно пользоваться поиском (Ctrl F).

        Одновременно по обоим интерфейсам осуществляется либо только передача, либо прием (режим полудуплекса). Поэтому, кроме линий входов/выходов UART, к каждому интерфейсу добавлена линия переключения направления. Ниже приводится таблица используемых в модуле линий процессора. В ней так же указаны перемычки,  которые должны быть замкнуты джамперами.

 

Название линии процессора

4-х проводный интерфейс

3-х проводный интерфейс

Замкнутые перемычки

4-х проводного

Замкнутые перемычки

3-х проводного

Rx

RPI43/RD14 (pin 47)

RPI36/RA14 (pin 66)

J10

J12

Tx

RP5/RD15

(pin 48)

RP15/RF8 (pin 53)

 

 

Переключение прием/передача

RG0 (pin 90)

RG1 (pin 89)

J9

 

 

        Небольшое отступление: если не замыкать перемычку J9, то на pin2 микросхемы D7 будет подаваться низкий уровень, что позволит производить одновременный прием передающихся байт. Этот режим можно использовать для тестирования выходного порта RS485.

        Формат передающихся и принимаемых пакетов следующий:

  1. Нулевой и первый байт в пакете равны 0xff.
  2. Второй байт – адрес сервопривода, к которому происходит обращение.
  3. Третий байт – количество всех последующих байт, включая контрольную сумму.
  4. Байты данных. (см. документацию).
  5. Контрольная сумма. Алгоритм ее подсчета см. в тексте примера программы.

        Скорость работы порта по умолчанию в 4-х проводных сервоприводах задана 56 кбит/с, а в 3-х проводных 1мбит/с. В примере программы заданы эти же скорости.

        Напряжение питания сервоприводов Dynamixel подключается через разъем X12.

        Теперь можно перейти непосредственно к рассмотрению работы примера программы для модуля UMM01.

 

Работа примера программы.

        После инициализаций, в функции main() производится последовательный опрос кнопок SB2 и SB3. При нажатии какой-нибудь из кнопок выполняется вызов функции MoveDyn() для установки сервопривода в заданную позицию. При этом на время движения загорается один из светодиодов. Окончание движения ротора определяется вызовом Moving():

while (Moving(1));//Ждать окончания движения

         Интерфейс (3-х или 4-х проводный) выбирается строкой:

#define DYNAMIXEL_3PIN    //Если используется 4-х проводный интерфейс, эту строку

                                           //нужно закомментировать

        Основные функции библиотеки – это функции обмена пакетами по UART1. Из файла “Main.c” эти функции явно не вызываются, их вызов включен в функции непосредственного управления сервоприводом. Прием пакетов производится только по прерыванию, после принятия пакета устанавливается флаг “HvDynamixelPacket”. Принятые данные будут находиться в массиве PacketRec_U1[].

        Передача производится вызовом функции TrmPacket_U1(). Она так же осуществляется по прерыванию. Поэтому выход из функции происходит сразу после начала передачи пакета. На время передачи устанавливается флаг Transmitting_U1, по которому можно определять передан ли пакет.

        Прием заданного числа байт из Dynamixel осуществляется функцией с прототипом:

int RecDynamixel(unsigned char AddrDyn, //Адрес сервопривода

                unsigned char AddrMem,  //Адрес ячейки памяти в Dynamixel

                unsigned char N         //Число байт, которые необходимо принять

                    )

        Принятые данные тоже будут находится в массиве PacketRec_U1[].

        Таким образом, функциями MoveDyn() и Moving() можно непосредственно управлять положением двигателя, а с помощью функций TrmPacket_U1() и RecDynamixel() основная программа получает доступ к пространству памяти сервопривода.

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

Автор:    Вячеслав Кулаков       03.09.2012г.

              www.robowell.ru

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