В данном разделе будут разобраны методы и подходы по непосредственной работе с периферийными функциональными модулями. Поскольку многие модули по принципам работы являются идентичными, то для таких модулей будут показаны обобщенные примеры. Для лучшего понимания процесса работы с модулями рекомендуется самостоятельно ознакомиться с принципами функционирования широко используемых простейших сенсоров, таких как: датчики расстояния, датчики освещения и т.п.
Рассматриваемые модули обладают двумя глобальными подходами к их применению. Первый подход они могут выступать как классические 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);
}
Рис. 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(){
}
Таким образом, можно управлять цифровыми модулями, используя как управление низким и высоким уровнем, так и управление путем плавного изменения уровня управляющего сигнала.
Получение данных с модуля «Потенциометр»
Подключаем модуль «Потенциометр» к контроллеру КПМИС, в соответствии со схемой расположения контактов. Линию модуля 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); // Задание положения привода
}
Далее будут приведены ряд примеров взаимодействия с периферийными модулями, как с 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);
}
Управление модулем «Силовой ключ»
Значение 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(b’1’)
if data.data == “2”:
port.write(b’2’)
Образец кода для контроллера 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(b’1’)
if data.data == “2”:
port.write(b’2’) 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