Linjeföljare med AVR, färdig

Berätta om dina pågående projekt.
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Linjeföljare med AVR, färdig

Inlägg av övrigt »

Tjena

Tänkte visa upp mitt senaste projekt. Detta är mitt första stora projekt sen jag började med mikrokontrollers. Det är en linjeföljare som ”ser” en svart linje och kör efter den. Både hård- och mjukvaran är designad helt efter egna idéer. Projektet blev klart ganska precis en månad efter att jag fått mitt STK500.

Processorn som används är en ATmega88. Styrtekniken är en PD regulator implementerad i assembler. Värdena på P och D har jag bara testat fram och inte räknat något på, men kan säga att den följer linjen ganska stabilt och helt ok snabbt. Jag gjorde en liten miss i hårdvaran då ögonen ligger rätt långt framför hjulen som driver roboten. Trots det fick jag ändå till mjukvaran så jag är nöjd med slutresultatet. Jo, slutresultatet. Kommer jag göra några förändringar ytterligare så kommer de troligen inte att vara några väsentliga.

Såhär ser den ut. Film finns på

http://www.youtube.com/watch?v=FlvyGUk_QIA


Bild

Bild

mvh
Senast redigerad av övrigt 2 juni 2008, 03:14:28, redigerad totalt 1 gång.
Appotus
Inlägg: 52
Blev medlem: 20 januari 2008, 15:39:19
Ort: Borås
Kontakt:

Inlägg av Appotus »

Snyggt :D
Användarvisningsbild
Jeppsson
EF Sponsor
Inlägg: 810
Blev medlem: 3 oktober 2005, 18:00:43
Ort: Karlskrona

Inlägg av Jeppsson »

Ganska enkelt, men ändå jättekul när man får det att funka bra...

Bra jobbat :tumupp:
Användarvisningsbild
Andax
Inlägg: 4379
Blev medlem: 4 juli 2005, 23:27:38
Ort: Jönköping

Inlägg av Andax »

Verkar som om diinoweb har en begränsad överföringsmängd. Går inte att gå in på sidan eller se bilderna...
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Jag såg det ja… visste inte om det och det var ju synd. Det funkade från början iaf, och det borde komma igång snart igen. Tar tillfälligt bort filmerna förutom slutversionen (samt en massa annat) för att försöka få ner totala mängden dataöverföring. Det jag ville visa med flera filmer var delar av utvecklingen samt hur mycket snabbare och stabilare den kunde gå med PD istället för P-regulator.

Tack för kommentarerna! :)
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Inlägg av squiz3r »

Du kan ju ladda upp dem på youtube istället.

Ser riktigt nice ut detta :)
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Ah, bra tips. Fast jag hade nog ändå inte vågat visa den så pass publikt. Visste ju inte vad andra skulle tycka om den :? . Men feedbacken här verkar ju god, så den kommer kanske ut där senare.

Förresten det där med att jag nått slutversionen kunde jag ju glömma :wink: . Med hårdvaran möjligen men nu jobbar jag med att få till mjukvaran bättre för att den ska gå snabbare. I filmen som ligger på diino gör den banan på ganska precis 20s. Nu är jag nere i 15 efter att ha laborerat vidare med P och D. Vad tror ni förresten om att förutom att ta hänsyn till reglerfelet och derivatan på detsamma även ta hänsyn till andraderivatan? Borde man kunna få den att reagera snabbare tror ni? Ska även försöka lägga in lite funktioner som gör att den utnyttjar banan lite bättre, så som jämnare fart i kurvorna och snabbare där det inte svänger så mycket. Ni får gärna komma med idéer också. Jag är mottaglig för tips nu när jag kommit så pass långt med den att jag ändå kan kalla den ”min” ide, även om jag tar emot tips :roll: (det var därför jag valde att lägga ut allt först när det var ”färdigt”).

mvh
DupeS
Inlägg: 90
Blev medlem: 30 september 2003, 18:27:39
Ort: Linköping

Inlägg av DupeS »

Här har du lite inspiration till pd snabbare har jag inte sett
http://elm-chan.org/works/ltc/report.html

han kör också avr samt P och D programerat i asm.
på filmerna som du hittar nederst på sidan observera hur
pappret rör på sig när den svänger, ändå håller den sig kvar på linjen.
Imponerande, tycker jag..
Användarvisningsbild
JonasJ
Inlägg: 653
Blev medlem: 11 september 2007, 16:02:26
Ort: Kinna
Kontakt:

Inlägg av JonasJ »

Trevligt! Har du något stöd längst fram eller glider den på kretskortet?

Önskar att jag själv någon gång skulle kunna hinna avsluta ett projekt innan jag påbörjar ett nytt :roll:

Edit: Hur driver du motorerna?
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Hehe, den där tänker jag inte ens låtsas att jag kommer slå :shock: .

Roboten är baktung pga motorernas placering så den vilar mot det lilla hjulet baktill, experimentkorten hänger fritt. Egentligen borde jag sätta nån slags kula eller typ skrivbordsstolshjul i miniatyr där istället. Får se om jag ger hårdvaran en översyn senare.

Motorerna är pwm styrda. Tiden hög för P delen är konstant och justeras över till ena eller andra motorn beroende på skillnaden i ljusintensitet upplevd för respektive fototransistor som sitter under den lilla biten eltejp framtill. Det är alltså bara de relativa nivåerna som är intressanta, inte de absoluta så den är inte speciellt känslig i sitt beteende beroende på hur ljust det är i rummet. D delen lägger sedan dels till extra tid hög på den sida som den är på väg mot och dels tar den bort delar av P delen ifall D är för stor. Dvs den går långsammare totalt sett (summan av pulskvot till motorerna) om det svänger mycket. Denna biten är dock inte helt färdigimplementerad så där ska finnas utrymme att köra lite snabbare. Annars är jag nere på 12s varv nu och har uppdaterat med snabbare film på Youtube. Ber om ursäkt för att diino ibland når gränsen så bilderna inte funkar.

Hoppas jag besvarade frågorna.

mvh
Senast redigerad av övrigt 2 juni 2008, 03:28:54, redigerad totalt 1 gång.
DupeS
Inlägg: 90
Blev medlem: 30 september 2003, 18:27:39
Ort: Linköping

Inlägg av DupeS »

Törs man fråga om du kan dela med dig av koden?
vore intressant och se hur du har gjort.
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Hade inte funderat över det innan så fick tänka till lite. Men visst delar av koden släpper jag gärna. Versionen här är hela första utkastet till PD regulatorn. Dvs den saknar lite konstanter samt vissa av funktionerna nämnda ovan. Men det är den koden jag jobbat vidare med och det är inte helt svårt att lägga till delar själv.

Jag är medveten om att jag är långt ifrån att utnyttja processorn fullt ut och att mycket kan finslipas för att göras snabbare, jämnare mm. Men detta funkar :) , se senaste filmen om ni inte tror mig. Garanterar inte att allt är 100% ok, men det borde vara det.

Förresten vad är praxis för kod på forumet? Att kopiera in den i inlägget eller att länka till den som med bilder? Lägger in det här så länge, för beständighetens skull om inte annat, så får ni rätta mig.

Men kommentera gärna koden. Även om mycket inte är optimalt så är det ”tillräckligt” för mitt projekt. Men fler projekt kommer ju at följa detta så tips är välkomna. Nästa projekt kommer att bli någon slags inverterad pendel, vilken kanske kan kräva lite uppstramning av koden.

Förresten, har jag förstått det rätt att programmet i någon mening liknar hur en PLC fungerar?

Håll tillgodo.

Kod: Markera allt


;This is the fourth level of the Line follower. The robot is 
;now able to follow a line of black duct tape somewhat fast and is nicely  
;stable. In this v1.1 a PD regulator is implemented. Hardware is somewhat 
;bad design, but software brings the total up. 

;Port configuration. Port C is input from phototransistors: PC0 to left 
;and PC1 to right. ;Port B is pwm output to motors ac to: PB0 left motor 
;(reg OutPwmL) and PB1 to right motor (reg OutPwmR). 
;For ATmega88
.include "m88def.inc"
.def Speed =r16	;	;Contains the speed provided by P part, change in Scale. 
.def OutPwmL = r17	;Contains the time high for left motor. 
.def OutPwmR = r21	;Contains the time high for right motor. 
.def I =r18 		;Loop (delay) variables. 
.def J = r19
.def Temp = r20		;Temporary registers, may be destroyed by subroutines. 
.def Temp2 = r22
.def OutMotor = r23	;The register to send out to motors. 
.def Error = r24 	

RESET:
ser Temp
out DDRD,Temp		;
ldi Temp,3			;Set ports. 
out DDRB,Temp
ldi Temp, low(RAMEND)
out SPL, Temp
ldi Temp, high(RAMEND)
out SPH, Temp		;Stack pointer set. 
ldi XH,0x01
ldi XL,0x00			;Used for SRAM access. 

cbi PRADC,0			;Turn power saving device of. 

ldi Temp,0b00100000	;Uses ADLAR, and start to read left. 
sts ADMUX,Temp		;tell ATmega. 
ldi Temp,0b10000000
sts ADCSRA,Temp		;Enable ADC. 


MAIN:
rcall Get_Analog

rcall Scale		
rcall MAKE_CYCLE

rjmp MAIN



;**************************** Subroutines ****************************
;Destroyes Temp registers. 



GET_ANALOG:
;Returns the  analog value on PC0..1 to digital 8 bit
;values in reg OutPwmL and OutPwmR resp. 

ldi Temp,0b00100000	;This reads the PC0.  
sts ADMUX,Temp		;Set mux to read left phototr, on PC0. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion. 
sts ADCSRA,Temp

WAIT_L:				;Wait for conversion to finish. 
sbic ADIF,4			;"ADIF,4" and "ADSC,6" will work with short delay after. 
rjmp WAIT_L 

rcall ANALOG_DLY	;Needed. 

lds OutPwmL,ADCH

;* Left value done, get right. 

ldi Temp,0b00100001	;Read PC1. 
sts ADMUX,Temp		;Set mux to read right phototr, on PC1. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion on PC1. 
sts ADCSRA,Temp

WAIT_R:
sbic ADIF,4			;"ADIF,4" and "ADSC,6" will work with short delay after. 
rjmp WAIT_R

rcall ANALOG_DLY	;Must have this. 

lds OutPwmR,ADCH

ret


;*************************************************************************


Scale:
;This routine maps the values in reg OutPwmL/R into other values in 
;the same registers to those better suited for control of the Line follower. 
;The PD regulator is within this function. 

ldi XL,00		;SRAM-pointer. 

ld Temp,X+		;Last value from ADC, L. 
ld Temp2,X+		;Last value from ADC, R. 

;*** First get D-part. Must not alter OutPwm registers, so push them. 

push OutPwmL
push OutPwmR

sub Temp2,Temp		;= last (R-L)
mov Error,OutPwmR
sub Error,OutPwmL	;= present (R-L)
sub Error,Temp2		;= present(R-L) - last(R-L)

brcs D_NEGATIVE

;*** Robot moves to right if gets here.

mov Temp2,Error	;:More speed to right. 
inc Temp2
ldi Temp,0		;Dont increase left motors speed 

rjmp D_DONE

D_NEGATIVE:

neg Error
;*** The robot moves to the left if gets here, inc left. 
mov Temp,Error
inc Temp
ldi Temp2,0		;Dont boost right motor. 


D_DONE:
;* First restore registers and update SRAM. 
pop OutPwmR
pop OutPwmL
st -X,OutPwmR	;Store present value from ADC before change them. 
st -X,OutPwmL

com Error
out PORTD,Error	;Debugging reason
com Error

;*** And now get P-part, the same as original way. 

ldi Speed,50	;Speeds 40-50 for small track, may be greater for larger. 

cp OutPwmR,OutPwmL
brcs GO_MORE_RIGHT		;Branch if L > R

;* Go more left: OutPwmR > OutPwmL from ADC, so increase right hand side pw. 

mov Error,OutPwmR
sub Error,OutPwmL	;=R-L > 0

dec Speed
cp Error,Speed
brcs LEFT_WITHIN	;Put upper bound on error since pw is bounded. 
mov Error,Speed

LEFT_WITHIN:
inc Speed

mov OutPwmL,Speed
mov OutPwmR,Speed
add OutPwmR,Error
sub OutPwmL,Error

rjmp SCALE_RETURN

GO_MORE_RIGHT: 		;Increase left hand side motors pw. 

;*Know that OutPwmL > OutPwmR

mov Error,OutPwmL
sub Error,OutPwmR ;=L-R > 0

dec Speed
cp Error,Speed
brcs RIGHT_WITHIN	;Put upper bound on error since pwm is bounded. 
mov Error,Speed

RIGHT_WITHIN:
inc Speed

mov OutPwmL,Speed
mov OutPwmR,Speed
add OutPwmL,Error
sub OutPwmR,Error 

SCALE_RETURN:
add OutPwmL,Temp	;Adjust from D part last. 
add OutPwmR,Temp2
ret


;******************************************************************


MAKE_CYCLE:
;Makes one duty cycle for both motors. Time high is in reg OutPwmL/R. 

push J
ldi J,6			;Dly for D part of regulator, etc. 

NBR_CYCLES:

push I
clr I			;Full cycle

ldi OutMotor,0b00000011	;Set high

mov Temp, OutPwmL
mov Temp2,OutPwmR
inc Temp		;To get zero right. 
inc Temp2

MAKE_CYCLE_RET:	;This is the loop itself

dec Temp
breq C_L		;If zero, then clear LED
LAT1:
dec Temp2
breq C_R
LAT2:

rcall PWM_DLY	;Use to change pwm frequency. 
out PORTB,OutMotor

dec I			;Sets the cycle
brne MAKE_CYCLE_RET
pop I
dec J
brne NBR_CYCLES
pop J
ret



;*************** TEMPORARY ROUTINES ***********
;Belongs to MAKE_CYCLE. 



C_L:
rcall C_Lt
rjmp LAT1

C_Lt:						;Clear Left 
andi OutMotor,0b00000010	;Possibly keep right high. 
ret

C_R:
rcall C_Rt
rjmp LAT2

C_Rt:
andi OutMotor,0b00000001	;Possibly keep left high. 
ret



;*************** DELAY ROUTINES ****************



ANALOG_DLY:
push J
ldi J,0x05
ANALOG_DLY_T:
dec J
brne ANALOG_DLY_T
pop J
ret

PWM_DLY:
push J
ldi J,0x05
PWM_DLY_T:
dec J
brne PWM_DLY_T
pop J
ret

mvh
DupeS
Inlägg: 90
Blev medlem: 30 september 2003, 18:27:39
Ort: Linköping

Inlägg av DupeS »

Tack
ska kolla lite närmmare på koden när jag har lite mera tid,
nu kan jag inte säga att jag är någon fena på pd direkt, men har varit intresserad att gör en egen så det är intressant och se hur man kan göra.
Skriv svar