ГЛАВА 6. РАБОТА МОДУЛЯ TRACKINGCAMС КОНТРОЛЛЕРОМ OPENCM

Контроллер OpenCM, является официальным opensource контролле ром, поставляемым компанией Robotis для использования совместно со своими комплектующими. По своей структуре и среде разработки контроллер OpenCM очень напоминает Arduinoподобные платы, за исключением того, что его программирование осуществляется из собственной среды разработки Robotis IDE (Robotis OpenCM) (рис. 6.1). Данная среда

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

Несмотря на это неудобство, по умолчанию в среду уже добавлено большое количество библиотек и примеров работы с ними, предназначенных для работы со всеми робототехническими компонентами, предлагаемыми компанией Robotis, а так же с компонентами сторонних производителей, использующих в своих разработках либо элементы от Robotis, либо совместимые протоколы передачи данных.

Рис. 6.1 Внешний вид среды разработки Robotis IDE

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

с Robotis IDE поставляется библиотека с одноименным названием, позволяющая обмениваться данными по протоколу как на низком уровне побайтово, так и прикладными командами, например, вращать вал сервопривода в определенном направлении с заданной скоростью.

Модуль технического зрения TrackingCam является Dynamixelсовместимым устройством, поэтому его работа с контроллерами OpenCM и CM530 аналогична, а именно сводится к чтению данных из памяти телекамеры по заданным адресам в соответствующие переменные для дальнейшего использования.

Для использования модуля TrackingCam с контроллером OpenCM рекомендуется выполнять подключение через плату расширения — либо через Expansion Board 485, либо через STEM Board и при работе использовать либо внешний аккумулятор, либо внешний блок питания. Подключение модуля может быть произведено к любому свободному 3х выводному разъему Dynamixel. Варианты подключения TrackingCam приведены на рисунках 6.2 (а) и (б).

a) ![[media/image36.jpeg]]

б) ![[media/image37.jpeg]

Рис. 6.2 Варианты подключения TrackingCam к OpenCM.

а) через Expansion Board 485, б) через STEM Board

Процесс разработки программы для опроса модуля в обоих случаях подключения будет абсолютно одинаков. Создадим новую программу (скетч) в среде Robotis IDE. Для дальнейшего удобства сразу создадим две структуры: TrackingCamBlobInfo_t и TrackingCamObjInfo_t. В пер вой будет переменные для хранения данных о распознанных областях, а в другой — о распознанных объектах. Внутри первой структуры разме стим следующие переменные:

  • type типа uint8 для хранения номера шаблона (типа) однотонного объекта
  • cx типа uint16 для хранения значения положения центра объекта по оси Х;
  • су типа uint16 для хранения значения положения центра объекта по оси Y;
  • area типа uint32 для хранения значения площади объекта;
  • left типа uint16 для хранения значения левой границы объекта;
  • right типа uint16 для хранения значения правой границы объекта;
  • top типа uint16 для хранения значения верхней границы объекта;
  • bottom типа uint16 для хранения значения нижней границы объекта

Внутри второй структуры, отвечающей за хранение информации об объектах разместим аналогично переменные :

  • type типа uint8 для хранения значения типа объекта
  • cx типа uint16 для хранения значения центра объекта по Х
  • су типа uint16 для хранения значения центра объекта по Y
  • angle типа uint16 для хранения значения угла поворота объекта
  • obj_size типа uint32 для хранения значения размера объекта Теперь объявим массивы вновь определенных структур:

TrackingCamObjInfo_t obj[10]; TrackingCamBlobInfo_t blob[15];

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

struct TrackingCamBlobInfo_t { 

uint8 type;
uint16 cx; 
uint16 cy; 
uint32 area; 
uint16 left; 
uint16 right; 
uint16 top; 
uint16 bottom;

};

struct TrackingCamObjInfo_t { 
uint8 type;
uint16 cx; 
uint16 cy; 
uint16 angle; 
uint32 obj_size;

};

TrackingCamObjInfo_t obj[10]; 
TrackingCamBlobInfo_t blob[15];
Объявим переменную ID_NUM со значением 51 — ID модуля TraсkingCam, переменную addr типа uint16, которая содержит в себе значение адреса памяти с которого необходимо начинать считывание

данных и укажем номер интерфейса Dynamixel, к которому подключен модуль. Номер этого интерфейса определяется куда именно подключен модуль. Если напрямую к плате OpenCM в соответствующий разъем, то его значение 1, если к плате OpenCM и в коммуникационный разъем, то 2, а если к плате Expansion Board или STEM Board, то 3. В нашем случае используется именно последний вариант.

Таким образом 3 последних строчки кода будут выглядеть следующим образом:

#define ID_NUM 51 
uint16 addr = 16; 
Dynamixel Dxl(3);
Перейдем к заполнению функции void setup(). Внутри нее разместим команды инициализации соединения с Dynamixel-совместимым устройством и компьютером, задержку перед началом работы и вывод данных в терминал компьютера о подключенном модулем TrackingCam. Функция в итоге будет выглядеть следующим образом:

void setup() {

SerialUSB.begin(); //инициализация соединения с компьютером по 
USB Dxl.begin(3); //инициализация соединения с Dynamixel-устройством на 3ей скорости (1Мбит\с)
delay(3000); //пауза в 3000 мс
SerialUSB.println(«TrackingCam ID:»); //вывод в терминал на экране компьютера сообщения «TrackingCam ID:» 
SerialUSB.println(Dxl.readByte(ID_NUM, 0x00)); //вывод в терминал на экране компьютера данных о модуле
}

Для получения данных с модуля используется функция Dxl.readByte(), с параметрами ID_NUM и адресом считывания.

Для получения данных об однотонных объектах создадим отдельную функцию TrackingCamGetBlobs(). В ней будет циклически выполняться следующие операции:

  1. Считывание данных по указанному адресу;
  2. Присвоение полученного значения переменной массива, представляющей хранящуюся в телекамере по текущему адресу величину;
  3. Смещение адреса;
  4. Вывод полученного результата в терминал на экране компьютера. Для реализации этой последовательности поместим внутрь функ-

ции переменную curAddr типа uint16, в которой будет хранится текущий адрес, по которому выполняется считывание. Проинициализируем эту переменную значением переменной addr – адресом, по которому в памяти телекамеры хранится таблица текущих данных. После этого создадим цикл for который будет осуществлять 16 итераций по опросу модуля. Вну-

три этого цикла сразу разместим вывод на экран значений, полученных в текущей итерации. После этого получим данные о типе объекта и присвоим их соответствующей переменной нашего массива, сместим адрес на 2 байта и выведем на экран полученный тип.

Код для этой операции будет выглядеть следующим образом:

uint16 curAddr = addr;

for (uint8 i = 0; i < 16; i++){ 
SerialUSB.print(i); 
SerialUSB.print(« «);
blob[i].type = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; 
SerialUSB.print(blob[i].type);
SerialUSB.print(« «);
Затем сделаем проверку полученного типа на совпадение со следующими значениями:

  • 255 (пустое значение)
  • 1 (ошибка)
  • 248 (специальный символ)

При совпадении с каким-либо из этих значений необходимо остановить выполнение цикла и выйти из него. Для этого используем оператор break:

if (blob[i].type == 255 || blob[i].type == -1 || blob[i].type == 248){ 
break;
}

Если все в порядке и значение поля типа объекта валидное, то далее начинается повторяющийся процесс получения требуемых данных, присвоение полученных значений соответствующим переменным, смещение адреса, вывод полученного значения. Данный процесс будет выполняться до тех пор, пока не закончатся распознанные объектов, либо до тех пор пока не будут получены данные о 16 объектах. Для использования этой функции разместим ее вызов в функции void loop() с паузой в 500 мс.

В результате код программы будет выглядеть следующим образом:

struct TrackingCamBlobInfo_t

{

uint8 type; 
uint16 cx; 
uint16 cy; 
uint32 area; 
uint16 left; 
uint16 right; 
uint16 top;
uint16 bottom;

};

struct TrackingCamObjInfo_t

{

uint8 type; 
uint16 cx; 
uint16 cy; 
uint16 angle; 
uint32 obj_size;

};

TrackingCamObjInfo_t obj[10]; 
TrackingCamBlobInfo_t blob[15]; 
#define ID_NUM 51

uint16 addr = 16; Dynamixel Dxl(3); 
void setup() { 
SerialUSB.begin(); 
Dxl.begin(3); 
delay(3000);

SerialUSB.println(«TrackingCam ID:»); 
SerialUSB.println(Dxl.readByte(ID_NUM, 0x00));

}

void loop() { 
TrackingCamGetBlobs(); 
delay(500);

}

void TrackingCamGetBlobs (){ uint16 curAddr = addr;

for (uint8 i = 0; i < 16; i++){ 
SerialUSB.print(i); 
SerialUSB.print(« «);
blob[i].type = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; 
SerialUSB.print(blob[i].type);
SerialUSB.print(« «);

if (blob[i].type == 255 || blob[i].type == -1 || blob[i].type == 248){ 
break;
}

blob[i].cx = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].cx);

SerialUSB.print(« «);

blob[i].cy = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].cy);

SerialUSB.print(« «);

blob[i].area = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].area);

SerialUSB.print(« «);

blob[i].left = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].left);

SerialUSB.print(« «);

blob[i].right = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].right);

SerialUSB.print(« «);

blob[i].top = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.print(blob[i].top); SerialUSB.print(« «);

blob[i].bottom = Dxl.readByte(ID_NUM, curAddr); 
curAddr = curAddr + 2; SerialUSB.println(blob[i].bottom);

Если полученный код запустить и открыть окно терминала, то результат будет аналогичен, представленному на рисунке 6.3.

В нем:

  • первое число — последняя итерация, на которой произошла остановка цикла for в результате срабатывания одного из условий.
  • второе число — значение типа, полученное на последней итерации (255 — пустое)
  • третье число — значение последней итерации на которой была корректно получения информация о распознанной области
  • четвертое и далее числа — информация об объекте, представленная в соответствии со структурой TrackingCamBlobInfo.

Таким образом можно получить информацию о распознанной области с помощью контроллера OpenCM.

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

Рис. 6.3 Вывод данных с OpenCM


Center-nav

← Назад | Оглавление | Вперёд →