История создания еще одного робота. Часть вторая, «it's alive!»

Продолжаю серию публикаций о создании простого колесного робота на микроконтроллере ATmega16A.
Во второй части моей публикации я опишу процесс создания и сборки своего робота. Начнем с изготовления печатной платы и закончим видео первых шагов (правильней сказать — прокручивания колес) нашего устройства. Также уделю внимание первому опыту программирования под PC в Qt, а именно созданию программы управления и обмена данными с роботом по Bluetooth.
Если хотите, можете ознакомится с первой публикацией и узнать с чего все началось, ну а всех остальных прошу под кат.
История создания еще одного робота. Часть вторая, «it's alive!»

Прошлая часть закончилась на том, что перед нами красовалась готовая разводка печатной платы, а значит, пора творить и переносить нашу задумку из электронной версии в реальный осязаемый мир, разве не это желание теплится в голове у каждого радиолюбителя, инженера, изобретателя?! У меня на руках был только 1мм текстолит, так что я недолго думая начал процесс переноса на плату рисунка дорожек стандартным ЛУТом.

Извиняюсь за качество фотографий, но телефон у меня дешевый…
История создания еще одного робота. Часть вторая, «it's alive!»

История создания еще одного робота. Часть вторая, «it's alive!»

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

История создания еще одного робота. Часть вторая, «it's alive!»

История создания еще одного робота. Часть вторая, «it's alive!»

80-90% дорожек на плате получились хорошо, но т.к. в основном дорожки были 0.2мм, попались протравы, которые я устранил с помощью припоя и тонких проводников, благодаря им же сделал переходные отверстия. Вообще весь процесс пайки занял 3 вечера.

История создания еще одного робота. Часть вторая, «it's alive!»

История создания еще одного робота. Часть вторая, «it's alive!»

Моторы пришлось перенести на нижнюю часть платы, так как понял, что мне нужен максимальный зазор между платой и поверхностью по которой нужно будет ездить, но и все равно робот получился с низкой посадкой.
И раз уж мы вспомнили про моторы, то вспомним и об идее с энкодером, так как магниты, которые я заказывал, были в диаметре буквально на пол миллиметра меньше пазов в колесе, то их нужно было как-то там зафиксировать, а как мы знаем все гениальное просто — я просто взял и загнал их туда, залив при этом из клеевого пистолета, не очень эстетично, зато быстро и практично. Главное не перепутать полярность, а то будут косяки с точностью, а она и так небольшая — 12 магнитов на колесо, т.е. 6 срабатываний за поворот, а с диаметром колес в 43мм получаем примерно 22мм пройденного колесом пути за одно срабатывание.

История создания еще одного робота. Часть вторая, «it's alive!»

На плате, в свою очередь, с небольшим разносом по высоте поставил датчики Холла, что бы понимать в какую сторону движемся.

История создания еще одного робота. Часть вторая, «it's alive!»

Для крепления аккумулятора, сервы и УЗ дальномера были распечатаны на 3D принтере простейшие детали.

Держатель аккумулятора.
История создания еще одного робота. Часть вторая, «it's alive!»

Держатель сервы.
История создания еще одного робота. Часть вторая, «it's alive!»

Держатель УЗ дальномера.
История создания еще одного робота. Часть вторая, «it's alive!»

Немного доводки деталей напильником и все встало на свои места, в итоге робот получился вот таким.

История создания еще одного робота. Часть вторая, «it's alive!»

История создания еще одного робота. Часть вторая, «it's alive!»

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

Была написана тестовая программа, которая реализовывала PD алгоритм. Она состояла из обработчика прерываний АЦП и собственно основного цикла работы с данными.

Обработчик прерывания
#define FIRST_ADC_INPUT 2 #define LAST_ADC_INPUT 7  unsigned 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]={0x21,0x41,0x61,0x63,0x23,0x43}; 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|=0x40;                       } 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|=0x40;         }     }   } } 


Реализация 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 |= 0x40; adc_ready = 0; sample_adc = 0;     } 



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



После этого я немного успокоился с частью программирования самого микроконтроллера и понял, что в будущем нужно будет реализовать программу управления роботом с ПК и принялся за изучение Qt, а так как последнюю программу для ПК я писал только в университете (на паскале) и это была какая-то стандартная лабораторная по информатике, то мои знания были в районе нуля.

оффтоп, о моих грандиозных планах управления роботом с смартфона и о том как я сдался и забил на эту идею
Вообще я изначально загорелся желанием написать программу для мобильного телефона на Android, но изучать Java не захотел, вернее не хотел уходить от Си, да и есть у меня друг, который шарил в Qt и у него можно было много чего спросить. Сначала я сам пытался постичь дзен работы с Qbluetooth и попытками состыковаться с HC-05 с помощью моего китайского Jiayu g3, но каждый раз натыкался на проблему, которая не позволяла HC-05 и Jiayu дружить. Сначала грешил на Qbluetooth и тем, что он не воспринимает HC-05, но в интернете нашел информацию о том, что люди запускают обмен данными через линейку блютуз модулей HC с помощью QBluetooth или пишут свои библиотеки, после жалоб другу о своей тяжелой жизни, друг за один день написал программу и все же смог обмениваться данными с роботом, но к сожалению через свой планшет. В итоге обосновав все тем что, мой китаец не поддерживает rfcomm, я сдался и решил писать все для ПК.


Программа должна была переключать режимы работы робота (следование по линии, управление с клавиатуры, автономный режим) и выдавать(задавать) данные со всех интересующих датчиков (сервы, датчики линии, УЗ дальномер, моторы, энкодеры).
После пары недель, была написана первая версия программы контрольной панели управления роботом. Очень понравилась работа с GUI в Qt — удобно.

История создания еще одного робота. Часть вторая, «it's alive!»

Код программы лучше не буду вставлять, дабы меня не забанили за издевательство над Си. Вкратце скажу, что программа просто по сигналу наличия данных в QSerialPort берет их и рассовывает по лэйблам и виджетам, в ответ по таймеру, если нужно, отправляет задающие данные, такие как положение сервы и скорость моторов. Зеленое поле в программе это в мечтах — будущая карта локации перед роботом.

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

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

П.С. В будущем постараюсь написать еще одну часть публикации, так сказать по мере продвижений в программной части.
Источник: http://habrahabr.ru/post/256209/