История создания еще одного робота. Часть вторая, «it's alive!»
Продолжаю серию публикаций о создании простого колесного робота на микроконтроллере ATmega16A.Во второй части моей публикации я опишу процесс создания и сборки своего робота. Начнем с изготовления печатной платы и закончим видео первых шагов (правильней сказать — прокручивания колес) нашего устройства. Также уделю внимание первому опыту программирования под PC в Qt, а именно созданию программы управления и обмена данными с роботом по Bluetooth.Если хотите, можете ознакомится с первой публикацией и узнать с чего все началось, ну, а всех остальных прошу под кат.Прошлая часть закончилась на том, что перед нами красовалась готовая разводка печатной платы, а значит, пора творить и переносить нашу задумку из электронной версии в реальный осязаемый мир, разве не это желание теплится в голове у каждого радиолюбителя, инженера, изобретателя?! У меня на руках был только 1 мм текстолит, так что я недолго думая начал процесс переноса на плату рисунка дорожек стандартным ЛУТом.Извиняюсь за качество фотографий, но телефон у меня дешевый…
Следующим шагом было травление! Опробовал для себя новый способ травления с помощью перекиси водорода и лимонной кислоты, способ конечно безопасный и очень дешевый, но показался мне слишком чувствительным к пропорциям компонентов. После часа колдовских манипуляций над тарой с раствором процесс пошел с достойной силой (стоит сказать, что можно было изменить шаблон платы и тогда бы все вытравилось заметно быстрее).
80–90% дорожек на плате получились хорошо, но т.к. в основном дорожки были 0.2 мм, попались протравы, которые я устранил с помощью припоя и тонких проводников, благодаря им же сделал переходные отверстия. Вообще весь процесс пайки занял 3 вечера.
Моторы пришлось перенести на нижнюю часть платы, так как понял, что мне нужен максимальный зазор между платой и поверхностью по которой нужно будет ездить, но и все равно робот получился с низкой посадкой.И раз уж мы вспомнили про моторы, то вспомним и об идее с энкодером, так как магниты, которые я заказывал, были в диаметре буквально на пол миллиметра меньше пазов в колесе, то их нужно было как-то там зафиксировать, а как мы знаем все гениальное просто — я просто взял и загнал их туда, залив при этом из клеевого пистолета, не очень эстетично, зато быстро и практично. Главное не перепутать полярность, а то будут косяки с точностью, а она и так небольшая — 12 магнитов на колесо, т.е. 6 срабатываний за поворот, а с диаметром колес в 43 мм получаем примерно 22 мм пройденного колесом пути за одно срабатывание.
На плате, в свою очередь, с небольшим разносом по высоте поставил датчики Холла, что бы понимать в какую сторону движемся.
Для крепления аккумулятора, сервы и УЗ дальномера были распечатаны на 3D принтере простейшие детали.
Держатель аккумулятора.
Держатель сервы.
Держатель УЗ дальномера.
Немного доводки деталей напильником и все встало на свои места, в итоге робот получился вот таким.
И да, это просто бусина, бусина на толстой проволоке, и это пока единственная нерешенная «проблема» конструкции. На самом деле не брался за решение вопроса о третьем колесе, ибо загорелся подрыгать колесами, повертеть сервой и т.п.Из за использования 1 мм текстолита робот кажется хлюпким, но так как масса у нас небольшая это никак не влияет на его прочность и маневренность.Ну и первым делом захотелось прокатиться по линии, так сказать первый опыт с автоматизированным управлением.Сразу скажу, что я не программист по профессии и это наверно моя самая слабая точка в хобби, так что прошу не сильно критиковать код, в любом случае я уверен, что нужно будет переписывать всю программу в будущем.
Была написана тестовая программа, которая реализовывала PD алгоритм. Она состояла из обработчика прерываний АЦП и собственно основного цикла работы с данными.
Обработчик прерывания #define FIRST_ADC_INPUT 2#define LAST_ADC_INPUT 7unsigned int real_adc[8]={0,0,0,0,0,0,0,0}; unsigned char sample_adc; volatile unsigned char adc_ready = 0; unsigned char leds[8]={0×21,0×41,0×61,0×63,0×23,0×43}; unsigned char adc_inputs[8]={0,1,2,4,6,7,3,5};
interrupt [ADC_INT] void adc_isr (void) //////////////ADC_INT{static unsigned char input_index=0;
if (adc_ready == 0){if (sample_adc == 0) {real_adc[input_index]=(signed int)(ADCW); if (input_index < LAST_ADC_INPUT-FIRST_ADC_INPUT){input_index++;} else {input_index = 0;PORTB=leds[input_index];sample_adc = 1;
}ADMUX=(ADC_VREF_TYPE & 0xff)+adc_inputs[(FIRST_ADC_INPUT+input_index)]; ADCSRA|=0×40;
} else {if (adc_ready==0) {if (ADCW > real_adc[input_index]){real_adc[input_index]=(signed int)(ADCW);} else {real_adc[input_index]=(signed int)(real_adc[input_index]);}
if (input_index < (LAST_ADC_INPUT-FIRST_ADC_INPUT)){input_index++;PORTB=leds[input_index];} else {input_index = 0;adc_ready = 1;PORTB&=~(1<<0);}
ADMUX=(ADC_VREF_TYPE & 0xff)+adc_inputs[(FIRST_ADC_INPUT+input_index)];
}
if (adc_ready == 0){ADCSRA|=0×40;}}}}
Реализация PID if (adc_ready == 1) {adc_l = (real_adc[1]+real_adc[2]); adc_r = (real_adc[3]+real_adc[4]); error = (adc_l-adc_r); delta_error = error — old_error;//sum_error += error; PID = Kp*error + Kd*delta_error + Ki*sum_error; old_error = error;
if (PID > 0) {pwr_l += (signed int)PID; pwr_r -= (signed int)PID;} else {pwr_l += (signed int)PID; pwr_r -= (signed int)PID;}
for (i=0; i < (LAST_ADC_INPUT-FIRST_ADC_INPUT)+1; i++){real_adc[i]=0;}
ADCSRA |= 0×40; adc_ready = 0; sample_adc = 0;}
Как же я был рад видеть, что робот выполняет возложенную на него функцию, не так конечно как на крутых видеороликах с абсолютно плавными и быстрыми linefolower’ами, но для меня даже такой результат был достижением.
[embedded content]
После этого я немного успокоился с частью программирования самого микроконтроллера и понял, что в будущем нужно будет реализовать программу управления роботом с ПК и принялся за изучение Qt, а так как последнюю программу для ПК я писал только в университете (на паскале) и это была какая-то стандартная лабораторная по информатике, то мои знания были в районе нуля.
оффтоп, о моих грандиозных планах управления роботом с смартфона и о том как я сдался и забил на эту идею Вообще я изначально загорелся желанием написать программу для мобильного телефона на Android, но изучать Java не захотел, вернее не хотел уходить от Си, да и есть у меня друг, который шарил в Qt и у него можно было много чего спросить. Сначала я сам пытался постичь дзен работы с Qbluetooth и попытками состыковаться с HC-05 с помощью моего китайского Jiayu g3, но каждый раз натыкался на проблему, которая не позволяла HC-05 и Jiayu дружить. Сначала грешил на Qbluetooth и тем, что он не воспринимает HC-05, но в интернете нашел информацию о том, что люди запускают обмен данными через линейку блютуз модулей HC с помощью QBluetooth или пишут свои библиотеки, после жалоб другу о своей тяжелой жизни, друг за один день написал программу и все же смог обмениваться данными с роботом, но к сожалению через свой планшет. В итоге обосновав все тем что, мой китаец не поддерживает rfcomm, я сдался и решил писать все для ПК.
Программа должна была переключать режимы работы робота (следование по линии, управление с клавиатуры, автономный режим) и выдавать (задавать) данные со всех интересующих датчиков (сервы, датчики линии, УЗ дальномер, моторы, энкодеры).После пары недель, была написана первая версия программы контрольной панели управления роботом. Очень понравилась работа с GUI в Qt — удобно.
Код программы лучше не буду вставлять, дабы меня не забанили за издевательство над Си. Вкратце скажу, что программа просто по сигналу наличия данных в QSerialPort берет их и рассовывает по лэйблам и виджетам, в ответ по таймеру, если нужно, отправляет задающие данные, такие как положение сервы и скорость моторов. Зеленое поле в программе это в мечтах — будущая карта локации перед роботом.
Программа принимает все доступные данные и временно выступает как дебаггер. Пока не реализовывал управление с клавиатуры, да и автономный режим очень сырой и робот пока просто видя препятствие, разворачивается на заданный угол и пытается уехать в новом направлении. В общем как я и говорил, проект в целом пока сыроват в программной части.
В будущем хочется реализовать грандиозные планы, которые немного стопорятся пониманием того что нужно переделывать обе программы на МК и ПК полностью, так как я сделал большую ошибку и начал писать обе программы как раздутый слоеный пирог где один тестовый модуль соседствует с другим, а не как строгую структурированную систему. Но главное не опускать руки и творить дальше, пока то, что ты задумал в голове не будет реализовано в материальном мире ведь в этом и есть смысл хобби.
П.С. В будущем постараюсь написать еще одну часть публикации, так сказать по мере продвижений в программной части.