Перейти к содержанию

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

Рассматриваемые модули обладают двумя глобальными подходами к их применению. Первый подход они могут выступать как классические Arduino-датчики, подключение к которым выполняется с помощью стандартных проводов типа «мама-мама» или «папа-мама». Для такого способа подключения все модули имеют в своем составе шестипиновую гребенку с контактными линиями и на оборотной стороне каждого модуля есть расшифровка каждого пина. Для облегчения подключения модулей к Arduino может быть использована плата расширения для подключения сенсорных модулей AR-SENS-RJ14. Подключение модулей выполняется через встроенные разъемы RJ14 платы расширения.

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

Модули как Arduino-датчики

Для работы с периферийными модулями, как с Arduino-устройствами, можно использовать любую Arduino-подобную плату с выведенными необходимыми интерфейсами на ней и классическую среду разработки Arduino IDE. В качестве вычислительной платформы подойдет любая платформа, которую можно запрограммировать с помощью Arduino IDE. В данном случае рассмотрим способы работы с датчиками на примере Arduino подобной плате «Программируемому контроллеру моделей инженерных систем» («Контроллер КПМИС») в таблице 2.1 показаны базовые интерфейсы модулей и направление обмена данными с ними.

Наименование модуля Направление данных Тип интерфейса
1 Модуль «Аудиоусилитель» Передача на модуль прочее
2 Модуль «Датчик атмосферного давления» Чтение с модуля I2C
3 Модуль «Датчика линии» Чтение с модуля цифровой
4 Модуль «Датчик наклона» Чтение с модуля цифровой (2 линии)
5 Модуль «Датчик температуры и влажности» Чтение с модуля прочее
6 Модуль «Датчик цвета» Чтение с модуля I2C
7 Модуль «Датчик шума» Чтение с модуля аналоговый
8 Модуль «Драйвер двигателя постоянного тока» Передача на модуль прочее (цифровой + PWM)
9 Модуль «Драйвер двигателя постоянного тока (2 канала)» Передача на модуль прочее (цифровой + PWM) x2
10 Модуль «Звуковой пьезоизлучатель» Передача на модуль цифровой (PWM)
11 Модуль «ИК приемник» Чтение с модуля цифровой
12 Модуль «Инерциальный датчик и магнетометр» Чтение с модуля I2C
13 Модуль «Концевой микропереключатель» Чтение с модуля цифровой
14 Модуль «Тактовая кнопка» Чтение с модуля цифровой
15 Модуль «Потенциометр» Чтение с модуля аналоговый
16 Модуль «Светодиод» Передача на модуль цифровой
17 Модуль «Силовой ключ» Передача на модуль цифровой
18 Модуль «Трехцветный светодиод» Передача на модуль цифровой
19 Модуль «Энкодер» Чтение с модуля цифровой
20 Модуль «Ультразвуковой дальномер» Чтение с модуля цифровой
21 Модуль «Джойстик» Чтение с модуля аналоговый
22 Модуль «Освещенности» Чтение с модуля аналоговый
23 Модуль «Силы» Чтение с модуля аналоговый
24 Модуль «Преобразователь интерфейсов» Чтение с модуля и запись на модуль цифровой

Таблица 2.1. Базовые интерфейсы модулей

Цифровые и аналоговые модули

Под цифровым или аналоговым модулем в рамках данного пособия понимается модуль со способом подключения, при котором используется 3 линии: питание, земля и сигнальная линия, которая в зависимости от типа модуля подключается либо к цифровой линии (передает или получает «0» или «1») контроллера, либо к аналоговой линии (получает непрерывный сигнал и декодирует его в диапазон 0 – 1023), либо к PWM линии (способной генерировать сигнал заданного уровня). Таким образом, работа с цифровыми датчиками при получении данных с них сводится к фиксированию уровня сигнала «0» или «1» (такие модули как: датчик линии, наклона, ИК приемника, концевого выключателя, тактовой кнопки, ИК энкодера). При управлении цифровым модулем можно передавать на него «0» или «1» для включения / выключения модуля (модули силового ключа, светодиода, трехцветного светодиода). Для примера такого способа управления рассмотрим светодиоды – при их включении они будут светить в полную силу. Однако, если необходимо управлять яркостью их свечения, то требуется подключить светодиоды к цифровым линиям с поддержкой PWM, после чего задавать уровень яркости их свечения программным способом. Так же, управление с помощью PWM линии обязательно для таких устройств, как модуль «Звуковой пьезоизлучатель» – для генерирования звуков. Таким образом, способ подключения цифровых модулей к контроллеру выбирается пользователем в зависимости от требований к решению задачи. При получении данных с аналогового модуля (датчик шума и потенциометр) непрерывный выходной сигнал с модуля должен быть оцифрован с помощью встроенного в контроллер АЦП и на выходе будет получено некое значение в диапазоне от 0 до 1023, соответствующее уровню выходного сигнала в диапазоне от 0 до 5В.

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

Опрос модуля «Тактовая кнопка»

Подключаем модуль «Тактовая кнопка» к контроллеру КПМИС в соответствии со схемой расположения контактов. Линию модуля 5В подключаем к линии 5В контроллера, линию GND – к GND контроллера, а SIG – к цифровой линии. В результате, подключённый к модуль будет выглядеть следующим образом (см. Рис. 2.1 и Рис. 2.2).

Рис. 2.1. Подключение модуля «Тактовая кнопка» к контроллеру КПМИС

Рис. 2.2. Схема подключения модуля «Тактовая кнопка» к контроллеру КПМИС

Для работы с модулем «Тактовая кнопка» напишем в среде Arduino IDE следующий код:

// номер цифровой линии, к которой подключен SIG const 
int buttonPin = 8;

// переменная для хранения состояния кнопки 
uint8_t buttonState = 0;

//инициализируем соединение по последовательному порту 
Serial.begin(115200);

// инициализируем цифровую линию SIG, как вход 
pinMode(buttonPin, INPUT);

}

void loop(){

//считываем значения с цифровой линии 
buttonState = digitalRead(buttonPin);

// проверяем, нажата ли кнопка

// если нажата, то buttonState будет иметь значение «HIGH»: 
if (buttonState == LOW) {

// сообщаем, что кнопка нажата 
Serial.println(Button pressed);

}

else {

// сообщаем, что кнопка не нажата 
Serial.println(Button not pressed);

}

// пауза в полсекунды при опросе кнопки 
delay(500);

}
И загрузим его в контроллер стандартным способом. В результате, если открыть монитор порта на скорости 115200 и понажимать на кнопку, можно увидеть, как меняется состояние системы (Рис. 2.3):

Рис. 2.3. Вывод в монитор порта информации о нажатии кнопки

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

Управление модулем «Трехцветный светодиод»

Подключаем модуль «Трехцветный светодиод» к контроллеру КПМИС, в соответствии со схемой расположения контактов. Линию модуля 5В подключаем к линии 5В контроллера, линию GND – к GND контроллера, а линии управления цветовыми составляющими R, G и B – соответственно, к цифровым линиям. В результате, подключённый к контроллеру КПМИС модуль будет выглядеть следующим образом (Рис. 2.4 и Рис. 2.5):

Рис. 2.4. Подключение модуля «Трехцветный светодиод» к контроллеру КПМИС

Рис. 2.5. Схема подключения модуля «Трехцветный светодиод» к контроллеру КПМИС

Для управления светодиодом напишем в среде Arduino IDE следующий скетч и загрузим его в контроллер стандартным способом:

// номера цифровой линии, к которой подключены линии RGB const 
int RPin = 6;
const int GPin = 7; 
const int BPin = 8;

// инициализируем цифровые линии, как выход 
pinMode(RPin, OUTPUT);
pinMode(GPin, OUTPUT); 
pinMode(BPin, OUTPUT);

}

void loop(){

// включаем все составляющие последовательно

// через каждые 2 секунды 
digitalWrite(RPin, HIGH); 
delay(2000); 
digitalWrite(GPin, HIGH); 
delay(2000); 
digitalWrite(BPin, HIGH); delay(2000);

// выключаем все составляющие 
digitalWrite(RPin, LOW);
digitalWrite(GPin, LOW); 
digitalWrite(BPin, LOW);

// плавное включение красного 
for (int i=0; i<255; i++){ 
analogWrite(RPin,i);
delay(5);
}

// выключаем составляющую 
digitalWrite(RPin, LOW);

// плавное включение зеленого 
for (int i=0; i<255; i++){ 
analogWrite(GPin,i);
delay(5);
}

// выключаем составляющую 
digitalWrite(GPin, LOW);

// плавное включение синего 
for (int i=0; i<255; i++){ 
analogWrite(BPin,i);
delay(5);
}
// выключаем составляющую 
digitalWrite(BPin, LOW);
}

В результате, трехцветный светодиод на модуле будет вести себя следующим образом:

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

Аналогичным образом, но используя другие функции, происходит управление модулем «Звуковой пьезоизлучатель» (см. Рис. 2.6 и Рис. 2.7):

Рис. 2.6. Подключение модуля «Звуковой пьезоизлучатель» к контроллеру КПМИС

Рис. 2.7. Схема подключения модуля «Звуковой пьезоизлучатель» к контроллеру КПМИС

Код в среде Arduino IDE, в этом случае, будет выглядеть следующим образом:

// номер цифровой линии, к которой подключен звуковой пьезоизлучатель

const uint8_t BuzzPin = 8;

void setup(){

// Выводим звуковой сигнал с частотой 2048 Гц и длительностью 0,1 сек 
tone(BuzzPin, 2048, 100);

delay(200);

// повторяем вывод звука 
tone(BuzzPin, 2048, 100);

}

void loop(){
}
В результате загрузки управляющей программы в контроллер, сразу после загрузки модуль «Звуковой пьезоизлучатель» издаст 2 коротких сигнала.

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

Получение данных с модуля «Потенциометр»

Подключаем модуль «Потенциометр» к контроллеру КПМИС, в соответствии со схемой расположения контактов. Линию модуля 5В подключим к линии 5В контроллера, линию GND – к GND контроллера, а линию SIG подключим к аналоговой линии. В результате, подключённый к контроллеру КПМИС модуль будет выглядеть следующим образом (см. Рис. 2.8 и Рис 2.9):

Рис. 2.8. Подключение модуля «Потенциометр» к контроллеру КПМИС

Рис. 2.9. Схема подключения модуля «Потенциометр» к контроллеру КПМИС

void setup() {

// инициализируем соединение по последовательному порту 
Serial.begin(115200);

}

void loop(){

// читаем данные на аналоговом порту в переменную 
int PotValue = analogRead(A0);

// выводим данные в монитор порта 
Serial.println(PotValue);

// пауза 
delay(100);

}

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

Таким образом, возможны обмен и получение данных с простейших цифровых и аналоговых модулей, подключенных к Arduino-подобным контроллерам. Оставшиеся нерассмотренные цифровые и аналоговые модули обладают теми же подходами к работе, что и те модули, которые были рассмотрены ранее. Рис. 2.10. Окно монитора порта с показаниями модуля «Потенциометр»

I2C модули

I2C интерфейс широко распространен в современной электронике. Данный интерфейс представляет собой две двунаправленные линии связи, называемые линией последовательных данных (SDA) и линией тактирования (SCL), которые реализуют последовательный протокол обмена данными. В дополнение к двум сигнальным линиям требуются линия питания и земля. Данный интерфейс позволяет последовательно подключать несколько модулей к одному контроллеру. Это происходит благодаря тому, что каждый I2C модуль является ведомым устройством (Slave) и имеет уникальный адрес, за счет которого ведущее устройство (Master) способно находить конкретное устройство в цепи и обмениваться данными именно с ним. Таким образом, устройства, поддерживающие I2C интерфейс, могут быть очень разнообразными по своей сути. И для работы с ними, как правило, применяются соответствующие библиотеки, существенно облегчающие процесс написания кода и обработки данных.

В качестве примера рассмотрим процесс работы с модулем «Датчика атмосферного давления» на чипе BMP280. Подключаем данный модуль к контроллеру КПМИС, в соответствии со схемой расположения контактов. Линию модуля 5В подключим к линии 5В контроллера, линию GND – к GND контроллера, а линии интерфейса SCL и SDA, соответственно к SCL и SDA на плате. В результате, подключённый к контроллеру КПМИС модуль будет выглядеть следующим образом (см. Рис. 2.11 и Рис 2.12):

Прежде чем приступить к написанию кода программы, для упрощения этого процесса требуется скачать библиотеку для работы с датчиком атмосферного давления (барометром) на чипе BMP280. Таких библиотек существует много, в данном примере воспользуемся библиотекой iarduino_Pressure_BMP, скачиваемой с сайта https://iarduino.ru/file/227. html.

Рис. 2.11. Подключение модуля «Датчик атмосферного давления» к контроллеру КПМИС

Рис. 2.12. Схема подключения модуля «Датчик атмосферного давления» к контроллеру КПМИС

После загрузки, библиотеку требуется установить в среду разработки стандартными методами, после чего можно приступать к написанию кода. Код для работы с модулем «Датчик атмосферного давления» будет выглядеть следующим образом:

// подключение библиотеки для работы с I2C интерфейсом 
#include <Wire.h>

// подключение библиотеки «iarduino_Pressure_BMP» 
#include <iarduino_Pressure_BMP.h>

// объявление объекта sensor для работы с датчиком давления 
iarduino_Pressure_BMP sensor;

void setup(){

// инициализируем соединение по последовательному порту 
Serial.begin(115200);

delay(1000);

// инициируем работу с датчиком. Текущая высота будет принята за 0 м. 
sensor.begin();

}

void loop (){

// Считываем данные и выводим следующие параметры: температуру в °С, давление в мм. рт. ст., изменение высоты, относительно значения, указанного в функции begin (по умолчанию 0 метров).

if(sensor.read(1))

{
Serial.println((String)CEHCOP BMP + sensor.type + : \t P =  + sensor. pressure + “\tMM.PT.CT, \t T =  + sensor.temperature +  *C, \t\t B = +sensor. altitude+ M.);
}

else
{Serial.println(HET OTBETA OT CEHCOPA);}

// Считываем данные и выводим следующие параметры: температуру в °С и давление в Па, давление в мм. рт. ст., изменение высоты, относительно значения, указанного в функции begin(по умолчанию 0 метров).

if(sensor.read(2))

{Serial.println((String)CEHCOP BMP + sensor.type + : \t P =  + sensor. pressure + “\tPa, \t\t T =  + sensor.temperature +  *C, \t\t B = +sensor. altitude+ M.);}

else

{Serial.println(HET OTBETA OT CEHCOPA);} delay(3000);

}

Рис. 2.13. Окно монитора порта с показаниями модуля «Датчик атмосферного давления»

По сути, работа с любыми I2C модулями, подключаемыми к Arduino-совместимым платам, сводится к установке соответствующей библиотеки и ее простейшего применения. Таким образом, подключив аналогично модуль «Датчика цвета» и модуль «Инерциальный датчик и магнетометр», можно организовать их опрос и использовать полученные данные в своих проектах.

Прочие модули

К прочим модулям, в данном случае, относятся те модули, которые не имеют стандартного способа взаимодействия (например, как в случае использования интерфейса I2C или при подключении стандартных цифровых или аналоговых датчиков). В связи с чем, при работе с каждым из них необходимо в каждом конкретном случае использовать уникальный подход – используя, например, готовую библиотеку или комбинацию способов управления. Рассмотрим процессы работы с модулями производства ООО «Прикладная робототехника», требующими нестандартные подходы к управлению.

Модуль «Датчик температуры и влажности воздуха»

Модуль «Датчик температуры и влажности воздуха» построен на базе сенсора DHT11, способного определять температуру и влажность окружающей среды в области около нормальных климатических условий (при температуре от 0 до 50 градусов и влажности от 20 до 90%). Подключение модуля к контроллеру КПМИС выполняется в соответствии с распиновкой разъема. Таким образом, линию модуля 5В подключим к линии 5В контроллера, линию GND – к GND контроллера, а линию управления SIG – к цифровой линии. В результате, внешний вид подключенного модуля будет выглядеть, как на Рис. 2.14 и Рис. 2.15.

Рис. 2.14. Подключение модуля «Датчик температуры и влажности воздуха» к контроллеру КПМИС

Поскольку данный модуль имеет уникальный протокол обмена данными, подобный 1-Wire, для работы с ним рекомендуется использовать подходящую библиотеку. Таких библиотек существует достаточно много, но в данном примере воспользуемся библиотекой «iarduino_DHT», скачать которую можно по следующей ссылке: https://iarduino.ru/file/225. html. После установки библиотеки стандартными способами можно открыть базовый пример и модифицировать его под актуальные требования. В результате, получится следующий код:

// подключаем библиотеку для работы с датчиком DHT 
#include <iarduino_DHT.h>

// объявляем переменную для работы с датчиком DHT, указывая номер цифрового вывода, к которому подключён модуль

iarduino_DHT sensor(5);
void setup(){

// открываем последовательный порт на скорости 9600 бод 
Serial.begin(115000);

// выполняем задержку для перехода датчика в активное состояние 
delay(1000);

}

void loop(){

// читаем показания датчика 
switch(sensor.read()){

case DHT_OK: 
Serial.println((String) CEHCOP B KOMHATE:  + sensor.hum + %  + sensor.tem + *C);

break;

case DHT_ERROR_CHECKSUM: 
Serial.println( CEHCOP B KOMHATE: HE PABEHCTBO KC);

break;

case DHT_ERROR_DATA: 
Serial.println( CEHCOP B KOMHATE: OTBET HE COOTBETCTB. CEHCOPAM DHT’”);

break;

case DHT_ERROR_NO_REPLY: 
Serial.println( CEHCOP B KOMHATE: HET OTBETA);

break;

default:

Serial.println( CEHCOP B KOMHATE: ERROR); break;

}

delay(2000);

}

Рис. 2.15. Подключение модуля «Датчик температуры и влажности воздуха» к контроллеру КПМИС

В результате, загрузив данный код в контроллер стандартным способом и открыв монитор порта, можно увидеть следующие данные (см. Рис. 2.16). Причем, если оказать влияние на модуль (прикоснуться к нему пальцем или подуть на него), показания будут изменяться, поскольку изменятся влажность и температура.

Рис. 2.16. Окно монитора порта с показаниями температуры и влажности

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

Модуль «Драйвер двигателя постоянного тока»

Модуль «Драйвер двигателя постоянного тока» построен на микросхеме, которая способна управлять скоростью и направлением вращения двигателя постоянного тока за счет двух входных параметров: сигнала, задающего направление вращения (постоянный цифровой сигнал низкого или высокого уровня), и PWM сигнала, задающего скорость вращения двигателя. В качестве примера рассмотрим одноканальный модуль «Драйвер двигателя постоянного тока», однако, данный подход аналогичен и для модуля «Драйвер двигателя постоянного тока (2 канала)». Подключение модуля к контроллеру КПМИС выполняется в соответствии с распиновкой. Таким образом, линию модуля VCC подключим к линии 5В контроллера, линию GND – к GND контроллера, линию управления DIR и линию управления PWM – к цифровой линии. В результате, внешний вид подключенного модуля будет выглядеть как на Рис. 2.17 и Рис. 2.18.

Рис. 2.17. Подключение модуля «Драйвер двигателя постоянного тока» к контроллеру КПМИС

Рис. 2.18. Подключение модуля «Драйвер двигателя постоянного тока» к контроллеру КПМИС

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

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

const uint8_t DirM1 = 8;

// указываем линию, к которой подключена линия управления скоростью

const uint8_t SpeedM1 = 9;

// объявляем переменную скорости uint8_t Speed = 0;

void setup(){

// инициализируем линии на выход. Устанавливаем их в значение «0» 
pinMode(DirM1, OUTPUT);
digitalWrite(DirM1, LOW); 
pinMode(SpeedM1, OUTPUT); 
digitalWrite(DirM1, LOW);

}

void loop(){

// задаем направление вращения 
digitalWrite(DirM1, LOW );

// увеличиваем скорость 
while(Speed<255){ 
analogWrite(SpeedM1, Speed++); 
delay(5);

}

// уменьшаем скорость 
while(Speed>0){



analogWrite(SpeedM1, Speed--); 
delay(5);

}

// меняем направление 
digitalWrite(DirM1, HIGH );

// увеличиваем скорость 
while(Speed<255){ 
analogWrite(SpeedM1, Speed++); 
delay(5);

}

// уменьшаем скорость 
while(Speed>0){ 
analogWrite(SpeedM1, Speed--); 
delay(5);

}

}

В результате загрузки данного кода в контроллер, двигатель постоянного тока, подключенный к модулю насчет ускоряться в одном направлении, затем произведет снижение скорости до 0, после чего изменит направление и повторит все снова. В случае использования двухканального модуля драйверов моторов в данный код необходимо аналогичным показанному способом добавить переменные для управления мотором М2 и отправить им соответствующие команды.

Плата расширения для подключения сенсорных модулей

В качестве модуля, облегчающего подключение периферийных функциональных модулей к Arduino-совместимым контроллерам, существует плата расширения для подключения сенсорных модулей (AR-SENS-RJ14), позволяющая подключать модуль с помощью 6ти-контактного кабеля. Внешний вид платы расширения представлен на Рис. 2.19.

Рис. 2.19. Внешний вид платы расширения AR-SENS-RJ14

На плате расширения для подключения сенсорных модулей расположены 12 комбинированных портов ввода-вывода, содержащих в своем составе по 6 линий, в которые входят как линии данных, так и линии, организующие питание модулей. Схема расположения портов и их распиновка приведены на Рис. 2.20.

Таким образом, исходя из распиновки портов разъема, при подключении к выбранному порту модуля управлять им надо линиями, относящимися к конкретному порту (линии подписаны в нотации Arduino Leonardo). К большинству портов можно подключать любые цифровые и аналоговые модули в любом порядке. Однако, из-за специфики некоторых модулей, имеются отдельные разъемы для подключения периферийных модулей, работающих по интерфейсу I2C, а также модуля

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

Рис. 2.20. Распиновка платы расширения AR-SENS-RJ14

Рис. 2.21. Модуль «Датчик шума», подключенный к плате расширения AR-SENS-RJ14

Для опроса модуля «Датчик шума» достаточно реализовать следующий код:

void setup() {

// инициализируем соединение по последовательному порту 
Serial.begin(115200);

}

void loop() {

// читаем данные с указанного аналогового порта 
int sensorValue = analogRead(A3);

// выводим данные в монитор порта 
Serial.println(sensorValue);

// задаем минимальную паузу для стабильности 
delay(1);

}

В данном примере происходит опрос аналогового порта А3, т.к. он физически выведен в порт №8 платы расширения. В результате, загрузив код стандартным способом, в окне монитора порта можно увидеть следующую картину (см. Рис. 2.22):

Рис. 2.22. Вывод данных с модуля «Датчик шума»

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

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

Модули, как Dynamixel-совместимые устройства

Для упрощения процесса подключения к управляющему контроллеру, а также для обеспечения возможности подключения большого количества модулей к одному управляющему контроллеру, на каждом периферийном функциональном модуле, производства ООО «Прикладная робототехника», имеется микроконтроллер, реализующий 3-пиновый интерфейс с протоколом Dynamixel. Для коммутации на каждом модуле имеется два 3-пиновых разъема Molex, позволяющих подключать модули последовательно друг за другом.

Для обмена данными с каким-либо модулем в сети периферийных модулей необходимо знать, как минимум, следующие данные о модуле:

  • Его уникальный номер – ID. По умолчанию, каждый модуль имеет свой уникальный ID, однако, если необходимо использовать несколько одинаковых модулей в цепи, то необходимо изменить их ID так, чтобы их значения не повторялись. Также надо следить, чтобы не пересекались значения ID периферийных модулей и сервоприводов DYNAMIXEL, если они присутствуют в одной сети. Другими словами, нужно следить за тем, чтобы к управляющему контроллеру не было подключено одновременно несколько устройств с одинаковыми значениями ID.
  • Скорость обмена данными – BAUD_RATE. По умолчанию, все устройства настроены на скорость в 57600 бод. При необходимости можно изменить данную скорость, например, для использования в цепи с сервоприводами, работающими на более низкой скорости, или при использовании длинных соединительных кабелей (чем длиннее используется кабель, тем ниже скорость рекомендуется использовать).
  • Регистры памяти – значения регистров памяти модуля, с которыми нужно работать. В зависимости от типа модуля и его назначения, одни и те же номера регистров могут быть использованы либо только для чтения, либо только для записи. Либо для чтения и записи одновременно. Информация по доступным для взаимодействия регистрам, а также их назначения, приведены ниже в таблице 2.2. Также в таблице 2.2 показаны тип данных, который применяется для параметров, допустимый диапазон значений (если регламентировано) и значения, записанные в регистрах по умолчанию.

Таким образом, для взаимодействия с периферийным функциональным модулем, как с Dynamixel-совместимым устройством, необходим контроллер, поддерживающий подключение по протоколу Dynamixel, и программный пакет (библиотека) для используемой среды разработки, реализующий обмен данными. Далее будут рассмотрены способы подключения модулей к популярным рекомендуемым контроллерам.

Таблица 2.2. Описание регистров периферийных модулей

Наименование модуля Наименова- ние регистра Адрес

(DEC)
Тип данных Допустимый диапазон Доступ Базовое значение Описание
Общее MODEL_

NUMBER
0 R/W Содержит номер модели
FIRMWARE_ VERSION 2 R/W Содержит версию встроенного ПО
ID 3 R/W Равно MODEL_ NUMBER Адрес устройства Dynamixel (ID)
BAUD_RATE 4 R/W 34 (57600

бит /с)
Содержит значение скорости обмена данными: baudrate = 2000000/(BAUD_ RATE + 1)
1 Модуль «Датчик наклона»

(ID 0x02)
BALL_1_DATA 26 uint8_t 0..1 R Возвращает состояние наклона по оси Х
BALL_2_DATA 27 uint8_t 0..1 R Возвращает состояние наклона по оси Y
2 Модуль «Такто- вая кнопка» (ID 0x03) BUT_DATA 27 uint8_t 0..1 R Возвращает состояние кнопки
3 Модуль «Датчик цвета» (ID 0x04) TCS3472_ CLEAR 24 uint16_t 0..65535 R 0 Возвращает значение яркости с фотодио- да без фильтров
TCS3472_RED 26 uint16_t 0..65535 R 0 Возвращает значение яркости с фотодио-

да с красным фильтром
TCS3472_ GREEN 28 uint16_t 0..65535 R 0 Возвращает значение яркости с фотодио- да с зеленым фильтром
TCS3472_BLUE 30 uint16_t 0..65535 R 0 Возвращает значение яркости с фотодио-

да с синим фильтром
TCS3472_LUX 32 uint16_t R Возвращает значение освещенности в люксах
TCS3472_

CTEMP
34 uint16_t 0..65535 R Возвращает значение цветовой темпера-

туры в Кельвинах
TCS3472_HUE 36 uint16_t 0..360 R Возвращает цветовые координаты по

шкале HSV
TCS3472_GAIN 38 uint8_t 0..3 R Программное усиление (как у фотоап- парата)
TCS3472_ COLOR 40 uint8_t R Возвращает одно из десяти значений цветовых оттенков (Черный, белый, красный, оранжевый, желтый, зеленый, голубой, синий, фиолетовый, розовый)
TCS3472_ LIGHT 42 uint8_t 0..255 W 0 Задает яркость светодиода подсветки
TCS3472_

BLACK_LVL
46 uint16_t 0..65535 W 850 Задает порог освещенности, до которо-

го цвет считается черным
TCS3472_ WHITE_LVL 48 uint8_t 0..65535 W 7 Задает минимальную разницу между нормированными значениями красного, зеленого и синего (дающих в сумме 255), более которой считается, что определен

оттенок цвета, а не белый цвет
4 Модуль «Драй- вер двигателя постоянного тока» (ID 0x05) MAX_POWER 24 uint16_t 0..1023 W 1023 Задает максимальную мощность двигателя при работе автоматической системы управления
ENCODER_ MODE 27 uint8_t 1..3 W 0 Задает режим работы энкодера:

0  - выключен

1  - AB - чтение 4х фронтов

2-  A rising and falling - чтение только канала A

3-  A rising only - чтение 1 фронта канала

А
POWER 28 uint16_t -1023..1023 W 0 Задает мощность двигателя при прямом управлении с учетом направления
ENCODER 32 uint16_t -32768..32767 R Возвращает количество тиков энкодера
PRESENT_ SPEED 34 uint16_t -32768..32767 R Возвращает значение текущей скорости в виде количество тиков энкодера / 100 мс
GOAL_SPEED 40 uint16_t -1000..1000 W 0 Задает значение требуемой скорости в виде количество тиков энкодера / 100 мс
CONTROL_ PERIOD 45 uint8_t 1..100 W 50 Задает длительность цикла управления (рекомендуется не менее 5 мс)
PID_P 47 uint8_t 0..255 W 16 Задает значение пропорциональной составляющей ПИД-регулятора
PID_I 48 uint8_t 0..255 W 32 Задает значение интегральной состав-

ляющей ПИД-регулятора
PID_D 49 uint8_t 0..255 W 0 Задает значение дифференциальной составляющей ПИД-регулятора
5 Модуль «Драй- вер двигателя постоянного тока (2 канала)»

(ID 0x06)
MAX_POWER 24 uint16_t 0..1023 W 1023 Задает максимальную мощность двигателя при работе автоматической системы управления
ENCODER_ MODE 27 uint8_t 1..3 W 0 Задает режим работы энкодера:

0  - выключен

1  - AB - чтение 4х фронтов

2-  A rising and falling - чтение только канала A

3-  A rising only - чтение 1 фронта канала

А
M1_POWER 28 uint16_t -1023..1023 W 0 Задает мощность двигателя М1 при пря- мом управлении с учетом направления
M2_POWER 30 uint16_t -1023..1023 W 0 Задает мощность двигателя М2 при пря-

мом управлении с учетом направления
M1_ENCODER 32 uint16_t -32768..32767 R Возвращает количество тиков энкодера двигателя М1
M1_PRESENT_ SPEED 34 uint16_t -32768..32767 R Возвращает значение текущей скорости двигателя М1 в виде количество тиков энкодера / 100 мс
M2_ENCODER 36 uint16_t -32768..32767 R Возвращает количество тиков энкодера двигателя М2
M2_PRESENT_ SPEED 38 uint16_t -32768..32767 R Возвращает значение текущей скорости двигателя М2 в виде количество тиков энкодера / 100 мс
M1_GOAL_ SPEED 40 uint16_t -1000..1000 W 0 Задает значение требуемой скорости двигателя М1 в виде количество тиков энкодера / 100 мс
M2_GOAL_ SPEED 42 uint16_t -1000..1000 W 0 Задает значение требуемой скорости двигателя M2 в виде количество тиков энкодера / 100 мс
CONTROL_ PERIOD 45 uint8_t 1..100 W 50 Задает длительность цикла управления (рекомендуется не менее 5 мс)
PID_P 47 uint8_t 0..255 W 16 Задает значение пропорциональной составляющей ПИД-регулятора обоих двигателей
PID_I 48 uint8_t 0..255 W 32 Задает значение интегральной составля- ющей ПИД-регулятора обоих двигате- лей
PID_D 49 uint8_t 0..255 W 0 Задает значение дифференциальной составляющей ПИД-регулятора обоих двигателей
6 Модуль «ИК энкодер» (ID 0x07) COUNT_DATA 26 uint32_t R Возвращает количество тиков
RESET_ ENCODER 30 uint8_t 0..1 W Сбрасывает значение энкодера
7 Модуль «Свето- диод» (ID 0x09) LED_DATA 26 uint8_t 0..255 W 0 Задает интенсивность свечения свето- диода
8 Модуль «Потен- циометр» (ID 0x13) POT_DATA 26 uint16_t 0..1023 R Возвращает значение потенциометра
9 Модуль «Трех- цветный свето- диод» (ID 0x15) GREEN_LED_ DATA 26 uint8_t 0..255 W 0 Задает интенсивность свечения зеленой составляющей светодиода
RED_LED_DATA 27 uint8_t 0..255 W 0 Задает интенсивность свечения красной

составляющей светодиода
BLUE_LED_ DATA 28 uint8_t 0..255 W 0 Задает интенсивность свечения синей составляющей светодиода
10 Модуль «Сило- вой ключ» (ID 0x11) MOS_FREQ 26 uint16_t 200..5000 W 220 Задает значение частоты
MOS_POR 28 uint8_t 0..255 W 0 Задает значение скважности
11 Модуль

«Звуковой пьезоизлуча- тель» (ID 0x18)
MOS_FREQ 26 uint16_t 200..5000 W 220 Задает значение частоты
MOS_POR 28 uint8_t 0..255 W 0 Задает значение скважности
12 Модуль

«Датчик шума» (ID 0x12)
SOUND_DATA 26 uint8_t 0..255 R Возвращает уровень звука
SOUND_ DETECTED_ COUNT 27 uint8_t 0..255 R 0 Возвращает количество хлопков
SOUND_ DETECTED_ TIME 28 uint16_t R 0 Возвращает время последнего хлопка
SOUND_ THRESHOLD_ VALUE 30 uint8_t 0..255 W 200 Задает пороговое значение для детек- тирования хлопка
13 Модуль

«Датчик линии» (ID 0x0A)
LINE_DATA 27 uint8_t 0..1 R Возвращает состояние датчика линии
14 Модуль «Конце- вой выключа- тель» (ID 0x17) USW_DATA 27 uint8_t 0..1 R Возвращает состояние микропереклю- чателя
15 Модуль «ИК при- емник» (ID 0x08) (совместим с пультом RC100) REMCON_IR_ DATA 26 uint16_t R Возвращает код нажатой кнопки
REMCON_IR_ ARRIVED 28 uint8_t R Возвращает сигнал о наличии данных
16 Модуль «Датчик атмосферного давления» (ID 0x14) BMP_PRESS_32 24 uint32_t 30000..

110000
R Возвращает значение давление в Па (1000 = 1 кПа)
BMP_ALT_32 28 int32_t -5000..90000 R Возвращает значение высоты в дм. (567

= 56.7 м над уровнем моря)
BMP_PRESS_16 32 uint16_t 0..65535 R Возвращает давление в даПа (100 = 1кПа)
BMP_ALT_16 34 int16_t -5000..32767 R Возвращает значение высоты в дм. (567

= 56.7 м над уровнем моря)
BMP_TEMP_16 36 int16_t -4000..8500 R Возвращает значение температуры в сотых градуса (2500 = 25 0С)
BMP_CFG_F4 38 uint8_t 0..255 W Регистр F4 конфигурации датчика
BMP_CFG_F5 40 uint8_t 0..255 W Регистр F5 конфигурации датчика
BMP_UPDATE 42 uint8_t 0..1 W При записи в этот регистр 1 к датчику применяются настройки регистров BMP_CFG_F4 и BMP_CFG_F5
17 Модуль «Датчик температуры и влажности

воздуха»
DTH11_RH_INT 24 uint8_t 0..100 R Возвращает целую часть от значения влажности
DTH11_RH_

DEC
26 uint8_t 0..9 R Возвращает десятичную часть значения

влажности
DTH11_TEMP_ INT 28 int8_t -40..80 R Возвращает целую часть от значения температуры
DTH11_TEMP_

DEC
30 uint8_t 0..9 R Возвращает десятичную часть от значе-

ния температуры
DTH11_ TEMP16 34 int16_t -400..800 R Возвращает значение температуры
18 Модуль «Датчик силы» (ID 0х20) FORCE_DATA 26 uint16_t 0..1023 R Возвращает значение силы нажатия (площадь пятна)
19 Модуль «Датчик освещенности»

(ID 0х19)
LIGHT_DATA 26 uint16_t 0..1023 R Возвращает значение освещенности
20 Модуль «Уль- тразвуковой дальномер» (ID 0x2A) MEAS_ CONTROL 25 uint8_t 0…1 W Включение замера данных
RESULT_0 26 uint16_t XZ R Тут данные № 1
RESULT_1 27 uint8_t XZ R Тут данные № 2
MEASUREMENT_ TIMEOUT 28 uint16_t XZ R Ошибка измерения
21 Модуль

«Джойстик» (ID 0х25)
POTX_0_DATA 26 uint8_t 0….1024 R Возвращает значение по горизонтали (верх либо низ)
POTX_1_DATA 27 uint8_t 0….1024 R Возвращает значение по горизонтали

(верх либо низ)
POTY_0_DATA 28 uint8_t 0….1024 R Возвращает значение по вертикали (верх либо низ)
POTY_1_DATA 29 uint8_t 0….1024 R Возвращает значение по вертикали

(верх либо низ)
BUT_DATA 31 uint8_t 0…. 1 Возвращает значение

Подключение к Arduino-контроллерам

На классических Arduino-контроллерах (таких как Mega2560, UNO, Leonardo) не встречается интерфейс Dynamixel. Поэтому для подключения к ним Dynamixel-совместимых устройств необходимо использовать платы расширения, реализующие требуемый интерфейс. Пример платы расширения показан на Рис. 2.23.

Рис. 2.23. Плата расширения с интерфейсом Dynamixel, разработанная ООО “Прикладная робототехника”

Данные платы расширения совместимы с популярными Arduino и Arduino-подобными контроллерами и позволяют обеспечивать необходимое питание подключаемых устройств и реализовывать как 3х-пиновый, так и 4х-пиновый интерфейсы Dynamixel.

Для реализации обмена данными через такие платы расширения существуют несколько программных пакетов (библиотек) для среды разработки Arduino IDE, разработанных как сообществом, так и производителями решений. Например, библиотека «DynamixelShield Library for Arduino», разработанная компанией ROBOTIS (https://github.com/ ROBOTIS-GIT/DynamixelShield).

Помимо плат расширения, реализующих интерфейс Dynamixel, существуют Arduino-подобные платы сторонних производителей, содержащих требуемый интерфейс. Такие платы, как правило, делаются на основе микроконтроллеров Atmega16u2 и Atmega2560. ООО «Прикладная робототехника» также производит собственные Arduino-подобные контроллеры, содержащие интерфейс Dynamixel. Самыми популярными среди таких контроллеров являются: «Программируемый контроллер моделей инженерных систем» («Контроллер КПМИС») (см. Рис. 2.24) и

«Универсальный вычислительный контроллер DXL-IoT» (см. Рис. 2.25).

Рис. 2.24. Контроллер КПМИС

Рис. 2.25. Универсальный вычислительный

контроллер DXL-IoT

По своей сути оба этих устройства являются полноценными контроллерами. Отличием является лишь то, что «Контроллер КПМИС» имеет на своей плате большой набор всевозможных элементов управления, индикаторов и интерфейсов (как проводных, так и беспроводных), а «Универсальный вычислительный контроллер DXL-IoT» представляет собой компактный модуль (с габаритами 40х40 мм), рассчитанный на встраиваемые системы и применение в среде «Интернета вещей» (Internet of Things – IoT). Оба этих контроллера построены на базе микроконтроллера Atmega2560 и могут быть запрограммированы с помощью среды Arduino IDE как плата Arduino Mega2560. Подробнее про «Контроллер КПМИС» можно прочитать в учебном пособии «Программирование моделей инженерных систем», а про «Универсальный вычислительный контроллер DXL-IoT» в одноименном учебном пособии.

В составе обоих контроллеров имеется по два 3х-пиновых порта для подключения Dynamixel-совместимых устройств. В случае «Контроллера КПМИС», питание на эти устройства подается напрямую с платы контроллера, если сам контроллер при этом подключен к источнику питания 12В. В случае «Универсального вычислительного контроллера DXL-IoT» питание 12В необходимо подать извне через 3х-пиновые разъемы, например, используя адаптер питания SMPS2Dynamixel.

Библиотека DxlMaster

Устройства Dynamixel: сервоприводы и датчики, поддерживающие протокол Dynamixel 1.0, подключаются к интерфейсу на основе последовательного порта UART в режиме полудуплекса. Для управления Dynamixel-cовместимыми устройствами c Arduino-подобных контроллеров производства ООО «Прикладная робототехника» необходимо использовать библиотеку «DxlMaster», которую вы можете скачать с сайта компании ООО «Прикладная робототехника» (раздел «Программное обеспечение»). Данная библиотека поставляется в виде zip-библиотеки Arduino и устанавливается штатными средствами Arduino IDE (Меню

«Скетч» -> «Подключить библиотеку» -> «Добавить .ZIP библиотеку»).

Рис. 2.26. Примеры для библиотеки DxlMaster

Библиотека содержит следующие примеры (меню «Файл» -> «Примеры») (см. Рис. 2.26):

  • blink_led – включение и выключение светодиодов сервоприводов DYNAMIXEL.
  • change_baudrate – изменение скорости передачи данных на шине Dynamixel.
  • console – терминал, позволяющий из командной строки найти и настроить Dynamixel-совместимые устройства в сети.
  • joint_mode – управление сервоприводами по положению (режим шарнирного сочленения).
  • wheel_mode – управление сервоприводами по скорости (режим колеса).
  • wheel_mode_low_level – управление сервоприводами на низком уровне (изменением значений регистров).

Инициализация библиотеки

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

#include «DxlMaster.h»

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

DxlMaster.begin(int baudrate);

где baudrate – скорость обмена данными с устройствами на шине Dynamixel (см. документацию к конкретной модели привода). Чаще всего используются скорости 57 600 бод и 1 000 000 бод. Скорость обмена данными с Dynamixel – совместимым устройством может быть изменена через программу ROBOTIS Dynamixel Wizard, либо используя пример change_baudrate.

Подключение произвольных устройств, класс DynamixelDevice

Обмен данными с Dynamixel – совместимыми устройствами происходит путем записи и чтения регистров в памяти такого устройства. Для этого предназначен класс DynamixelDevice библиотеки «DxlMaster».

Общие методы класса DxlMaster:

  • DxlMaster(uint8_t id) – конструктор, id – уникальный номер устройства Dynamixel в сети (см. документацию на устройство). Может быть изменен в программе ROBOTIS Dynamixel Wizard.
  • DynamixelStatus init() – поиск и инициализация устройства. Если найдено устройство с адресом id и скоростью обмена, соответствующей текущим настройкам шины, возвращает 0, иначе – код ошибки.
  • DynamixelStatus changeId(uint8_t id) - изменение id устройства (для этого устройство все равно должно быть инициализировано с исходным id).
  • uint16_t model() – возвращает номер модели устройства.
  • uint8_t firmware() – возвращает версию прошивки устройств.
  • void communicationSpeed(uint32_t aSpeed) – изменение скорости обмена данными с устройством.

Обмен данными:

Все методы для обмена данными возвращают статус выполнения команды DynamixelStatus, принимающий значение «0» в случае успеха или выдающий номер стандартной ошибки шины Dynamixel, в случае сбоя обмена данными.

Методы чтения данных выполнены в виде шаблонов для чтения регистров разной длины (чаще всего в Dynamixel – совместимых устройствах применяются регистры типов uint8_t, uint16_t), например:

template DynamixelStatus read(uint8_t aAddress, T& aData) – шаблон метода для чтения регистра произвольного типа T по адресу aAdress.

Пример использования:

uint16_t pos; device.read(DYN_ADDRESS_CURRENT_POSITION, pos);

После успешного выполнения команды в переменной pos окажется значение 16-ти разрядного регистра DYN_ADDRESS_CURRENT_POSITION, который занимает в памяти сервопривода 2 байта.

Методы для обмена данными:

  • DynamixelStatus read(uint8_t aAddress, T& aData) – чтение регистра типа T по адресу aAddress с записью результата в переменную aData.
  • DynamixelStatus read(uint8_t aAddress, uint8_t size, uint8_t *ptr) – чтение массива из регистров, в количестве size по адресу aAddress с записью результата в массив по адресу ptr.
  • DynamixelStatus write(uint8_t aAddress, const T& aData) – запись в регистр типа T по адресу aAddress значения aData.
  • DynamixelStatus write(uint8_t aAddress, uint8_t size, const uint8_t *ptr) -запись в массив регистров, длиной size, по адресу aAddress значений из локального массива с указателем ptr.
  • DynamixelStatus regWrite(uint8_t aAddress, const T& aData)** – команда отложенной записи в регистр типа T по адресу aAddress значения aData. Значение передается на устройство, но применяется к регистру только после команды action()**.
  • DynamixelStatus regWrite(uint8_t aAddress, uint8_t size, const uint8_t*ptr) - команда отложенной записи в массив регистров, длиной size, по адресу aAddress значений из локального массива по указателю ptr.
  • DynamixelStatus action() – команда, получив которую все устройства в сети применяют значения регистров, полученные с командой отложенной записи. Функция применяется для организации синхронной работы сервоприводов: вначале всем сервоприводам рассылаются целевые значения (положение, скорость), а затем широковещательной командой «action» приводы запускаются.
  • DynamixelStatus ping() – команда для проверки наличия устройства в сети. В случае, если устройство найдено, возвращает значение «0», иначе – код ошибки.

Примечание. Для отправки широковещательных команд необходимо создать абстрактное устройство DynamixelDevice с широковещательным адресом.

Пример низкоуровнего управления сервоприводом DYNAMIXEL MX-28:

#include «DxlMaster.h» // Добавление библиотеки

DynamixelDevice device(1); // Создание объекта управления с адресом id = 1

void setup() {

DxlMaster.begin(1000000); // Инициализация шины со скоростью 1000000 бод

device.init(); // Поиск в сети и инициализация устройства 
device.write(DYN_ADDRESS_ENABLE_TORQUE, 1); // Включение момента

uint16_t zero_limit = 0;

device.write(DYN_ADDRESS_CW_LIMIT, zero_limit); // Очистка ограничения вращения по часовой стрелке

device.write(DYN_ADDRESS_CCW_LIMIT, zero_limit); // Очистка ограничения вращения против часовой стрелки

}

void loop() {

int16_t speed = 1000;

device.write(DYN_ADDRESS_GOAL_SPEED, speed); // Установка скорости

}

Подключение сервоприводов, класс DynamixelMotor

Для более удобного управления сервоприводами DYNAMIXEL, необходимо применять ориентированный на такое использование класс DynamixelMotor, наследующий класс DynamixelDevice вместе со всеми представленными в предыдущем разделе методами. Дополнительно к методам класса DynamixelDevice в классе DynamixelMotor реализованы следующие специальные методы.

  • void wheelMode() – настраивает регистры привода для работы в режиме колеса.
  • void jointMode(uint16_t aCWLimit=0, uint16_t aCCWLimit=0x3FF) – настраивает привод для управления по положению (режим шарнирного сочленения) с ограничениями углов поворота по и против часовой стрелки (aCWLimit и aCCWLimit, соответственно).
  • void enableTorque(bool aTorque=true) – включает момент, регистр целевого положения принимает значение текущего положения, и сервопривод удерживает текущее положение.
  • void speed(int16_t aSpeed) – задает скорость вращения привода в режиме колеса, либо максимальную скорость вращения в режиме сочленения.
  • void goalPosition(uint16_t aPosition) – задает целевое положение при управлении по положению.
  • void led(uint8_t aState) – управляет светодиодом сервопривода: aState = 0 – выключение, aState = 1 – включение.
  • uint16_t currentPosition() – опрашивает и возвращает показания о текущем угловом положении сервопривода.
  • DynamixelStatus getCurrentPosition(uint16_t &pos) – метод аналогичен предыдущему, но возвращает статус выполнения команды для построения более надежных систем управления.

Пример управления мотором:

#include «DxlMaster.h» // Добавление библиотеки

DynamixelMotor motor(1); // Создание объекта класса сервопривода с адресом 1

void setup() {

DxlMaster.begin(1000000); // Инициализация шины Dynamixel со скоростью 1000000 бод

motor.enableTorque(); // Включение момента привода 
motor.jointMode(204, 820); // Включение режима сочленения с угловыми ограничениями
motor.speed(100); // Задание максимальной скорости вращения привода
}
void loop() {
motor.goalPosition(123); // Задание положения привода
}
Более подробно возможности библиотеки представлены в примерах среды Arduino IDE (Меню «Файл» -> «Примеры» -> «DxlMaster») (см. Рис. 2.26).

Далее будут приведены ряд примеров взаимодействия с периферийными модулями, как с Dynamixel-совместимыми устройствами, используя управляющую плату «Контроллер КПМИС» и библиотеку «DxlMaster». Подключение модулей к контроллеру выполняется с помощью 3х-пинового кабеля к любому разъему на плате и на модуле. Пример подключения модуля «Потенциометр» показан на Рис. 2.27. Остальные модули подключаются аналогичным образом.

Опрос модуля «Потенциометр»

Модуль «Потенциометр» имеет значение ID «0х13», что в десятичной записи составляет 19. Данные хранятся в двух регистрах памяти: в 26 регистре малый байт, в 27 большой, поэтому суммарно показания датчика варьируются от 0 до 1023 (до 8 бит в малом и до 2 бит в большом). Чтение данных из регистров реализовано через метод DynamixelStatus read.

Рис. 2.27. Подключение модулей по интерфейсу Dynamixel на примере подключения модуля «Потенциометр»

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 19;

uint8_t a; 
uint8_t b;

DynamixelDevice pot(id); 

void setup() {

DxlMaster.begin(dynamixel_baudrate); 
pot.init(); 
Serial.begin(serial_baudrate);

}

void loop() {

pot.read(26, a); // малый регистр от 0 до 255 
pot.read(27, b); // большой регистр от 1*256 до 3*256 
Serial.print(Pot position: );

Serial.print((a + 256*b)/10.23); 
Serial.print(%\n); 
delay(1000);

}

Рис. 2.28. Окно монитора порта с показаниями модуля «Потенциометр»

Приведенная выше программа выводит в монитор последовательного порта информацию о положении потенциометра в диапазоне от 0% до 100% (см. Рис. 2.28).

Опрос модуля «Тактовая кнопка»

Значение ID модуля «Тактовая кнопка» 0х03, что в десятичной записи составляет 3. Статус нажатия хранится в 27 регистре и представляет собой один изменяющийся бит во всем регистре.

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 3;

uint8_t a; 
DynamixelDevice but(id);

void setup() { 
DxlMaster.begin(dynamixel_baudrate); 
but.init(); 
Serial.begin(serial_baudrate);

}

void loop() {

but.read(27, a); // значение «0» - кнопка не нажата, «1» - нажата 
if (a==0)

{

Serial.print(Button is not pressed\n);

}

else

{

Serial.print(Button pressed\n);

}

delay(1000);

}

Рис. 2.29. Окно монитора порта с показаниями модуля «Тактовая кнопка»

В данной программе регистр опрашивается с периодом в одну секунду и, в зависимости от статуса нажатия кнопки, выводит в монитор последовательного порта соответствующую информацию (см. Рис. 2.29).

Опрос модуля «Датчик линии»

Значение ID модуля «Датчик линии» - 0х0A, что составляет в десятичной записи 10. Данные детектирования линии хранятся в 27 регистре и представляют собой один изменяемый бит либо фотопара фиксирует отражение сигнала, либо нет.

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 10;

uint8_t a; DynamixelDevice line(id);

void setup() { 
DxlMaster.begin(dynamixel_baudrate); 
line.init(); 
Serial.begin(serial_baudrate);

}

}

Рис. 2.30. Окно монитора порта с показаниями модуля «Датчик линии»

Опрос модуля «Датчик силы»

Значение ID модуля «Датчик силы» - 0x20, что составляет в десятичной записи - 32. Данные о силе нажатия приходят в регистр 26 и занимает 2 байта.

#include «DxlMaster2.h»

//Подключаем библиотеку для работы с Dynamixel устройствами

const unsigned long dynamixel_baudrate = 57600;

//Выставляем скорость обмена данными с Dynamixel устройствами 
const unsigned long serial_baudrate = 57600;

//Выставляем скорость сериал порта 
const uint8_t id = 32; //ID Датчика uint16_t strength = 0;

DynamixelDevice power(id); //Объявляем Dynamixel устройство 
void setup() {

DxlMaster.begin(dynamixel_baudrate); //Начинаем работу библиотеки

power.init(); //Инициализируем устройство 
Serial.begin(serial_baudrate);

}


void loop() { power.read(26,strength);

//Считываем силу нажатия и записываем в переменную strength 
Serial.println(strength);

delay(500);

}

Опрос модуля «Датчик освещенности»

Значение ID модуля «Датчик освещенности» - 0x19, что составляет в десятичной записи - 25. Данные о освещенности приходят в регистр 26 и занимает 2 байта.

#include «DxlMaster2.h»

//Подключаем библиотеку для работы с Dynamixel устройствами

const unsigned long dynamixel_baudrate = 57600;

//Выставляем скорость обмена данными с Dynamixel устройствами 
const unsigned long serial_baudrate = 57600;

//Выставляем скорость сериал порта 
const uint8_t id = 25;//ID Датчика 
uint16_t brightness = 0;

DynamixelDevice light(id);

//Объявляем Dynamixel устройство

void setup() {

DxlMaster.begin(dynamixel_baudrate); //Начинаем работу библиотеки 
light.init(); //Инициализируем устройство 
Serial.begin(serial_baudrate);

}

void loop() {

light.read(26,brightness); //Считываем уровень освещенности 
Serial.println(brightness);

delay(500);

}

Опрос модуля «Ультразвуковой дальномер»

Значение ID модуля «Ультразвуковой дальномер» - 0x2A, что составляет в десятичной записи - 42. Для измерения необходимо записать 1 в регистр 25. Это запустит измерение датчика. Данные же приходят в регистры 26, 27 и занимает по 2 байта.

#include «DxlMaster2.h»


//Подключаем библиотеку для работы с Dynamixel устройствами 
const unsigned long dynamixel_baudrate = 57600;

//Выставляем скорость обмена данными с Dynamixel устройствами 
const unsigned long serial_baudrate = 57600;

//Выставляем скорость сериал порта 
const uint8_t id = 34;//ID Датчика

const uint8_t start_echo = 25; //Регистр в который начинает измерение 
const uint8_t result_0 = 26; //Регистр измерения

uint8_t sum = 0; uint8_t mas[2];

DynamixelDevice dist(id); //Объявляем Dynamixel устройство 
void setup() {

DxlMaster.begin(dynamixel_baudrate); //Начинаем работу библиотеки

dist.init(); //Инициализируем устройство 
Serial.begin(serial_baudrate);

delay(200);

}

void loop() { dist.write(start_echo, 1);

//Записываем в регистр измерения 1, чтобы датчик измерил расстояние

dist.read(result_0, mas);

//Считвыаем данные с регистра и записываем в переменную mas

sum = mas[1] != 0 ? sum = (mas[0] * 256) + mas[1] - 4 : sum = (mas[0] * 256)

+ mas[1];

sum = mas[0] * 256 + mas[0]; Serial.println(«Dist: « + String(sum) + « cm»); delay(1000);

}

Опрос модуля «Преобразователь интерфейсов»

Значение ID модуля «Преобразователь интерфейсов» - 0xA1, что составляет в десятичной записи - 161.Для выбора режима работы необходимо в регистр 28 записать режим работы датчика: DAС - 0x20, PWM - 0x21, I2C - 0x22, SPI - 0x23, UART(Master) - 0x24, UART(Slave) - 0x25.

#include «DxlMaster2.h»


//Подключаем библиотеку для работы с Dynamixel устройствами 
const unsigned long dynamixel_baudrate = 1000000;

//Выставляем скорость обмена данными с Dynamixel устройствами 
const unsigned long serial_baudrate = 57600;

//Выставляем скорость сериал порта 
const uint8_t id = 161; //ID Датчика 
const uint8_t FREQ_MSB = 34;

const uint8_t FREQ_LSB = 35; 
const uint8_t MODE_I2C = 34;

//Значение для выставления режима работы в I2C

const uint8_t SELECT_MODE = 28; //Регистр выбора режима работы 
const uint8_t I2C_ENABLE = 29; //Регистр включение режима работы 
const uint8_t ADDR_BUF = 26; //Буфер для записи

DynamixelDevice xface(id); //Объявляем Dynamixel устройство 
void setup() {

DxlMaster.begin(dynamixel_baudrate); //Начинаем работу библиотеки

xface.init(); //Инициализируем устройство 
Serial.begin(serial_baudrate); 
xface.write(FREQ_MSB, 96);

xface.write(FREQ_LSB, 10);

xface.write(SELECT_MODE, MODE_I2C); //Выставляем режим работы в I2C

}

void loop() {

xface.write(ADDR_BUF, «test»); //Записываем в буфер данные 
delay(200);

xface.write(I2C_ENABLE, 2); //Отправляем данные по шине 
delay(300);

}

Опрос модуля «Джойстик»

Значение ID модуля «Джойстик» - 0x27, что составляет в десятичной записи - 39. Данные о смещение по оси X приходят в регистры 26 и 27, о смещении по оси Y в регистры 28 и 29, а информация о нажатии кнопки приходит в регистр 31.

#include «DxlMaster.h»

//Подключаем библиотеку для работы с Dynamixel устройствами

//Регистры сдвига джойстика 
#define POTX_0_DATA 26

#define POTX_1_DATA 27


#define POTY_0_DATA 28

#define POTY_1_DATA 29

#define BUT_DATA 31

//Регистр нажатия джойстика

const unsigned long dynamixel_baudrate = 57600;

//Выставляем скорость обмена данными с Dynamixel устройствами 
const unsigned long serial_baudrate = 57600;

//Выставляем скорость сериал порта 
const uint8_t id = 39; //ID Датчика

DynamixelDevice joy(id); //Объявляем Dynamixel устройство 
void setup() {

DxlMaster.begin(dynamixel_baudrate); //Начинаем работу библиотеки 
joy.init(); //Инициализируем устройство

Serial.begin(serial_baudrate);

}

void loop() { uint8_t byte;

joy.read(BUT_DATA, byte); //Считвыаем нажатие 
Serial.print(«BUT:»);

Serial.println(byte); 
uint8_t byte0, byte1;

//Считываем смещение джойстика (центр 512) 
joy.read(POTX_0_DATA, byte0); 
joy.read(POTX_1_DATA, byte1);

Serial.print(«X:» + String((byte1 << 8) + byte0) + «\n»);

joy.read(POTY_0_DATA, byte0); joy.read(POTY_1_DATA, byte1);

Serial.print(«Y:» + String((byte1 << 8) + byte0) + «\n»);

delay(50);

}

Управление модулем «Светодиод»

Значение ID модуля «Светодиод» - 0х09, что составляет в десятичной записи - 9. Запись происходит в 26 регистр памяти, величина записываемого значения влияет на яркость светодиода. В программе реализовано 3 уровня яркости, которые сменяют друг друга с задержкой в 1 секунду. Управление реализовано с помощью метода DynamixelStatus write.

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 9;

uint8_t a; 
uint8_t b;

DynamixelDevice light(id);

void setup() { 
DxlMaster.begin(dynamixel_baudrate); 
light.init(); 
Serial.begin(serial_baudrate);

}

void loop() { 
light.write(26, 0); 
delay(1000); 
light.write(26, 50); 
delay(1000); 
light.write(26, 255); 
delay(1000);

}

Управление модулем «Звуковой пьезоизлучатель»

Значение ID модуля «Звуковой пьезоизлучатель» - 0х18, что составляет в десятичной записи - 24. Регистры памяти 26 и 27 содержат данные о воспроизводимой частоте. Данные из 28 регистра содержат информацию о скважности сигнала (пьезоизлучатель управляется по принципу ШИМ).

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 24;

uint8_t a; 
DynamixelDevice buz(id);

void setup() { 
DxlMaster.begin(dynamixel_baudrate); 
buz.init(); 
Serial.begin(serial_baudrate);

}

void loop() { 
buz.write(28, 127);

buz.write(26, (uint16_t) 512); 
delay(2000);

buz.write(26, (uint16_t) 256); 
delay(2000);

buz.write(26, (uint16_t) 1024); 
delay(2000);

}
Для работы модуля на высоких частотах рекомендуется изменить скорость передачи данных (Dynamixel_baudrate). При низкой скорости обмена данными модуль может вести себя некорректно.

Управление модулем «Силовой ключ»

Значение ID модуля «Силовой ключ» - 0х11, что составляет в десятичной записи - 17. Регистр памяти 28 содержит информацию о скважности сигнала (ток, подаваемый на присоединенную нагрузку, управляется по принципу ШИМ).

#include “DxlMaster.h”

const unsigned long dynamixel_baudrate = 57600; 
const unsigned long serial_baudrate = 57600; 
const uint8_t id = 17;

uint8_t a; 
DynamixelDevice mos(id);


void setup() { 
DxlMaster.begin(dynamixel_baudrate); 
mos.init(); 
Serial.begin(serial_baudrate);

}

void loop() { 
a = 0;

mos.write(28, a); // подача сигнала на открытие, при значении «0» - закрыт (ШИМ 0%)

delay(1000); // при значении «255» - открыт (ШИМ 100%) a = 127;

mos.write(28, a); 
delay(1000);

a = 255;

mos.write(28, a); 
delay(1000);

}

Таким образом, можно взаимодействовать с остальными модулями, подключенными по Dynamixel интерфейсу к Arduino-подобным контроллерам, производства ООО «Прикладная робототехника».

Подключение к контроллерам STEM Board и OpenCR-AR

Помимо Arduino-подобных контроллеров у ООО «Прикладная робототехника» существуют программируемые контроллеры, базирующиеся на микроконтроллерах STM и поддерживающие программирование через Arduino IDE, при условии установки дополнительного пакета поддержки плат. Примером таких контроллеров являются STEM Board и OpenCR-AR. Универсальный контроллер STEM Board представляет собой периферийную плату расширения, в которую физически устанавливаются программируемый контроллер OpenCM, производимый компанией ROBOTIS, и одноплатный микрокомпьютер NanoPi-AR. В свою очередь, контроллер OpenCR является более «продвинутой» версией контроллера STEM Board, за счет встроенного в плату значительно более мощного микроконтроллера, а также большого количества размещенной на плате периферии. Контроллер OpenCR-AR так же поддерживает интеграцию встраиваемого микрокомпьютера NanoPi-AR.

Для возможности программировать данные контроллеры с помощью Arduino IDE необходимо стандартными средствами среды разработки установить дополнительные пакеты поддержки данных плат. Для этого необходимо добавить в «Файл» -> «Настройки» -> «Дополнительные ссылки для менеджера плат» следующие ссылки:

https://raw.githubusercontent.com/ROBOTIS-GIT/OpenCM9.04/master/arduino/opencm_release/package_opencm9.04_index.json

https://raw.githubusercontent.com/ROBOTIS-GIT/OpenCR/master/arduino/opencr_release/package_opencr_index.json

После добавления вышеуказанных ссылок, в меню «Инструменты» -> «Плата» -> «Менеджер плат» необходимо выполнить поиск и установить предлагаемые пакеты для плат OpenCM и OpenCR (см. Рис. 2.31).

Рис. 2.31. Установка пакетов поддержки плат OpenCR и OpenCM

После установки данных пакетов в списке доступных для программирования плат появятся платы OpenCM и OpenCR (см. Рис. 2.31 2.32) Оба этих контроллера имеют аппаратную поддержку Dynamixel интерфейса (аналогично рассмотренным ранее

Arduino-подобным платам), в связи с чем для подключения Dynamixel-совместимых устройств требуется только подать питание 12В на плату через штатный разъем.

Рис. 2.32. Доступные к выбору платы OpenCR и OpenCM

https://emanual.robotis.com/docs/en/software/dynamixel/dynamixel__sdk/overview/

Управление модулем «Светодиод»

Рассмотрим процесс управления модулем «Светодиод». Значение ID модуля «Светодиод» 0х09, что составляет в десятичной записи 9. Запись происходит в 26 регистр памяти, величина записываемого значения влияет на яркость светодиода. В программе реализовано мигание светодиода с интервалом в 2 секунды. Подключение модуля необходимо выполнять к центральному 3х пиновому порту.

#include <DynamixelSDK.h>

// указываем версию протокола (для всех модулей - 1.0) 
#define PROTOCOL_VERSION 1.0

// базовые настройки

#define DXL_ID 9

#define BAUDRATE 57600

#define DEVICENAME “3”

// создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

// создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

void setup() {

// инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// инициализируем обработчик пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

// открываем порт 
portHandler->openPort();

// устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

// включаем светодиод

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 200); delay(2000);

// выключаем светодиод

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 0); delay(2000);

}

Опрос модуля «Концевой выключатель»

Рассмотрим процесс опроса модуля «Концевой выключатель». Значение ID модуля «Концевой выключатель» - 0х17, что составляет в десятичной записи - 23. Чтение происходит из 27 регистра памяти. В программе реализован вывод состояния микропереключателя в монитор порта. Подключение модуля необходимо выполнять к центральному 3х пиновому порту.

#include <DynamixelSDK.h>

// указываем версию протокола (для всех модулей - 1.0) 
#define PROTOCOL_VERSION 1.0

// базовые настройки 
#define DXL_ID 23

#define BAUDRATE 57600

#define DEVICENAME “3”

// создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

// создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

// создаем и инициализируем переменную для хранения состояния 
uint8_t data = 0;

void setup() {

// инициализируем вывод в последовательный порт 
Serial.begin(115200);

// ждем, пока не открылся монитор порта 
while(!Serial);

//инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// инициализируем обработчик пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

// открываем порт 
portHandler->openPort();

// устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

// выполняем чтение регистра 27

packetHandler->read1ByteTxRx(portHandler, DXL_ID, 27, (uint8_t*)&data); Serial.println(data);

delay(50);

}

Опрос модуля «Потенциометр»

Рассмотрим процесс опроса модуля «Потенциометр». Значение ID модуля «Потенциометр» - 0х13, что составляет в десятичной записи - 19. Чтение происходит из 26 регистра памяти. В программе реализован вывод положения потенциометра в монитор порта. Подключение модуля необходимо выполнять к центральному 3х пиновому порту. Отличием от предыдущего примера является то, что результатом чтения является двухбайтовое число.

#include <DynamixelSDK.h>

// указываем версию протокола (для всех модулей - 1.0) 
#define PROTOCOL_VERSION 1.0

// базовые настройки 
#define DXL_ID 19

#define BAUDRATE 57600

#define DEVICENAME “3”

// создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

// создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

// создаем и инициализируем переменную для хранения значения 
uint16_t data = 0;

void setup() {

// инициализируем вывод в последовательный порт 
Serial.begin(115200);

// ждем, пока не открылся монитор порта 
while(!Serial);

// инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// инициализируем обработчик пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

// открываем порт 
portHandler->openPort();

// устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);


}


void loop() {

// выполняем чтение с регистра 26 длиной 2 байта

packetHandler->read2ByteTxRx(portHandler, DXL_ID, 26, (uint16_t*)&data); Serial.println(data);

delay(50);

}

Управление модулем «Драйвер двигателя постоянного тока (2 канала)»

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

«Драйвер двигателя постоянного тока (2 канала)». Значение ID данного модуля – 0х06, что составляет в десятичной записи – 6. Схема подключения представлена (Рис. 2.33 и Рис 2.34). Обратите внимание – подключение модуля к контроллеру выполняется через средний разъем. Т.к. именно он управляется встроенным контроллером OpenCM.

Рис. 2.33. Внешний вид подключения двигателей постоянного тока к модулю «Драйвер двигателя постоянного тока (2 канала)» и контроллеру STEM Board

Рис. 2.34. Схема подключения двигателей постоянного тока к модулю «Драйвер двигателя постоянного тока (2 канала)» и контроллеру STEM Board

#include <DynamixelSDK.h>

// указываем версию протокола (для всех модулей - 1.0) 
#define PROTOCOL_VERSION 1.0

// базовые настройки 
#define DXL_ID 6

#define BAUDRATE 57600

#define DEVICENAME “3”

// создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

// создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

// создаем и инициализируем переменную для хранения значения 
uint16_t data = 0;

void setup() {

// инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// инициализируем обработчик пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

// открываем порт 
portHandler->openPort();

// устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

// выполняем запуск первого и второго мотора на 50% мощности 
packetHandler->write2ByteTxRx(portHandler, DXL_ID, 28, 512);

packetHandler->write2ByteTxRx(portHandler, DXL_ID, 30, 512); 
delay(2000);

// меняем направление

packetHandler->write2ByteTxRx(portHandler, DXL_ID, 28, -512);

packetHandler->write2ByteTxRx(portHandler, DXL_ID, 30, -512); 
delay(2000);

}

Управление модулем «Трехцветный светодиод»

В качестве примера использования контроллера OpenCR-AR рассмотрим управление периферийным модулем «Трехцветный светодиод». Поскольку архитектуры программируемых контроллеров STEM Board и OpenCR-AR подобны, то управляющий код для обоих плат выглядит идентично, за исключением начальных настроек – для OpenCR-AR параметр DEVICENAME должен быть равен «1». В случае использования контроллера OpenCR-AR периферийные модули подключаются в ближний к USB разъем (см. Рис. 2.35).

Рис. 2.35. Контроллер OpenCR-AR с подключенным к нему модулем

«Трехцветный светодиод»

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

#include <DynamixelSDK.h>

// указываем версию протокола (для всех модулей - 1.0) 
#define PROTOCOL_VERSION 1.0

// базовые настройки 
#define DXL_ID 21

#define BAUDRATE 57600

#define DEVICENAME “1”


// создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

// создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

// создаем и инициализируем переменную для хранения значения 
uint16_t data = 0;

void setup() {

// инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

// инициализируем обработчик пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

// открываем порт 
portHandler->openPort();

// устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

// выполняем включение всех RGB составляющих последовательно 
packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 200); 
delay(2000);

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 27, 200); 
delay(2000);

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 28, 200); 
delay(2000);

// выключаем все составляющие

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 0);

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 27, 0);

packetHandler->write1ByteTxRx(portHandler, DXL_ID, 28, 0); 
delay(2000);

}

Управление модулем «Ультразвуковой дальномер»

В качестве примера рассмотрим процесс измерения расстояния при помощи модуля «Ультразвуковой дальномер». Значения расстояния будут выводиться на экране. Значение ID данного модуля – 0х02, что составляет в десятичной записи – 42. Схема подключения представлена на рисунке Рис. 2.36. Обратите внимание, в какой разъем осуществляется подключение модуля к контроллеру. Т.к. именно он управляется встроенным контроллером OpenCM.

После загрузки требуется открыть «Монитор порта» во вкладке «Инструменты»

Рис. 2.36. Подключение модуля «Ультразвуковой дальномер»

#include «DynamixelSDK.h»

//Базовые настройки

#define PROTOCOL_VERSION 1.0

#define DXL_ID 42

#define BAUDRATE 57600

#define DEVICENAME «3»

//Создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

//Создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;


uint8_t data = 0;

void setup() {

//Инциализируем вывод в последовательный порт 
Serial.begin(115200);

//Инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

//Иницализируем обработчика пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

//Открываем порт 
portHandler->openPort();

//Устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

//Запись значения 1 в регистр 25 для начала измерения данных 
packetHandler->write1ByteTxRx(portHandler, DXL_ID, 25, 1);

//Выполняем чтение с регистра 26 длиной 2 байта

packetHandler->read1ByteTxRx(portHandler, DXL_ID, 27, (uint8_t*)&data); Serial.println(«Дальность: « + String(data));

delay(200);

}

### Управление модулем «Датчик освещенности»

Рассмотрим процесс управления светодиодом с помощью модуля «Датчик освещенности». Для реализации подключаем модуль «Светодиод» к модулю «Датчика освещенности», последний подключаем к управляющей плате. В программе выставлено значение освящения. После запуска программы, при затемнении датчика освещенности, горящий модуль светодиода, увеличивает яркость.

Рис. 2.37. Подключение модулей «Датчик освещенности» и «Светодиод»

#include «DynamixelSDK.h»

//Базовые настройки

#define PROTOCOL_VERSION 1.0

#define DXL_LIGHT 25

#define DXL_LED 9

#define BAUDRATE 57600

#define DEVICENAME «3»

//Создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

//Создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

uint16_t data = 0; void setup() {

//Инциализируем вывод в последовательный порт 
Serial.begin(115200);

//Инициализируем обработчик порта


portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

//Иницализируем обработчика пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

//Открываем порт 
portHandler->openPort();

//Устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

//Выполняем чтение с регистра 26 длиной 2 байта

packetHandler->read2ByteTxRx(portHandler, DXL_LIGHT, 26, (uint16_t*)&data);

//Проверяем значение освещенности 
if(data < 330){

//Записываем в 26 регистр яркость LED датчика (0 - 255) 
packetHandler->write1ByteTxRx(portHandler, DXL_LED, 26, 180);

}

else{

packetHandler->write1ByteTxRx(portHandler, DXL_LED, 26, 80);

}

Serial.println(«Уровень освещенности: « + String(data)); 
delay(200);

}

Управление модулем «Датчик силы»

В качестве примера рассмотрим процесс измерения силы нажатия на модуль «Датчика силы». Значения будут выводиться на экране. Значение ID данного модуля – 0х20, что составляет в десятичной записи – 32. Схема подключения представлена на рисунке Рис. 2.38. Обратите внимание, в какой разъем осуществляется подключение модуля к контроллеру. Т.к. именно он управляется встроенным контроллером OpenCM.

Рис. 2.38. Подключение модуля «Датчик силы»

После загрузки требуется открыть «Монитор порта» во вкладке «Инструменты».

#include «DynamixelSDK.h»

//Базовые настройки

#define PROTOCOL_VERSION 1.0

#define DXL_ID 32

#define BAUDRATE 57600

#define DEVICENAME «3»

//Создаем экземпляр объекта обработчика порта 
dynamixel::PortHandler *portHandler;

//Создаем экземпляр объекта обработчика пакета 
dynamixel::PacketHandler *packetHandler;

uint16_t data = 0; void setup() {

//Инциализируем вывод в последовательный порт 
Serial.begin(115200);

//Инициализируем обработчик порта

portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);

//Иницализируем обработчика пакета

packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOC OL_VERSION);

//Открываем порт 
portHandler->openPort();

//Устанавливаем скорость соединения 
portHandler->setBaudRate(BAUDRATE);

}

void loop() {

//Выполняем чтение с регистра 26 длиной 2 байта

packetHandler->read2ByteTxRx(portHandler, DXL_ID, 26, (uint16_t*)&data); Serial.println(«Сила нажатия: « + String(data));

delay(200);

}

## Подключение к контроллеру CM-530

Программируемый контроллер CM-530, производимый компанией ROBOTIS, входит в состав большого количества робототехнических конструкторов, таких как: ROBOTIS STEM, ROBOTIS PREMIUM, «СТЕМ Лаборатория», «СТЕМ Академия». Программирование данного контроллера выполняется с помощью блочно-графической среды R+Task 3.0. Поскольку данный контроллер, по умолчанию, рассчитан на взаимодействие с Dynamixel-совместимыми устройствами, рассмотрим процесс управления и опроса некоторых простейших периферийных модулей. Остальные модули будут опрашиваться и управляться аналогично. Важно! Контроллер CM-530 умеет обмениваться данными только на скорости 1000000, в связи с чем, перед использованием периферийных модулей совместно с ним, необходимо изменить им настройки скорости.

Управление модулем «Трехцветный светодиод»

Подключение периферийного модуля «Трехцветный светодиод» к программируемому контроллеру СМ-530 выглядит следующим образом (см. Рис. 2.39):

Рис. 2.39. Подключение модуля «Трехцветный светодиод» к контроллеру CM-530

Рис. 2.40. Код управления модулем «Трехцветный светодиод» при помощи контроллера СМ-530 в среде разработки R+ Task

Опрос модуля «Потенциометр»

В качестве примера периферийного модуля, с которого можно получать данные на контроллер CM-530, рассмотрим модуль «Потенциометр». Для получения данных с модуля, код будет выглядеть следующим образом (см. Рис. 2.41):

Рис. 2.41. Код управления модулем «Потенциометр» при помощи контроллера СМ-530 в среде разработки R+ Task

Основным отличием данного примера является то, что результат опроса – двухбайтовое число, в связи с чем приходится читать подряд два регистра, а затем склеивать их в одно значение. В итоге, в монитор порта будет выводиться результат каждую 0.1 секунды.

Подключение к микрокомпьютеру с Linux и ROS через микроконтроллер

Для взаимодействия с функциональными периферийными модулями из-под операционной системы ROS (Robot Operating System) можно использовать промежуточный микроконтроллер. В качестве примера рассмотрим взаимодействие с периферийными модулями, используя микроконтроллер NanoPi-AR, интегрированный в контроллер OpenCR- AR (см. Рис. 2.42), и на котором установлены операционные системы Linux и ROS. Аналогичный подход можно применять и в случае использования периферийной платы STEM Board, с интегрированными в него микроконтроллером NanoPi-AR и контроллером OpenCM (см. Рис. 2.43).

Рис. 2.42. Подключение периферийного модуля к контроллеру OpenCR-CR с интегрированным в него контроллером NanoPi-AR

Рис. 2.43. Подключение периферийного модуля к универсальному контроллеру STEM Board (периферийная плата STEM Board с интегрированными в нее микроконтроллером NanoPi-AR и контроллером OpenCM)

Рассмотрим взаимодействия с периферийными модулями посредством контроллера под управлением на операционной системе ROS на двух следующих примерах – разберем способ опроса модуля «Концевой выключатель» и управление модулем «Светодиод». Подключение модулей к контроллерам в примерах выполняется так, как было показано на рисунках выше. Также для корректной работы необходимо подключить к контроллерам внешнее питание 12В.

Опрос модуля «Концевой выключатель»

Первым делом, необходимо загрузить управляющую программу в микроконтроллер. Полный код программы будет приведен в данном разделе далее. Сейчас давайте разберем основные части данной программы. У каждого Dynamixel-совместимого устройства есть свой ID. Стандартный DXL_ID (значение ID Dynamixel-совместимого устройства) для модуля «Концевой выключатель» составляет 23. Объявление значения ID

устройства происходит в строчке:

#define DXL_ID 23

Связь платы с микрокомпьютером NanoPI-AR осуществляется с помощью последовательного порта (Serial) на аппаратном уровне. Поэтому необходимо инициировать последовательное соединение с помощью команды:

Serial2.begin(115200);

После успешного открытия порта и инициализации модуля «Концевой выключатель» возможно считать состояние микропереключателя с помощью следующей команды:

dxl_comm_result = packetHandler->read2ByteTxRx(portHandler, DXL_ID, 27, &dxl_present_position, &dxl_error);

Состояние микропереключателя хранится в 27 регистре. Считав из него информацию, можно переслать соответствующие команды на микроконтроллер:

if (dxl_present_position != 0)

{

Serial2.println(push down); 
Serial.print(push down);

}

else { Serial2.println(push up);

}

В свою очередь, на стороне микрокомпьютера в рабочей папке требуется создать пакет и ноду-паблишер. Весь код ноды приведен далее. Кроме установленного и настроенного на микроконтроллере ROS, так же понадобится библиотека serial. Ниже разберем основные части управляющей программы.

Импортируем библиотеку serial:

import serial

Создадим паблишер и инициализируем ноду, более подробно с принципом работы ROS можно ознакомиться в соответствующих пособиях.

pub = rospy.Publisher(‘chatter’, String, queue_size=1) rospy.init_node(‘talker’, anonymous=True)

rate = rospy.Rate(100) # 10hz

Далее необходимо указать порт и скорость передачи данных:

port = serial.Serial(“/dev/ttyS1” , baudrate=115200, timeout=100)

После этого можно считать информацию с выбранного порта и отослать её в топик.

c = port.readline() print(c) pub.publish(c) rate.sleep()

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

Образец кода для контроллера OpenCR-AR:

#include <DynamixelSDK.h>

// Protocol version

#define PROTOCOL_VERSION 1.0 // See which protocol version is used in the Dynamixel

// Default setting

#define DXL_ID 23

#define BAUDRATE 57600

#define DEVICENAME “OpenCR_DXL_Port” // This definition only has a symbolic meaning and does not affect to any functionality

// Dynamixel moving status threshold 
#define ESC_ASCII_VALUE 0x1b 
#define CMD_SERIAL Serial

int getch()

{

while(1)

{

if( CMD_SERIAL.available() > 0 )

{

break;

}

}

return CMD_SERIAL.read();

}

int kbhit(void)

{

return CMD_SERIAL.available();

}

void setup()

{

Serial2.begin(115200); 
Serial.begin(115200); 
while(!Serial);

Serial.println(Start..);

// Initialize PortHandler instance

// Set the port path

// Get methods and members of PortHandlerLinux or 
PortHandlerWindows dynamixel::PortHandler *portHandler =dynamixel::PortHandler::getPortH

andler(DEVICENAME);

// Initialize PacketHandler instance

// Set the protocol version

// Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler

dynamixel::PacketHandler *packetHandler = dynamixel::PacketHandler::g etPacketHandler(PROTOCOL_VERSION);

int index = 0;

int dxl_comm_result = COMM_TX_FAIL; // Communication result uint8_t dxl_error = 0; // Dynamixel error


uint16_t dxl_present_position = 0; // Present position


// Open port

if (portHandler->openPort())

{

}

else

{

}

Serial.print(Succeeded to open the port!\n);

Serial.print(Failed to open the port!\n); return;

// Set port baudrate

if (portHandler->setBaudRate(BAUDRATE))

{

}

else

{

}

Serial.print(Succeeded to change the baudrate!\n);

Serial.print(Failed to change the baudrate!\n); return;

while(1)

{

dxl_comm_result = packetHandler->read2ByteTxRx(portHandler, DXL_ID, 27, &dxl_present_position, &dxl_error);

if (dxl_comm_result != COMM_SUCCESS)

{

Serial.print(packetHandler->getTxRxResult(dxl_comm_result));

}

else if (dxl_error != 0)

{

Serial.print(packetHandler->getRxPacketError(dxl_error));

}

if (dxl_present_position != 0)

{

Serial2.println(push down); 
Serial.print(push down);

}

else { Serial2.println(push up);

}

Serial.println( );

}

// Close port

portHandler->closePort();

}

void loop()

{

}

Образец кода ноды для микроконтроллера NanoPi-AR:

!/usr/bin/env python import rospy

import serial

from std_msgs.msg 
import String def talker():

pub = rospy.Publisher(chatter, String, queue_size=1) 
rospy.init_node(talker, anonymous=True)

rate = rospy.Rate(100) # 10hz

port = serial.Serial(/dev/ttyS1 , baudrate=115200, timeout=100) 
while not rospy.is_shutdown():

c = port.readline() 
print(c) 
pub.publish(c) 
rate.sleep()

if name ==  main :

try:

talker()

Управление модулем «Светодиод»

В случае управления модулем «Светодиод», посредством контроллера под управлением на операционной системе ROS, код программы будет приблизительно такой же, как и в случае предыдущего примера, за исключением направления передачи данных.

На стороне контроллера OpenCR-AR:

Значение DXL_ID для модуля «Светодиод» составляет 9:

#define DXL_ID 9

Информацию о состоянии модуля «Светодиод» можно получить при помощи следующих команд:

if (Serial2.available() > 0)

{

//Serial.println(Serial2.read());


incomingByte = Serial2.read(); 
Serial.println(incomingByte, DEC); 
if (incomingByte == 49)


{

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 50, &dxl_error);

}

if (incomingByte == 50)

{

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 0, &dxl_error);

}

}
Теперь нужно не считывать состояние, а записывать его. Для этого можно использовать следующую команду:

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 50, &dxl_error); Запись происходит в 26 регистр, следующий аргумент команды отвечает за значение, которое мы запишем в регистр:

«0» - светодиод не горит;

«50» - светодиод горит.

На стороне микроконтроллера NanoPi-AR:

На стороне микроконтроллера NanoPi-AR необходимо создать ноду-подписчик, которая будет отправлять информацию в порт S1 в зависимости от информации, которую она получила из топика.

rospy.loginfo(data.data) 
if data.data == 1:

port.write(b1)

if data.data == 2:

port.write(b2)

Образец кода для контроллера OpenCR-AR:

include

// Protocol version

define PROTOCOL_VERSION 1.0 // See which protocol version is used in the Dynamixel

// Default setting

#define DXL_ID 9 // Dynamixel ID: 1

#define BAUDRATE 57600

#define DEVICENAME “OpenCR_DXL_Port” // This definition only has a symbolic meaning and does not affect to any functionality

// Dynamixel moving status threshold 
#define ESC_ASCII_VALUE 0x1b #define CMD_SERIAL Serial

int getch()

{

while(1)

{

if( CMD_SERIAL.available() > 0 )

{

break;

}

}

return CMD_SERIAL.read();

}

int kbhit(void)

{

return CMD_SERIAL.available();

}

void setup()

{

Serial2.begin(115200); 
Serial.begin(115200); 
while(!Serial);

Serial.println(Start..);

// Initialize PortHandler instance

// Set the port path

// Get methods and members of PortHandlerLinux or 
PortHandlerWindows dynamixel::PortHandler *portHandler =dynamixel::PortHandler::getPortH

andler(DEVICENAME);

// Initialize PacketHandler instance

// Set the protocol version

// Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler

dynamixel::PacketHandler *packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION);

int index = 0;

int dxl_comm_result = COMM_TX_FAIL; // Communication result

uint8_t dxl_error = 0; // Dynamixel error 
uint16_t dxl_present_position = 0; // Present position


// Open port

if (portHandler->openPort())

{

}

else

{

}

Serial.print(Succeeded to open the port!\n);

Serial.print(Failed to open the port!\n); 
return;

// Set port baudrate

if (portHandler->setBaudRate(BAUDRATE))

{

}

else

{

}

Serial.print(Succeeded to change the baudrate!\n);

Serial.print(Failed to change the baudrate!\n); 
return;

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 0,&dxl_error);

int incomingByte = 0; 
while(1)

{

// 
dxl_comm_result = packetHandler->read2ByteTxRx(portHandler, DXL_ID, 27, &dxl_present_position, &dxl_error);

if (Serial2.available() > 0)

{

//
Serial.println(Serial2.read()); incomingByte = Serial2.read(); Serial.println(incomingByte, DEC); if (incomingByte == 49)

{

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 50,&dxl_error);

}

if (incomingByte == 50)

{

dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, DXL_ID, 26, 0, &dxl_error);

}

}

}

// Close port

portHandler->closePort();

}

void loop()

{

}

Образец кода ноды для микроконтроллера NanoPi-AR:

#!/usr/bin/env python import rospy

import serial from std_msgs.msg 
import String

def callback(data):

rospy.loginfo(data.data) 
if data.data == 1:

    port.write(b1)

if data.data == 2:

    port.write(b2) def listener():

    rospy.init_node(listener, anonymous=True) rospy.Subscriber(chatter, String, callback)

# spin() simply keeps python from exiting until this node is stopped rospy.spin()

if name ==  main :

    port = serial.Serial(/dev/ttyS1, baudrate=115200, timeout=100) listener()

Библиотека «PythonSDK» для микроконтроллера NanoPi-AR

#!/usr/bin/env python # -*- coding: utf-8 -*-

import os 
import rospy from std_msgs.msg 
import String 

if os.name == nt:
import msvcrt

def getch():

return msvcrt.getch().decode() 
else:

import sys, tty, termios fd = sys.stdin.fileno()

old_settings = termios.tcgetattr(fd) def getch():

try:

tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1)

finally:

termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
return ch

from dynamixel_sdk import * 
# Uses Dynamixel SDK library # Control table address

ADDR_MX_TORQUE_ENABLE = 64 
# Control table address is different in Dynamixel model

ADDR_MX_GOAL_POSITION = 116

ADDR_MX_PRESENT_POSITION = 132

# Protocol version

PROTOCOL_VERSION = 1.0 
# See which protocol version is used in the Dynamixel

# Default setting

DXL_ID = 9 # Dynamixel ID : 1

BAUDRATE = 57600 
# Dynamixel default baudrate : 57600 DEVICENAME = ‘/dev/ttyS2’ 
# Check which port is being used on your controller

# ex) Windows: “COM1” Linux: “/dev/ttyUSB0”

Mac: /dev/tty.usbserial-*

TORQUE_ENABLE = 1 # Value for enabling the torque TORQUE_DISABLE = 0 # Value for disabling the torque DXL_MINIMUM_POSITION_VALUE = 10 # Dynamixel will rotate between this value

DXL_MAXIMUM_POSITION_VALUE = 4000 # and this value (note that the Dynamixel would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.) DXL_MOVING_STATUS_THRESHOLD = 20 # Dynamixel moving status threshold

index = 0

dxl_goal_position = [DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_ POSITION_VALUE] # Goal position

# Initialize PortHandler instance

# Set the port path

# Get methods and members of PortHandlerLinux or PortHandlerWindows portHandler = PortHandler(DEVICENAME)

# Initialize PacketHandler instance # Set the protocol version

# Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler

packetHandler = PacketHandler(PROTOCOL_VERSION)

# Open port

if portHandler.openPort():

print(Succeeded to open the port) else:

print(Failed to open the port) print(Press any key to terminate...) getch()

quit()

# Set port baudrate

if portHandler.setBaudRate(BAUDRATE):

print(Succeeded to change the baudrate) else:

print(Failed to change the baudrate) print(Press any key to terminate...) getch()

quit()

# Enable Dynamixel Torque def callback(data):

rospy.loginfo(data.data) if data.data == 1:

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 26, 0)

if data.data == 2:

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 26, 50)

def listener():

rospy.init_node(listener, anonymous=True) rospy.Subscriber(chatter, String, callback)

# spin() simply keeps python from exiting until this node is stopped rospy.spin()


if name ==  main :


listener()

# Disable Dynamixel Torque

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, ADDR_MX_TORQUE_ENABLE, TORQUE_DISABLE)

if dxl_comm_result != COMM_SUCCESS:

print(%s % packetHandler.getTxRxResult(dxl_comm_result)) elif dxl_error != 0:

print(%s % packetHandler.getRxPacketError(dxl_error))

# Close port portHandler.closePort()

Управление модулем «Преобразователь интерфейсов»

Работа модуля «Преобразователь интерфейсов» по интерфейсу PWM. Подключение устройств к модулю по PWM. Пример программы для управления модулем регулирует подачу напряжения. Выбирается режим работы, записывается режим работы на 2 канала. В коде можно выста- вить параметр для первого и второго канала. Образец кода можно найти по ссылке: https://github.com/orgs/AppliedRobotics/

import os import sys

from socket import timeout

from lib.dynamixel_sdk import * #Библиотека до Dynamixel sdk !Стоит обратить внимание на маршрут библиотеки

#Обязательная инициализация if os.name == ‘nt’:

import msvcrt 
def getch():

return msvcrt.getch().decode() else:

import sys, tty, termios 
fd = sys.stdin.fileno()

old_settings = termios.tcgetattr(fd) 
def getch():

try:

tty.setraw(sys.stdin.fileno()) 
ch = sys.stdin.read(1)

finally:


termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 
return ch

os.system(«rs485 /dev/ttyS2 1»)
#открываем порт Dynamixel # Необходимые регистры и переменные

ADDR_BUF_A = 26

ADDR_DAC_ENABLE = 29

ADDR_MODE_SELECT = 28

# Protocol version PROTOCOL_VERSION = 1.0

# Default setting

DXL_ID = 161

BAUDRATE = 1000000

DEVICENAME = /dev/ttyS2

DAC_BUF_SIZE = 20

DAC_ENABLE = 2

DAC_DISABLE = 1

MODE_DAC = 33


#Инициализуруем обработчик порта и обработчик пакетов portHandler = PortHandler(DEVICENAME)

packetHandler = PacketHandler(PROTOCOL_VERSION)

# Открываем порт

if portHandler.openPort(): print(«Succeeded to open the port»)

else:

print(«Failed to open the port») print(«Press any key to terminate...») getch()

quit()

# Устанавливаем скорость обмена данными if portHandler.setBaudRate(BAUDRATE):

print(«Succeeded to change the baudrate») else:

print(«Failed to change the baudrate») print(«Press any key to terminate...») getch()

quit()


#Выставляем параметры для 1 и 2 канала parameters = [150, 155, 0, 0]


# Выставляем режим работы DAC

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, ADDR_MODE_SELECT, MODE_DAC)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) else:

print(«Mode selected»)

#Записываем параметры

dxl_comm_result, dxl_error = packetHandler.writeTxRx(portHandler, DXL_ ID, ADDR_BUF_A, 4, parameters)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) 
else:

print(«Parameters set»)

# Включаем 1 канал

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 24,2)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) 
elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) else:

print(«PWM1 enabled») #Включаем 2 канал

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 25, 2)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) else:

print(«PWM1 enabled»)

#Задержка в 10 секунд для проверки time.sleep(10)


#Закрываем 1 канал

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 24, 1)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) 
elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) 
else:

print(«PWM disabled») #Закрываем 2 канал

dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, 25, 1)

if dxl_comm_result != COMM_SUCCESS:

print(«%s» % packetHandler.getTxRxResult(dxl_comm_result)) 

elif dxl_error != 0:

print(«%s» % packetHandler.getRxPacketError(dxl_error)) 
else:

print(«PWM disabled»)

# Закрываем порт 
portHandler.closePort()

Center-nav

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