на втором месте после bldc по интересности, для меня, стоят протоколы взаимодействия между контроллерами.
тему я поднимал давно тут
forum40/topic10112.html?style=8Сергей сразу ответил что вопрос не в скорости а в протоколе.
С тех пор я много чего перепробовал, после того как освоил USB мне он кажется наиболее оптимальным в качестве связки между компом(ROS) и роботом (железом).
если есть возможность то лучше использовать USB (CONTROL message), просто, понятно быстро и надёжно.
Я выделяю структуры через которые происходит управление, например
Код:
struct BASE_CFG{
//in mm
float WHEEL_BASE_mm;
float WHEEL_L_D_mm;
float WHEEL_R_D_mm;
float WHEEL_C_r_m; //caster wheel radius (m)
float AF_m; //caster pivot to axle distance (m)
float FC_m; //caster pivot to axle distance (m)
float LEFT_CLICKS_PER_mm;
float RIGHT_CLICKS_PER_mm;
bool WHEEL_L_INVERSE_ROTATION;
bool WHEEL_R_INVERSE_ROTATION;
uint16_t usb_timeout_millis;
float p_gain;
float i_gain;
float d_gain;
float ff_gain; //ff gain
//must be lastone
bool configured;
};
struct ODOMETRY_MSG{
float transform_x; //m
float transform_y; //m
float transform_orientation; //rad
float linear_vel; // m/s
float angular_vel; // rad/s
float batt; //battery voltage v
};
struct USB_CMD_VEL{
float linear;
float angular;
}target_velocity;
Далее в коде после того как успешно подключаюсь к устройству начинаю обмен данными (пересылка структур) например
Код:
libusb_send(
CONTROL_REQUEST_TYPE_OUT , /*bmRequestType*/
ETERM_OUT_BASE_CFG, /*bRequest*/
0x00, /*wValue*/
16, /*wIndex*/
( unsigned char*)&basecfg, /*data*/
sizeof(BASE_CFG) /*wLength*/
);
здесь ETERM_OUT_BASE_CFG это команда а basecfg это структура которую я заполнил и передаю в МК.
Таким образом и на хосте и в МК одинаковые структуры с одинаково заполненными полями.
Т.е. с точки знерия программирования я не задумываясь работаю с одинаковой конфигурацией и на хосте и в МК.
Вот так например получаю состояние одометрии
Код:
int eterm_get_odometry(libusb_device_handle *devh)
{
if (!device_ready) return 1;
if ( libusb_send(
CONTROL_REQUEST_TYPE_IN ,
ETERM_IN_ODOMETRY_MSG,
0x00,
0,
(unsigned char*)&odometrymsg,
sizeof(odometrymsg)
) )
{
ROS_DEBUG( "recieve odometry x,y,th,V,A=%f,%f,%f,%f,%f",
odometrymsg.transform_x,
odometrymsg.transform_y,
odometrymsg.transform_orientation,
odometrymsg.linear_vel,
odometrymsg.angular_vel );
}
return 0;
}
Т.е главная фишка, в usb мы можем определить произвольную команду через которую можем посылать структуру (сообщение), и принимать(синхронизировать) структуру.
При этом мы не задумываемся о сериализации или надёжности доставки сообщений,всё происходит автомагически.
Ещё одно преимущество, можно взять стандартный класс, например CDC и дополнить его своими командами,
при этом одновременно (параллельно) будут работать
1) терминал (usb uart) minicom (там отладочные сообщения и shell)
2) команды управления (нода ROS)
3) мониторинг состояния батареии по cron.
Скорость обмена контрольными сообщениями 1000 сообщений в сек, размер одного сообщения до 64 байт.
поскольку нет затрат на сериализацию, вычисления контрольных сумм и прочего, то этого вполне достаточно.
В роботе пылесосе
forum90/topic16676.html?style=8к сожалению USB недоступен, поэтому я реализовал похожий протокол поверх UART.
но конечно накладных расходов больше чем при работе по USB.
Более подробно расскажу когда доделаю этот протокол и робота.
_________________
R3
forum87/topic15337.html R2 roboforum.ru/forum102/topic13980.html
R4 roboforum.ru/post336339.html#p336339
Делать надо хорошо - плохо получится само!