DOKUMENTACJA dot. Budowy i przebiegu konstrukcji linefollower-a Data: 2016-11-25 MCHT2 Jakub Tomczyk Łukasz Pawelec Mateusz Wróbel
Spis Treści 1. Opis tematu. 2. Niezbędne obliczenia 3. Schemat ideowy 4. Wykaz elementów użytych do budowy 5. Schemat elektryczny 6. Przebieg konstrukcji projektu 7. Software MCU wraz z komentarzami i opisem działania 8. Wnioski i sugestie dotyczące ulepszenia robota
1.Opis działanie produktu końcowego. Celem projektu jest stworzenie robota podążającego za linią. Na budowę robota składają się dwie płytki PCB. Płytka stanowiąca podwozie oraz listewko z czujnikami. Układ stworzony został w oparciu o mikrokontroler ATMEGA 32. Rozpoznawanie linii zostało zrealizowane poprzez zamontowanie czujników odbiciowych na przedniej listewce z czujnikami robota. Stan każdego czujnika wyświetlany jest na diodzie LED. Czujniki po odróżnieniu koloru czarnego od białego wysyła sygnał do przetwornika ADC mikrokontrolera, gdzie podejmowana jest decyzja o regulacji obrotów silnika poprzez PWN, wykorzystując do tego regulator PD. Sterowanie kierunkiem działania silników odbywa się przy użyciu mostku H. 3.Schemat ideowy
4. Wykaz elementów użytych do budowy KAB-05476 Bezpiecznik polimerowy 72V/0,5A raster 5,1mm - 10szt. 1 PLL-04973 Silnik Pololu HPCB 10:1 2 PAS-00430 Kondensator tantalowy 100uF/10V SMD - C 4 PAS-00513 Kondensator tantalowy 22uF/16V SMD - C 2 UCC-00160 Mikrokontroler AVR - ATmega32A-AU SMD 2 UCC-00053 Czujnik transoptor odbiciowy KTIR0711S 10 KAB-00191 Wtyk IDC 10 pin prosty - 5 szt. 1 PAS-00438 Dławik osiowy przeciwzakłóceniowy 10uH/160mA - 10szt. 1 KAB-01450 Zestaw goldpin raster 2,54mm - mini 1 LED-01456 Zestaw diod LED SMD 0603-30 szt. 1 UCC-00495 TB6612FNG - dwukanałowy sterownik silników 2 UCC-00250 Dioda Schottky SK23 SMD 10 UCC-05272 Przełącznik suwakowy SS22T25 2-pozycyjny 2 PLL-00036 Mocowania do micro silników Pololu - czarne - 2szt. 1 PAS-02002 Rezonator kwarcowy 16MHz - SMD 5 x 3,2 mm 1 UCC-00081 Stabilizator 5V L7805ABV - THT TO220 2
5.Schematy elektryczne
6.Przebieg konstrukcji projektu 1. Projektowanie płytki BRD po przetworzeniu schematu elektrycznego 2. Przejście do wytrawienia i docięcia fizycznej płytki
3.Przystąpienie do lutowania elementów układu SMD a)listwa z czujnikami b)główna płytka układu
4. Podłączenie zasilania, wgranie programu i rozruch robota 7.Software MCU wraz z komentarzami #include <AVR/io.h> #include <AVR/interrupt.h> #include <util/delay.h> #define port_silnikow PORTD #define lewy_1 PD1 #define lewy_2 PD2 #define prawy_1 PD7 #define prawy_2 PD6 #define led1on PORTB = (1<<PB3) #define led1off PORTB &= ~(1<<PB3) #define led2on PORTB = (1<<PB2) #define led2off PORTB &= ~(1<<PB2) #define led3on PORTB = (1<<PB1) #define led3off PORTB &= ~(1<<PB1) #define led4on PORTB = (1<<PB0) #define led4off PORTB &= ~(1<<PB0) #define led5on PORTC = (1<<PC7) #define led5off PORTC &= ~(1<<PC7) #define led6on PORTC = (1<<PC6) #define led6off PORTC &= ~(1<<PC6) #define led7on PORTC = (1<<PC1) #define led7off PORTC &= ~(1<<PC1) #define led8on PORTC = (1<<PC0) #define led8off PORTC &= ~(1<<PC0) #define led4tg PORTB ^= (1<<PB0) unsigned int Kp = 15; unsigned int Kd = 0; unsigned int V_max = 50; unsigned int prog = 128; //nastawy regulatora // 255 możliwe;
volatile unsigned int tablica_ktir[8]; volatile int wagi[8] = -10,-7,-3,-1,1,3,10,10; unsigned int adr_czujnikow[8] = 0,1,2,3,4,5,6,7; volatile int uchyb = 0; volatile int regulacja = 0; unsigned int flaga_ktir = 0, flaga_go = 0; volatile unsigned int flaga_start = 0; volatile unsigned int i=0; volatile int uchyb_poprzedni; int PD(int uchyb); int Licz_uchyb(); void Regulacja_silnikow(int lewy, int prawy); int main(void) DDRC = (1<<PC0) (1<<PC1) (1<<PC6) (1<<PC7); // ustawienie diod jako wyjscia DDRB = (1<<PB0) (1<<PB1) (1<<PB2) (1<<PB3); // ustawienie diod jako wyjscia DDRD &= ~(1<<PD3); // ustawienie przycisku jako wejscie PORTD &= ~(1<<PD3); // zewnetrzny pull up DDRD = (1<<PD4) (1<<PD5); //ustawienie pinow PWM jako wyjscie DDRD = (1<<PD1) (1<<PD2) (1<<PD6) (1<<PD7); //ustawienie pinow silnikow jako wyjścia port_silnikow = (1<<prawy_1); port_silnikow &= ~(1<<prawy_2); port_silnikow = (1<<lewy_2); port_silnikow &= ~(1<<lewy_1); DDRA &= 0b00000000; // ustawienie pinow czujnikow jako wejscia //konfiguracja przerwania //////////////////////////////////////////////////////// MCUCR = (1<<ISC11); GICR = (1<<INT1); przerwan INT1 //zbocze opadajace INT1 //wlaczenie //PWM////////////////////////////////////////////////////////////////////////////// TCCR1A = (1<<WGM10); //Phase Correct PWM TCCR1B = (1<<CS11) ; //prescaler 8 TCCR1A = (1<<COM1B1) (1<<COM1A1); TCCR1A = (1<<COM1A0); //odwrocenie fazy pierwszego kanalu pwm //ADC////////////////////////////////////////////////////////////////////////////// ADMUX = (1<<REFS0); AVCC ADCSRA = (1<<ADPS0) (1<<ADPS1) (1<<ADPS2); 128 ->125kHz ADC dla 16 MHz clock ADMUX = (ADMUX & 0b11111000) 0; będzie sprawdzał // zrodlo odniesienia // ustawienie prescalera na // pierwszy kanał, który
ADMUX = (1<<ADLAR); lewej ADCSRA = (1<<ADEN) (1<<ADIE) ; i zgoda na przerwanie ADCSRA = (1<<ADSC); // justowanie wyniku do // wlaczenie przetwornika ADC //start pierwszej pojedynczej konwersji bo jest dłuższa //Timer2 CTC 30Hz ////////////////////////////////////////////////////////////// TCCR2 = (1<<WGM21); //wybor trybu CTC TCCR2 = (1<<CS21) (1<<CS22) (1<<CS20); //prescaler 1024 TIMSK = (1<<OCIE2); //przerwanie OCR2 = 50; //max wartość porownania sei(); while(1) while(1) if(tablica_ktir[0]) led1on; else led1off; if(tablica_ktir[1]) led2on; else led2off; if(tablica_ktir[2]) led3on; else led3off; if(tablica_ktir[3]) led4on; else led4off; if(tablica_ktir[4]) led5on; else led5off; if(tablica_ktir[5]) led6on; else led6off; if(tablica_ktir[6]) led7on; else led7off; if(tablica_ktir[7]) led8on; else led8off; if(flaga_start) _delay_ms(2000); flagastart^=1 flagago^=1 if(flaga_ktir && flaga_go ) uchyb = Licz_uchyb(); flaga_ktir = 0; Regulacja_silnikow(V_max - regulacja, V_max + regulacja); else OCR1A = 0; OCR1B = 0; ISR(ADC_vect) if (ADCH > 100) tablica_ktir[i] = 1; else tablica_ktir[i] = 0; //wykrywa kolor czarny if (i>=7)
flaga_ktir = 1; i = 0; else i++; ADMUX = (ADMUX & 0b11111000) adr_czujnikow[i]; ADCSRA = (1<<ADSC); // start pojedynczej konwersji int Licz_uchyb() int cnt = 0 ; int j; for ( j = 0; j<8; j++) cnt += tablica_ktir[j]; // ile czujników miało czarny kolor if(cnt) uchyb = 0; for ( j = 0; j<8; j++) uchyb += tablica_ktir[j] * wagi[j]; uchyb /= cnt; uchyb_poprzedni = uchyb; return uchyb; //################################################################################# int PD(int uchyb) int regulacja; int P=0,D=0; P = Kp * uchyb; D = Kd * (uchyb - uchyb_poprzedni); uchyb_poprzedni = uchyb; regulacja = P+D; return regulacja; void Regulacja_silnikow(int lewy, int prawy) int silnik_lewy; int silnik_prawy; if(lewy >= 0) if(lewy >= 255) silnik_lewy = 255; port_silnikow = (1<<lewy_1); port_silnikow &= ~(1<<lewy_2); else if(lewy < -255) silnik_lewy = -255; silnik_lewy = -lewy; // Silnik lewy // do przodu // do tyłu
port_silnikow &= ~(1<<lewy_1); port_silnikow = (1<<lewy_2); //------------------------------------------------------------- if(prawy >= 0) // Silnik prawy if(prawy >= 255) silnik_prawy = 255; // do przodu port_silnikow = (1<<prawy_1); port_silnikow &= ~(1<<prawy_2); else if(prawy < -255) silnik_prawy = -255; // do tyłu silnik_prawy = -prawy; port_silnikow &= ~(1<<prawy_1); port_silnikow = (1<<prawy_2); OCR1A = silnik_lewy; OCR1B = silnik_prawy; ISR(TIMER2_COMP_vect) regulacja = PD(uchyb); ISR(INT1_vect) flaga_start = 1; 8.Wnioski i sugestie ulepszenia robota Jeżeli chodzi o samego robota to zaleca się wykonanie odrobinę grubszych ścieżek z większą izolacją, ze względu na duże problemy z wykonaniem płytki tego typu przy użyciu termotransferu. Dodatkowo ułatwienie lutowania całego układu może spowodować zamiana prostych wtyk idc na kątowe. W celu ulepszenia robota można zalecić wprowadzenie sterowania silnikami przy użyciu pojedynczego dwukanałowego mostka H. Istnieje także, możliwość zamontowania modułu Bluetooh w celu odbierania i wysłania danych przy użyciu terminala na androida.