Программка для управления роботом через UART

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

Я купил китайское шасси и сделал простенькую схему – микроконтроллер Atmega16, с одной стороны общающийся с компом по UART через блютус модуль, а с другой – рулящий парой коллекторных двигателей через H-мосты. Написал элементарную программу для мк – при получении символа через UART проверялось, что это за символ, и если это символ ‘w’, то робот едет вперед, ‘a’ – влево, ‘d’ – вправо, ’z’ – назад, ‘s’ – стоп. Если запустить putty и открыть в ней нужный ком-порт, то можно нажимать клавиши на клавиатуре и управление получится почти как в компьютерной игрушке при помощи WASD, благодаря тому, что putty немедленно отправляет вводимые символы, не дожидаясь «Enter», как многие другие терминальные программы. В принципе, эта система на тот момент меня вполне радовала.

Но у такого подхода есть два существенных недостатка. Во-первых, непривычно и неудобно нажимать и тут же отпускать кнопку, лично я привык в игрушках зажимать кнопку «вперед», все время, пока я хочу ехать вперед. Во-вторых, не регулируется скорость, в частности, нельзя «подруливать», робот либо едет на полную мощность вперед, либо влево, и так далее – движения получаются очень дерганными, а управление – неудобным.

Последние полтора года я регулярно преподаю электронику и робототехнику школьникам (возможно, участникам сообщества с детьми будет интересно, школа называется «Ланат»), и они частенько строят всякие ездящие, ползающие и водоплавающие тележки с управлением через UART, короче столкнулся я с этой проблемой на регулярной основе – неудобно управлять через putty. Тем более, школьникам неинтересно просто сделать робота и поездить на нем – им подавай какие-нибудь соревнования, а какие соревнования могут быть, если робот кое-как управляется.

В общем, давно я хотел научиться писать GUI приложения, и кажется этот момент настал. После не очень длительного выбора остановился на QT, ибо писать умел только на C, и понравились обещания кросплатформенности, да и отзывы неплохие. Попутно пришлось раскурить C++ и вообще ООП, чему я очень рад, и просто влюбился в этот подход =). Сходу было не так легко переломить в себе закостенелое «процедурное» мышление, мне очень помог курс «Объектно-ориентированное программирование» (C++). МарГТУ [2010 г.]

Итак, в результате родилось приложение, которое позволяет управлять роботом на танковом шасси абсолютно так же, как в какой-нибудь Need For Speed, с плавным разгоном, поддержанием скорости, подруливанием, и автоматическим плавным торможением при отпускании.



Расскажу для начала, как работать с интерфейсом программы, а потом опишу протокол общения с роботом.


Интерфейс программы
Связь у нас через UART, поэтому в левом верхнем углу в разделе «Connection» есть необходимые для этого инструменты, а именно – выбрать порт, скорость, подключиться, отключиться. Ну и обновить список портов.

Далее в левом нижнем углу, в разделе «Robot’s status», показывается фактическое состояние двигателей, в какую сторону они крутятся и с какой силой. Если быть точнее – показывается мощность, вкачиваемая в мотор, а если еще точнее – просто OCR ШИМ-а от 0 до 255, ну и направление. Отображение уровня заряда батареи пока не работает, не дошли руки, хотя допилить очень легко. Сейчас робот ничего не отвечает на команды, в дальнейшем хочу добавить обратную связь, чтобы напряжение батареи снималось через АЦП и отправлялось в прогу, и возможно еще показания каких-нибудь других датчиков.

Посередине, в разделе «Robot’s control», показывается логическое состояние робота – в какую сторону и с какой скоростью едет, с какой интенсивностью поворачивает. Я до конца не разобрался в QT, но сейчас для успешной работы программы необходимо, чтобы фокус был на одном из ползунков, и стояла английская раскладка.

Справа блок настроек.
Control packets send interval, ms – периодичность отправки управляющих пакетов роботу.
Keyboard poll interval, ms – периодичность опроса клавиатуры программой.
Speed user change step – параметр, определяющий, насколько быстро скорость будет нарастать при зажатии кнопки «W» и «S».
Speed auto back change step – параметр, определяющий, насколько быстро скорость будет спадать при отпускании кнопок «W» и «S».
Steering user change step – параметр, определяющий, насколько быстро «руль поворачивается» при зажатии кнопки «A» и «D».
Steering auto back change step – параметр, определяющий, насколько быстро «руль возвращается в центральное положение» при отпускании кнопок «A» и «D».
Engines PWM deadzone – параметр, определяющий величину заполнения ШИМ, которой едва хватает для того, чтобы сдвинуть робота с места. Например, для моих моторов при питании от 12V этот параметр – 100. Когда я нажимаю «вперед», скважность не набирается от нуля, а сразу прыгает на 100, и дальше уже регулируется плавно до максимума, таким образом управление получается без провалов. Эта мертвая зона отрабатывается также при любых других сценариях, не обязательно старте с места. И тут наверное стоило бы ввести еще один параметр – величину заполненения ШИМ, которой достаточно для поддержания уже крутящегося двигателя, и при снижении скорость вращения использовать другую мертвую зону на основе этого параметра, но пока не стал заморачиваться.
Left/right engine using power, % — параметр, нужный для корректировки несимметричности двигателей. Зачастую при подаче одинаковой мощности, двигатели крутятся немного с разной скоростью, и это мешает ехать вперед прямо. Данный параметр, как вы наверное уже догадались, вводит понижающий коэффициент для более скоростного мотора, что помогает решить проблему.

Протокол общения.
Программа периодически шлет в UART простенький пакет из 6 байт
0x0F, LEFT_SPEED, LEFT_DIRECTION, RIGHT_SPEED, RIGHT_DIRECTION, 0x0E


Стартовый байт — 0x0F, подразумевается, что скорости и направления не могут быть равны этому значению.
Скорость левого — от 0* до 255.
Направление левого — 0 или 1.
Скорость правого — от 0* до 255.
Направление правого — 0 или 1.
Финишный байт — 0x0F

*Скорости теоретически задаются от 0 до 255, но, как я писал выше, функция PWM deadzone приводит к тому, что значения ниже некоторой планки никогда не придут. Я принудительно ограничил в программе поле ввода на уровне 90, поэтому в качестве стартового и финального байтов смело использую 0x0F и 0x0E. Костыль, велосипед, но уж как сделал =)

На этом пока всё.
В дальнейшем планирую еще добавить кручение сервомашинок при движениях мышью.
Критика и пожелания приветствуются. =)

Файлы прикреплены(смотрите под топиком, адски мелким незаметным шрифтом):
Архив с уже скомпилированной для Windows программой и необходимыми библиотеками — Robot_control.zip
Исходники, проект для QtCreator 5 — com_control2.zip
Проект для Atmel Studio 6 с работающим примером, там все просто, только, возможно, надо будет поменять контроллер на ваш и передефайнить ножки направления двигателей — Control_board.zip
  • +1
  • 26 ноября 2015, 05:35
  • termik
  • 3
Файлы в топике: com_control2.zip, Robot control.zip, Сontrol_board.zip

Комментарии (15)

RSS свернуть / развернуть
Хм, неплохо)) У самого есть что-то похожее(машинка+свой софт). Но у меня Windows Forms, поэтому не понимаю, зачем задавать периодичность опроса клавиатуры, ибо всё на события повесил)
0
Это нужно для того, чтобы отрабатывать длительность зажатия клавиши.
0
А, вон оно что)) У меня нажатие\отпускание клавиш обрабатываются с помощью событий KeyUp и KeyDown.
0
Наверняка в Qt так же можно сделать, я просто адски новичок в нем =)
0
Что то похожее писал на С#, оно у меня работает вместе из игровым джойстиком. По WiFi передает дату в ESP8266, а потом СТМ32 делает из этого 8- канальный ШИМ или PPM.
www.youtube.com/watch?v=yXlhmV_ZIEw
0
Control_board.zip — не открывается.
0
Действительно. Сейчас перезалил, проверил — открывается.
0
не-а, теперь 2 файла control_board.zip прикреплено и оба не открываются)
0
всё, психанул и сделал ссылки на дропбокс))
0
ну да, открываются, но что-то мне подсказывает вы не то выложили...)
0
Всё то, а из-за чего такие подозрения?)
0
я, конечно, на плюсах никогда не писал, но в while(1) только ";" как-то смущает, а в обработчике прерывания uart я предполагал будет массив в который будет складываться то что пришло в пакете по uart, а там вылавливаются только оnдельные ascii символы
0
Так, еще раз исправил))
0
Ну теперь похоже на правду, а с кодом в обработчике я не угадал =)
0
Дропбокс имеет свойство отваливаться спустя некоторое время. Не сам по себе, но по мере забивания автора.
ну и плюс на нем антилич, при срабатывании которого дропик шлет куда подальше всех желающих скачать.
Местная аттачилка вполне неплохо работает, если не открывается файл — вероятно приаттачено что-то не то.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.