14.01.2015 Views

Teknisk dokumentation

Teknisk dokumentation

Teknisk dokumentation

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Linköpings tekniska högskola 2003-12-09<br />

Institutionen för systemteknik (ISY)<br />

<strong>Teknisk</strong> <strong>dokumentation</strong><br />

Platon – en härligt gul sexbent robot<br />

Projektgrupp 15 – Jessica Heyman<br />

Version 1.1<br />

Granskad<br />

Godkänd<br />

Status<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 1


Platon<br />

2003-12-09<br />

PROJEKTIDENTITET<br />

Projektgrupp 15 – Platon<br />

Linköpings tekniska högskola, ISY<br />

Gruppdeltagare<br />

Namn Ansvar Telefon E-post<br />

Johan Rees Projektledare 070 – 249 91 52 johre469@student.liu.se<br />

David Landén Dokumentansvarig 013 – 473 18 18 davla185@student.liu.se<br />

Pia Fåk Designansvarig, hårdvara 073 – 698 68 78 piafa456@student.liu.se<br />

Jessica Heyman Leveransansvarig 070 – 391 83 14 jeshe852@student.liu.se<br />

Mattias Lennartsson Testansvarig 073 – 767 12 15 matle017@student.liu.se<br />

Johan Mårtenson Designansvarig, mjukvara 073 – 931 98 96 johma196@student.liu.se<br />

E-postlista för hela gruppen martenson+stalin@lysator.liu.se<br />

Kund Tomas Svensson<br />

Kursansvarig Tomas Svensson, Olle Seger<br />

Handledare Anders Nilsson<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 2


Platon<br />

2003-12-09<br />

Innehåll<br />

1 INLEDNING .............................................................................................................................................. 5<br />

1.1 Tidigare dokument............................................................................................................................ 5<br />

1.2 Definitioner ...................................................................................................................................... 5<br />

2 ÖVERSIKT AV SYSTEMET................................................................................................................... 6<br />

2.1 Fysisk uppbyggnad........................................................................................................................... 6<br />

2.2 Ingående moduler ............................................................................................................................. 6<br />

2.2.1 Kommunikation mellan moduler ........................................................................................... 7<br />

3 FJÄRRSTYRNINGSENHET ................................................................................................................... 7<br />

3.1 Inledande beskrivning av fjärrstyrningsenheten ............................................................................... 7<br />

3.2 Mjukvara .......................................................................................................................................... 8<br />

3.2.1 Signal från IR-detektor........................................................................................................ 10<br />

3.2.2 Signal från tryckknapp ........................................................................................................ 11<br />

3.3 Kommunikation.............................................................................................................................. 11<br />

3.3.1 Informationsöverföring inom fjärrstyrningsenheten ........................................................... 11<br />

3.3.2 Gränssnitt mot andra enheter.............................................................................................. 12<br />

3.4 Störningar ....................................................................................................................................... 12<br />

4 STYRENHET........................................................................................................................................... 12<br />

4.1 Inledande beskrivning av styrenheten............................................................................................. 12<br />

4.2 Mjukvara ........................................................................................................................................ 13<br />

4.2.1 Styrlogik .............................................................................................................................. 13<br />

4.2.2 Steglogik.............................................................................................................................. 16<br />

4.3 Kommunikation.............................................................................................................................. 17<br />

4.3.1 Informationsöverföring inom styrenheten ........................................................................... 17<br />

4.3.2 Gränssnitt mot andra enheter.............................................................................................. 18<br />

5 SENSORENHET ..................................................................................................................................... 19<br />

5.1 Inledande beskrivning av sensorenheten ........................................................................................ 19<br />

5.2 Mjukvara ........................................................................................................................................ 19<br />

5.2.1 Sensorer............................................................................................................................... 20<br />

5.3 Gränssnitt mot andra enheter.......................................................................................................... 20<br />

5.3.1 Insignaler ............................................................................................................................ 20<br />

5.3.2 Utsignaler............................................................................................................................ 21<br />

5.3.3 Signalprioritet ..................................................................................................................... 22<br />

5.3.4 Display ................................................................................................................................ 22<br />

5.4 Sensorer.......................................................................................................................................... 22<br />

5.4.1 Hårdvara............................................................................................................................. 22<br />

5.4.2 Namngivning ....................................................................................................................... 22<br />

6 ANVÄNDARHANDLEDNING.............................................................................................................. 23<br />

7 REFERENSER ........................................................................................................................................ 24<br />

Bilagor<br />

1 Hårdvarulista<br />

A1 Kretsschema för fjärrstyrningsenheten<br />

B1 Kretsschema för styrenheten<br />

C1 Kretsschema för sensorenheten<br />

A2 Assemblerkod för fjärrstyrningsenheten<br />

B2 Assemblerkod för styrenheten<br />

C2 Assemblerkod för sensorenheten<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 3


Platon<br />

2003-12-09<br />

Dokumenthistorik<br />

Version Datum Förändringar från föregående version Utförda av Granskad<br />

0.1 2003-12-01 Första utkast Jessica Heyman Pia Fåk,<br />

Johan Rees,<br />

David Landén<br />

1.0 2003-12-05<br />

Ny programkod för styr- och sensorenhet<br />

Förtydliganden och layoutkorrigeringar<br />

Jessica Heyman<br />

Pia Fåk<br />

1.1 2003-12-09<br />

Tillägg av bild på framsida, i inledning och i<br />

avsnitt 2.2.1<br />

Jessica Heyman<br />

Rättning av småfel<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 4


Platon<br />

2003-12-09<br />

1 Inledning<br />

På uppdrag av beställaren Tomas Svensson har vi i projektgrupp 15, Platon, konstruerat en<br />

liten sexbenig robot som återfinns i figur 1.1. Denna kan styras manuellt med fjärrkontroll,<br />

men kan också autonomt ta sig genom en labyrint hjälp av ultraljudssensorer.<br />

Detta dokument beskriver i detalj hur vår robot är konstruerad och hur den ska användas. I<br />

avsnitt två ges en översiktlig bild av roboten, som följs av detaljerna i de tre ingående<br />

modulerna fjärrstyrning, styrning och sensorer i avsnitt tre, fyra respektive fem. I anslutning<br />

till modulbeskrivningarna förklaras också hur de olika modulerna kommunicerar med<br />

varandra. Slutligen finns en användarmanual till konstruktionen i avsnitt sex.<br />

Figur 1.1 Fotografi på Platon – en härligt gul sexbent robot.<br />

1.1 Tidigare dokument<br />

Inom ramen för projekt Platon har vi tidigare tagit fram en kravspecifikation, en<br />

systemskiss och en designspecifikation. Detaljer om samtliga återfinns i referenslistan<br />

i slutet av denna <strong>dokumentation</strong>.<br />

1.2 Definitioner<br />

Följande begrepp används i detta dokument:<br />

Platon, roboten<br />

autonomt läge<br />

den sexbeniga robot vi har konstruerat<br />

det läge då Platon utan hjälp från användaren hittar rätt<br />

väg genom en labyrint.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 5


Platon<br />

2003-12-09<br />

2 Översikt av systemet<br />

Detta avsnitt behandlar roboten som helhet: dess huvudsakliga delar och grovt deras<br />

gränssnitt mot varandra.<br />

2.1 Fysisk uppbyggnad<br />

Robotens grundbyggsten är ett robotskelett som har sex styrbara ben och rörligt<br />

huvud. På robotens kropp sitter ett virkort, där alla komponenter som behövs för<br />

manövrering och navigation har fästs. Virkortet matas med 7.5 V spänning från sex<br />

uppladdningsbara batterier som ligger mellan robotkroppen och virkortet.<br />

Figur 2.1 Blockschema: översiktlig vy av systemet.<br />

2.2 Ingående moduler<br />

Roboten Platon är uppbyggd av tre moduler:<br />

• Fjärrstyrningsenhet som gör det möjligt för användaren att ge styrkommandon<br />

till roboten med hjälp av en fjärrkontroll.<br />

• Styrenhet som med hjälp av kommandon från de övriga enheterna styr benen så<br />

att roboten rör sig åt rätt håll.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 6


Platon<br />

2003-12-09<br />

• Sensorenhet som känner av robotens omgivning och skickar information om<br />

denna till styrenheten.<br />

Modulerna beskrivs mer ingående i avsnitt tre, fyra respektive fem.<br />

2.2.1 Kommunikation mellan moduler<br />

Informationsöverföring sker enbart mellan sensor- och styrenhet samt mellan<br />

fjärrstyrnings- och styrenhet.<br />

Mellan sensor- och styrenhet sker dubbelriktad kommunikation med fyra bitar<br />

till styrenheten från sensorenheten och två bitar från styr- till sensorenhet enligt<br />

figur 2.2. Med hjälp av dessa bitar skickar sensorenheten information till<br />

styrenheten om nödvändiga riktningskorrigeringar eller om en korsning hittats,<br />

och i så fall även vilken typ av korsning det rör sig om. Utförligare beskrivning<br />

finns i avsnitt 4.3.<br />

styrenhet<br />

sensorenhet<br />

Figur 2.2 Mellan styr- och sensorenhet skickas två bitar från styrenheten till<br />

sensorenheten och fyra bitar åt andra hållet.<br />

Mellan fjärrstyrningsenheten och styrenheten sker enbart enkelriktad<br />

informationsöverföring. Med virade kopplingstrådar skickar<br />

fjärrstyrningsenheten fyra bitar till styrenheten, där tre bitar kodar för ett<br />

kommando och den fjärde är en strobe som anger att fjärrstyrningsenheten<br />

skickar en ny signal. Vidare beskrivning av de tre informationsbitarna och när<br />

stroben läggs på finns i avsnitt 3.4.2.<br />

Sammanfattningsvis har alla tre moduler mycket enkla gränssnitt, vilket gör att<br />

de enkelt kan bytas ut.<br />

3 Fjärrstyrningsenhet<br />

3.1 Inledande beskrivning av fjärrstyrningsenheten<br />

Då roboten inte är i autonomt läge, kan den styras manuellt med en enkel fjärrkontroll.<br />

En användare kan då ge följande kommandon:<br />

• gå framåt<br />

• gå bakåt<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 7


Platon<br />

2003-12-09<br />

• sväng höger<br />

• sväng vänster<br />

• stanna<br />

• autonomt läge på/av<br />

• ljudsignal<br />

Fjärrkontrollen sänder ut IR-signaler till roboten enligt fjärrkontrollens i förhand<br />

inställda protokoll. IR-detektorn tar emot dessa signaler och omvandlar dem till<br />

elektriska signaler, som skickas till signalbehandlingsenheten. Till denna enhet<br />

kommer också en signal från en tryckknapp som används för i- och urkoppling av<br />

autonomt läge. De inkomna signalerna tolkas i signalbehandlingsenheten och då<br />

roboten inte är i autonomt läge skickas de vidare till styrenheten i form av<br />

styrkommandon i samtliga fall utom då den mottagna signalen beskriver<br />

användarkommandot ”ljudsignal”. Då användaren ger kommandot ”ljudsignal” tutar<br />

signalbehandlingsenheten nämligen själv med summern, utan att styrenheten är<br />

inblandad.<br />

När signalbehandlingsenheten tar emot kommandot ”autonomt läge på/av”, antingen<br />

via tryckknapp eller fjärrkontroll, kommer även en lysdiod att tändas eller släckas<br />

(beroende på om läget slås av eller på) samtidigt som ett kommando skickas till<br />

styrenheten.<br />

Alla komponenter finns närmare beskrivna i bilaga 1 och hur de är anslutna till<br />

varandra illustreras i bilaga A1.<br />

Figur 3.1 Översiktlig vy över fjärrstyrningsenheten.<br />

3.2 Mjukvara<br />

För att kunna ta emot signaler, tolka dessa, sända ut styrkommandon samt styra<br />

lysdiod och summer, krävs förstås mjukvara i mikrokontrollern. Dess funktion är<br />

schematiskt illustrerad i figur 3.1 och beskriven nedan, medan den fullständiga<br />

assemblerkoden återfinns i bilaga A2.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 8


Platon<br />

2003-12-09<br />

Figur 3.2 Flödesschema för fjärrstyrningsenheten.<br />

Efter en kort initieringssekvens som konfigurerar portar och olika avbrott, väntar<br />

mikrokontrollern i en loop. Denna loop kan avbrytas av två saker: en fallande flank på<br />

insignalen från IR-detektorn eller en ändring av insignalen från tryckknappen. Nästan<br />

all signalbehandling sker således i avbrottsrutiner, men då mikrokontrollern är så pass<br />

snabb i förhållande till hur mycket data den ska behandla är detta inget problem.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 9


Platon<br />

2003-12-09<br />

3.2.1 Signal från IR-detektor<br />

Då användaren trycker på en knapp på fjärrkontrollen, kommer ett pulståg från<br />

IR-detektorn in till signalbehandlingsenheten. Beroende på vilken knapp<br />

användaren har tryckt på har detta pulståg olika utseende enligt tabell 3.1.<br />

Knapp<br />

Bitmönster<br />

gå framåt 00T11111 001010<br />

gå bakåt 00T11111 001111<br />

sväng höger 00T11111 001011<br />

sväng vänster 00T11111 001101<br />

stanna/filosofera 00T11111 001001<br />

autonomt läge på/av 00T11111 110011<br />

ljudsignal 00T11111 001000<br />

T står för toggle-bit och ett mellanrum mellan meta- och signaldata har lagts till<br />

för tydlighet<br />

Tabell 3.1 Bitmönster för IR-signaler sedan de konverterats till digitala signaler.<br />

De elektriska signalerna genererar ett avbrott, som i sin tur startar en timer (i<br />

subrutinen IRKOM) och konfigurerar mikrokontrollern att lyssna efter denna<br />

timers avbrott. Ungefär en åttondel in i perioden för nästkommande bit hos den<br />

inkommande signalen ger den satta timern ett avbrott, och dess avbrottsrutin<br />

(TMRAVB) börjar exekvera. Denna bestämmer först med hjälp av två inre<br />

räknare, en för metadata och en för signaldata, vilket av dessa den inkommande<br />

biten hör till och lagrar signalens värde i korresponderande register. Därefter<br />

kollar den om det var den sista biten i signalen som just mottogs, i vilket fall<br />

den anropar en subrutin som kollar om signalen är giltig (SIGKOLL) och i så<br />

fall skickar den om roboten inte är i autonomt läge med hjälp av en annan<br />

subrutin (SKICKA). I annat fall sätter den om timern för att generera ett nytt<br />

avbrott då nästa bit ligger på ingången.<br />

En signal bedöms som giltig om dess metadata är korrekt och dess signaldata<br />

motsvarar koden för en knapp som mikrokontrollern lyssnar efter. Metadata är<br />

korrekt om det består av – i tur och ordning – två nollor som är synkbitar, en<br />

togglebit med godtyckligt värde och till sist fem ettor, allt enligt<br />

fjärrkontrollens inställda protokoll (se bilaga 1). De signaldata som<br />

mikrokontrollern anser giltiga utgörs av de sex sista bitarna i tabell 3.1, det vill<br />

säga de knappspecifika koderna för de knappar som används för att ange ”gå<br />

framåt”, ”gå bakåt”, ”sväng höger”, ”sväng vänster”, ”stanna”, ”autonomt läge<br />

på/av” och ”ljudsignal”.<br />

Då en signal som mottagits från IR-detektorn bedömts som giltig, skickar<br />

fjärrstyrningenheten signaler till styrenheten, dioden och summern enligt<br />

tabell 3.2.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 10


Platon<br />

2003-12-09<br />

Användarkommando<br />

Autonomt läge på<br />

Åtgärd<br />

Autonomt läge av<br />

gå framåt ingen skicka 001 till styrenheten<br />

gå bakåt ingen skicka 010 till styrenheten<br />

sväng höger ingen skicka 011 till styrenheten<br />

sväng vänster ingen skicka 100 till styrenheten<br />

stanna/filosofera ingen skicka 101 till styrenheten<br />

autonomt läge på/av<br />

byt till tillstånd ”autonomt läge av”<br />

släck lysdiod<br />

skicka 000 till styrenheten<br />

byt till tillstånd ”autonomt läge på”<br />

tänd lysdiod<br />

skicka 000 till styrenheten<br />

ljudsignal tuta! (signal till summern) tuta! (signal till summern)<br />

Tabell 3.2 Kommandon med bitmönster från fjärrstyrningsenheten.<br />

De åtgärder som mikrokontrollern utför kommer enligt ovanstående tabell att<br />

vara olika beroende på vilket tillstånd roboten befinner sig i (autonomt läge på<br />

eller av) och vilket kommando det är frågan om. Eftersom autonomt läge<br />

enbart kan slås på och av via fjärrstyrningsenheten har denna en inre<br />

tillståndsvariabel, onoff i registret statreg, som alltid berättar om roboten<br />

befinner sig i autonomt läge eller inte. Denna variabel används då<br />

signalbehandlingsenheten ska bestämma vad som ska skickas: om roboten är<br />

autonom ska enbart kommandona autonomt läge på/av samt tuta göra att ett<br />

kommando skickas, medan alla giltiga signaler gör att ett kommando skickas<br />

till antingen styrenheten eller tutan då autonomt läge är avslaget.<br />

3.2.2 Signal från tryckknapp<br />

Den tryckknapp som finns monterad på virkortet har samma funktion som<br />

knappen ”autonomt läge på/av” på fjärrkontrollen. Robotens autonoma läge<br />

kan således stängas av via fjärrkontrollen för att sedan sättas på med<br />

tryckknappen, och vice versa.<br />

Då tryckknappen trycks ner genereras ett avbrott, som tas om hand i en<br />

avbrottsrutin (TRYCKAVB). Denna gör precis samma sak som rutinen SIGKOLL<br />

då insignalen från IR-detektorn kodat för ”autonomt läge på/av”, det vill säga<br />

släcker eller tänder lysdioden, togglar det inre tillståndet och skickar<br />

kommandot ”autonomt läge på/av” till styrenheten.<br />

3.3 Kommunikation<br />

3.3.1 Informationsöverföring inom fjärrstyrningsenheten<br />

Mellan fjärrkontroll och IR-mottagare sker överföring av data med hjälp av IRsignaler<br />

och mellan IR-mottagare och signalbehandlingsenhet finns enkla<br />

kopplingstrådar. De IR-signaler som, sedan de konverterats till elektriska<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 11


Platon<br />

2003-12-09<br />

signaler av IR-detektorn, bedöms som giltiga av signalbehandlingsenheten<br />

finns i tabell 3.1.<br />

Också tryckknapp, diod, samt summer är anslutna till signalbehandlingsenheten<br />

på enklast möjliga sätt; direkt till ett ben på signalbehandlingsenheten.<br />

3.3.2 Gränssnitt mot andra enheter<br />

Fjärrstyrningsenheten kommunicerar enkelriktat med styrenheten genom virade<br />

kopplingstrådar. Informationsöverföringen består av fyra bitar, där tre av dessa<br />

utgör en binär kodning för sex olika kommandon som användaren kan ge<br />

roboten via fjärrkontrollen enligt tabell 3.2.<br />

Då fjärrenheten mottagit en signal från användaren, läggs aktuellt kommando<br />

på tre trådar till styrenheten, och precis därefter ges en strobe på den fjärde<br />

tråden. Stroben genererar ett avbrott i styrenheten, som då läser av de tre andra<br />

trådarna. Dessa tre trådar behåller sitt värde mellan det att två kommandon<br />

skickas, men då ingen ny strobe ges kommer inte styrenheten att läsa av dem<br />

och deras värde är således ointressant. Pinnummer för de tre<br />

informationsbitarna och stroben återfinns i bilaga A1.<br />

3.4 Störningar<br />

I vanliga miljöer finns IR-ljus som ibland genererar en puls från IR-detektorn. Denna<br />

puls sätter igång signalavkodningen i fjärrstyrningsenheten precis som en giltig signal<br />

från fjärrkontrollen, men sannolikheten är mycket låg att en störning ska ha samma<br />

värden som en giltig signal vid samtliga tider då signalen avläses. Sannolikheten finns<br />

dock, och därför skickar aldrig fjärrstyrningsenheten iväg något kommando till<br />

styrenheten såvida den inte tagit emot samma signal från IR-detektorn två gånger i rad.<br />

Då varje knapptryckning på fjärrkontrollen oftast genererar fler än tre upprepningar av<br />

knappens IR-signal, påverkar inte detta handhavandet av fjärrkontrollen utan är bara<br />

en extra felkontroll.<br />

Även om mikrokontrollerna inte kommer att skicka några signaler till styrenheten, sin<br />

diod eller sin tuta på grund av störningar, leder dessa dock till att mikrokontrollern<br />

sätter igång inläsningen av en signal och läser in tretton bitar. Detta gör att användaren<br />

ibland måste upprepa sin knapptryckning för att roboten ska reagera i en miljö med<br />

mycket störningar.<br />

4 Styrenhet<br />

4.1 Inledande beskrivning av styrenheten<br />

Styrenhetens uppgift är att ta emot signaler från fjärrstyrningsenheten samt<br />

sensorenheten och därefter bestämma hur roboten ska gå och röra benen på ett sådant<br />

sätt att roboten förflyttar sig på önskat sätt. Enheten kan befinna sig i fjärrstyrt eller<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 12


Platon<br />

2003-12-09<br />

autonomt läge och läser då information från fjärrstyrningsenheten respektive<br />

sensorenheten.<br />

För att få en enkel och tydlig uppdelning inom modulen används två kretsar. En,<br />

kallad steglogik, som genom tre servon kontrollerar benens rörelser och en, kallad<br />

styrlogik, som hanterar vägval samt kommunikation med de andra modulerna.<br />

Uppdelningen bör framgå tydligt ur figur 4.1.<br />

Fjärrstyr Styrlogik Sensor<br />

Steglogik<br />

Servo 1 Servo 2 Servo 3<br />

Ben<br />

VF, VB<br />

Ben<br />

VM, HM<br />

Ben<br />

HF, HB<br />

Figur 4.1 Interface mellan de olika delarna av styrenheten. VF, HM… står för Vänster Fram,<br />

Höger Mitten och så vidare.<br />

4.2 Mjukvara<br />

4.2.1 Styrlogik<br />

Styrenheten kan befinna sig i två olika lägen; autonomt eller fjärrstyrt.<br />

Mjukvaran är uppbyggd av en loop enligt figur 4.2. En gång i varje varv i<br />

denna loop kontrolleras vilket av lägena enheten befinner sig i.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 13


Platon<br />

2003-12-09<br />

Figur 4.2 Flödesschema över styrenheten (se tabell 4.4 för förklaring av signalerna A1<br />

och A2).<br />

Då styrenheten befinner sig i fjärrstyrt läge skickas det kommando som läses in<br />

från fjärrstyrningsenheten vidare till steglogiken som sedan gör att roboten går<br />

på motsvarande sätt.<br />

Då styrenheten befinner sig i autonomt läge läses signaler från sensorenheten.<br />

Dessa signaler kan vara av tre typer:<br />

• ingen korrigering behövs<br />

• korrigering behövs<br />

• korsning hittad<br />

Då ingen korrigering behövs fortsätter roboten rakt fram. Om korrigering<br />

behövs utförs denna. Korrigeringen kan vara av två olika typer enligt figur 4.3<br />

och enligt<br />

• sväng höger<br />

• sväng vänster<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 14


Platon<br />

2003-12-09<br />

Figur 4.3 Förklaring av riktningskorrigeringarna: höger/vänster.<br />

Då korsning hittats kommer sensorenheten senare även skicka signaler om<br />

vilken typ av korsning det är. Mer om detta i avsnitt 4.3.2.2. De olika<br />

korsningstyperna återfinns i figur 4.4.<br />

Figur 4.4 Sju korsningstyper.<br />

Den algoritm med vilken roboten autonomt ska ta sig genom labyrinten är<br />

mycket enkel. Roboten följer alltid labyrintens högerkant, vilket betyder att<br />

den förr eller senare alltid kommer till målet. Tabellen nedan visar vilken<br />

åtgärd som vidtas vid de olika typerna av korsningar för att åstadkomma denna<br />

algoritm.<br />

Korsningstyp<br />

vänstersväng<br />

högersväng<br />

T-korsning<br />

framåt-höger korsning<br />

framåt-vänster korsning<br />

återvändsgränd<br />

fyrvägskorsning<br />

mål<br />

Åtgärd<br />

sväng vänster<br />

sväng höger<br />

sväng höger<br />

sväng höger<br />

gå rakt fram<br />

vänd 180 o<br />

sväng höger<br />

stanna<br />

Tabell 4.1 Åtgärder vid de åtta olika korsningstyperna.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 15


Platon<br />

2003-12-09<br />

4.2.2 Steglogik<br />

Steglogiken tar emot signaler från styrlogiken och skickar sedan ut<br />

pulsbreddsmodulerande signaler, PWM-signaler, till de tre servona som i sin<br />

tur får benen att röra på sig på motsvarande sätt. Steglogiken är programmerad<br />

att utföra 11 olika rörelser enligt tabell 4.2.<br />

Rörelse Används i läge Kodning<br />

stanna fjärr/auto 0000<br />

gå framåt fjärr/auto 0001<br />

gå bakåt fjärr 0010<br />

sväng vänster fjärr 0011<br />

sväng höger fjärr 0100<br />

snurra vänster 0101<br />

parallellförflyttning höger auto 0110<br />

parallellförflyttning vänster auto 0111<br />

snurra höger 1000<br />

snurra 90 o höger auto 1001<br />

snurra 90 o vänster auto 1010<br />

Tabell 4.2 Steglogikens olika rörelser. De rörelser som inte används av någon modul<br />

är endera till för testsyfte eller används för att utföra de andra rörelserna.<br />

Dessa förflyttningar använder sig i sin tur av följande sex subrutiner:<br />

Subrutin<br />

höger upp<br />

vänster upp<br />

höger fram<br />

vänster fram<br />

höger bak<br />

vänster bak<br />

Beskrivning<br />

höger sida av roboten pressas upp från marken<br />

vänster sida av roboten pressas upp från marken<br />

både det främre och det bakre benet på höger sida flyttas till sitt<br />

främre läge.<br />

både det främre och det bakre benet på vänster sida flyttas till sitt<br />

främre läge<br />

båda benen på höger sida flyttas bak<br />

båda benen på vänster sida flyttas bak<br />

Tabell 4.3 Steglogikens sex subrutiner.<br />

Tack vare denna abstraktion fås lätt en bra överblick över koden och det är lätt<br />

att lägga till nya rörelsemönster.<br />

Servona fungerar på så sätt att en pulsbreddsmodulerad signal med perioden<br />

20 ms och pulslängd mellan 0,5 och 2,5 ms anger servots läge. Förflyttning<br />

mellan ändlägena motsvarar en vridning av servot på ungefär 180 o . För att<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 16


Platon<br />

2003-12-09<br />

ställa servot i ena ändläget måste alltså en 0,5 ms lång puls skickas upprepade<br />

gånger med periodtiden 20 ms, enligt figur 4.5.<br />

Figur 4.5 Servots läge beroende på den pulsbreddsmodulerade signalen.<br />

Då det räcker att roboten kan flytta benen mellan de båda ändlägena kodar vi<br />

PWM-signalen så att den endast kan ha två diskreta pulslängder, motsvarande<br />

de båda ändlägena. I kretsen använder vi två räknare som räknar upp från 0 till<br />

255. De båda räknarna genererar avbrott vid något värde X, samt vid<br />

maxvärdet 255. För räknare nummer 1 är X lika med 243 och för räknare 2 är<br />

det 253. På så sätt skapar vi 2 PWM-signaler, som figur 4.6 visar. Dessa<br />

signaler har de båda önskade pulslängderna och kan därmed ställa servona i de<br />

båda ändlägena.<br />

Figur 4.6 Den pulsbreddsmodulerade signalens utseende beroende på räknarens<br />

X-värde.<br />

Nu behöver vi alltså bara ange vilken av de båda PWM-signalerna som skall<br />

skickas till vilket servo. Detta gör vi genom att sätta eller nollställa tre register<br />

som svarar mot de tre servona. Dessa register ändras sedan av subrutinerna i<br />

tabell 4.3. På så sätt rör roboten på benen och kan gå.<br />

4.3 Kommunikation<br />

4.3.1 Informationsöverföring inom styrenheten<br />

Det inre gränssnittet i styrenheten är en enkelriktad trebitars kommunikation<br />

från styrlogiken till steglogiken. Styrlogiken skickar ständigt någon av de elva<br />

signalerna i tabell 4.2. För varje varv i steglogikens huvudloop läses signalerna<br />

in och motsvarande rörelse utförs.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 17


Platon<br />

2003-12-09<br />

4.3.2 Gränssnitt mot andra enheter<br />

4.3.2.1 Fjärrstyrningsenhet–styrenhet<br />

Fjärrstyrningsenheten skickar signaler till styrenheten enligt tabell 3.2. Dessa<br />

signaler läses sedan in av styrenheten på varje nedåtgående flank på den strobe<br />

som finns mellan fjärrstyrning- och styrenheten. När signalen från<br />

fjärrstyrningsenheten till styrenheten är 000 byter styrenheten mellan fjärrstyrt<br />

och autonomt läge, enligt avsnitt 4.2.1. I fjärrstyrt läge lyssnar styrenheten av<br />

alla fjärrstyrningsenhetens signaler och agerar utifrån dessa. I autonomt läge<br />

lyssnar enheten dock endast efter signalen 000 – autonomt läge på/av.<br />

4.3.2.2 Sensorenhet–styrenhet<br />

Kommunikationen mellan sensorenheten och styrenheten består av två bitar<br />

från styrenheten till sensorenheten samt fyra bitar åt det motsatta hållet. Tabell<br />

4.4 förklarar betydelsen av de olika bitarna.<br />

Bit Betydelse Riktning<br />

A1 leta efter korsning och behov av korrigering från styrenhet<br />

A2 roboten befinner sig i en korsning som ska undersökas från styrenhet<br />

B1<br />

typ av signal som skickas<br />

1 betyder korrigeringstyp<br />

0 betyder korsningstyp<br />

till styrenhet<br />

B2 – B5 kod för korrigeringstyp eller korsningstyp till styrenhet<br />

Tabell 4.4 Beskrivning av signalerna mellan sensorenhet och styrenhet.<br />

Kommunikationen går till så att då roboten befinner sig i en korridor sätts bit<br />

A1 hög och sensorenheten börjar leta efter korsningar eller<br />

riktningskorrigeringar. Allt enligt flödesschemat i figur 4.2.<br />

Behövs en korrigering sätts A1 låg så att sensorenheten slutar leta efter<br />

korrigeringar och korsningar. Därefter utför styrenheten den nödvändiga<br />

korrigeringen och A1 sätts åter hög. På detta sätt uppstår inte problem med att<br />

sensorenheten skickar korrigeringssignaler som beror på korrigeringen.<br />

Om sensorenheten hittar en korsning sätts även där A1 låg. Roboten går sedan<br />

ungefär 15 cm in i korsningen så att sensorenheten lättare kan avgöra vilken<br />

typ av korsning roboten står i. A2 sätts hög så att sensorenheten vet att den<br />

skall bestämma korsningstyp. När den gjort detta och styrenheten tagit emot<br />

signalen sätts A2 låg. Styrenheten förflyttar sedan roboten på det sätt som<br />

beskrivs av algoritmen i avsnitt 4.2.1. Styrenheten förflyttar även roboten<br />

ungefär 20 cm in i den korridor som ligger efter korsningen. Detta för att<br />

sensorenheten inte ska bli störd av den tidigare korsningen. Slutligen sätts A1<br />

hög och sensorenheten börjar återigen söka efter riktningskorrigeringar och<br />

korsningar.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 18


Platon<br />

2003-12-09<br />

5 Sensorenhet<br />

5.1 Inledande beskrivning av sensorenheten<br />

Sensorenhetens uppgifter är att meddela styrenheten om en ny korsning upptäckts,<br />

vilken typ av korsning det är samt om kurskorrigering behövs. Styrenheten meddelar<br />

sensorenheten vad den är intresserad av just nu, antingen korrigera och finna korsning,<br />

eller avgöra korsningstyp. Korrigeringssignaler för korrigering åt vänster och höger<br />

beräknas och skickas till styrenheten då roboten befinner sig alltför nära en vägg och<br />

signaler för korsningar beräknas då en korsning upptäckts. Utsignaler från<br />

sensorenheten är uppdelade i två grupper. Den första gruppen är typ av korsning, den<br />

andra är hitta korsning eller korrigera. Sensorenheten har tre sensorer till hjälp och en<br />

mikrodator för att samordna dem.<br />

5.2 Mjukvara<br />

Då signalen A1 eller A2 är hög läses sensorerna av en efter en. Detta görs i en<br />

avbrottsrutin till timer1 som räknar upp sexton bitar med åtta MHz. I detta läge är<br />

mätningen på vilket markeras med att variabeln MATNING_PA har värdet 256. När alla<br />

sensorer är avlästa körs en rutin UPPD_UTV (uppdatera utvärde); denna körs också<br />

kontinuerligt av timer1 då mätningen är avstängd. Varje gång UPPD_UTV körs<br />

undersöks invärden från styrenheten och det avgörs om mätningen ska fortsätta vara<br />

på, stängas av eller kanske sättas på. Exakt hur sensorerna läses av återfinns i<br />

avsnitt 5.2.1.<br />

Varje gång rutinen UPPD_UTV körs finns alltså tre korrekta mätvärden till hands,<br />

alternativt att de inte finns om mätningen är avstängd. I det sista fallet görs bara den<br />

tidigare nämnda undersökningen sedan avslutas rutinen.<br />

Dessa tre utvärden behandlas på följande sätt.<br />

Om A1 är hög:<br />

De tre sista bitarna i en variabel (MAT_BYTE) sätts till höga<br />

respektive låga beroende på om sensorn har en vägg eller inte<br />

framför sig. Framåt betraktas ett eko med avståndet < 30 cm<br />

som en vägg, åt sidorna mätvärde < 50 cm.<br />

Sedan mappas dessa bitmönster om till en signal (korsningstyp).<br />

Denna signal skrivs sedan till utporten.<br />

Om A2 är hög:<br />

Mätvärdena undersöks efter lämpliga utsignaler efter signalernas<br />

prioritet (se avsnitt 5.3.3). Signalerna bestäms av följande krav och<br />

gränser:<br />

Korsning höger/vänster: sidorna > 50 cm åt något håll<br />

Korrigering:<br />

sidorna


Platon<br />

2003-12-09<br />

5.2.1 Sensorer<br />

För att läsa av sensorerna används en timer (timer0) som räknar upp åtta bitar<br />

med klockans sexton MHz. När sensorn ska läsas av skickas först en triggersignal<br />

till den aktuella sensorn som ska mätas av. Medan signalen skickas<br />

loopar processorn i en loop som inte gör någonting en liten tid. Detta eftersom<br />

pulsen inte behöver vara så speciellt lång. Sedan startas timern och tidigare<br />

mätvärden nollställs. Även ett värde TID_START nollställs.<br />

När timerrutinen sedan körs kontrollerar den om signalen echo-out (se avsnitt<br />

5.4.1) är hög. Är den hög räknas mätvärdet upp med ett steg. Variabeln till<br />

TID_START sätts också till 255 om den inte redan är det. Är signalen däremot<br />

låg antas dessa två fall vara möjliga:<br />

1. Pulsen har inte kommit ännu.<br />

2. Pulsen har passerat och mätningen är klar.<br />

För att särskilja dessa värden undersöks värdet av TID_START. Om<br />

TID_START har värdet 255 antas mätningen vara klar och timern stängs samt<br />

om alla mätningar från sensorerna är klara uppdateras utvärdet till styrenheten.<br />

Har TID_START värdet 0 återgår datorn till att vänta på en puls från<br />

sensorerna. Kommer ingen puls återgår datorn till att vänta.<br />

Ett problem med våra ultraljudssensorer är att de inte ger något stabilt värde.<br />

Det verkar som att de har en tendens att ge ett felaktigt mätvärde lite då och då.<br />

Detta är inte bra i vårt fall eftersom om en korsning undersöks felaktigt<br />

kommer roboten kanske inte att kunna hitta ut ur labyrinten. För att undvika<br />

detta gör vi tre mätningar per sensor i rad och beräknar medelvärdet av de två<br />

mätningar som ger närmast mätvärde. Differensen mellan mätvärdena<br />

beräknas, det finns alltså tre möjliga differenser. De två mätvärden som har<br />

lägst differens väljs och medelvärdet av dem beräknas. Denna behandling ger<br />

ett mycket stabilt mätvärde.<br />

5.3 Gränssnitt mot andra enheter<br />

5.3.1 Insignaler<br />

Sensorenheten har två insignaler från styrenheterna, A1 och A2. När<br />

styrenheten vill ha information om vilken typ av korsning roboten befinner sig<br />

i så sätter den signalen A2 hög. Sensorenheten läser då av sensorerna och när<br />

den sedan har fått mätvärdet från alla sensorer beräknar den vilken korsning<br />

roboten befinner sig i och sätter det som utvärde. Utvärdet kommer sedan att<br />

uppdateras kontinuerligt ända tills att signalen A2 går låg igen. Den kommer då<br />

att sätta 0 0000 som utsignal efter en kortare tid.<br />

När roboten går i en av labyrintens korridorer och styrenheten vill veta om<br />

korrigering är nödvändig eller om roboten kommit till en korsning sätts<br />

signalen A1 till hög. Roboten kommer då kontinuerligt att uppdatera utvärdet<br />

och om den upptäcker att korrigering behövs, sätta signal för detta, samma sak<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 20


Platon<br />

2003-12-09<br />

om roboten kommer till en korsning. Signalen för korrigering försvinner då<br />

roboten står rätt i korridoren igen.<br />

5.3.2 Utsignaler<br />

Styrenheten har en uppsättning signaler som kan skickas till styrenheten. Dessa<br />

representeras med ett bitmönster. Signalerna kan delas in i två grupper:<br />

• korsningstyp<br />

• korrigeringstyp eller hittad korsning.<br />

Den första biten beskriver vilken typ av signal som skickas, 0 betyder grupp<br />

ett, 1 betyder grupp två. Själva signalen representeras sedan med ett fyrabitars<br />

tal. Signalerna ur grupp ett är svar på signalen A2 från styrenheten och signaler<br />

ur grupp två svar på signalen A1.<br />

Grupp ett, som skickas då styrenheten vill undersöka vilken typ av korsning det<br />

är, finns i tabell 5.1, medan grupp två, som skickas då styrenheten vill leta efter<br />

korsning eller få signal för korrigering, åskådliggörs i tabell 5.2.<br />

Korsningstyp<br />

Bitmönster<br />

felmeddelande, okänd korsning. 0 0000<br />

återvändsgränd 0 0001<br />

vänsterkorsning 0 0010<br />

högerkorsning 0 0011<br />

T-korsning (höger-vänster korsning) 0 0100<br />

framåt-vänster korsning 0 0101<br />

framåt-höger korsning 0 0110<br />

fyrvägskorsning 0 0111<br />

Den första biten i bitmönstret betecknar grupp: 0 står för grupp ett<br />

Tabell 5.1 Korsningssignaler från sensorenheten till styrenheten.<br />

Korrigering/finn korsning<br />

Bitmönster<br />

ingen korrigering 1 0000<br />

korrigera vänster 1 0001<br />

korrigera höger 1 0010<br />

hittat en korsning 1 1111<br />

Den första biten i bitmönstret betecknar grupp: 1 står för grupp två<br />

Tabell 5.2 Korrigeringssignaler från sensorenheten till styrenheten.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 21


Platon<br />

2003-12-09<br />

5.3.3 Signalprioritet<br />

När sensorenheten går i en korridor och söker efter en korsning eller<br />

korrigering en situation där det både behöver skickas en korrigeringssignal och<br />

signal för korsningtyp uppstå. För att kunna hantera detta har de olika<br />

signalerna ur grupp två olika prioritet. Inträffar två situationer samtidigt väljs<br />

den signal som har högst prioritet.<br />

Prioritet:<br />

1. Korsning funnen<br />

2. Korrigering<br />

3. Återvändsgränd<br />

5.3.4 Display<br />

Eftersom sensorenheten inte ger ett lika konkret resultat som styrenheten eller<br />

fjärrstyrenheten har vi utrustat den med en display för att återge vad<br />

sensorenheten ger för utsignaler. Detta underlättar testning av roboten och<br />

kontroll av sensorenhetens resultat.<br />

Vi har därför valt att bygga in en display bestående av ett sjusegment. Detta är<br />

inkopplat med ett motstånd på 120 ohm för att begränsa strömmen samt en<br />

avkodare och tolv stycken inverterare. Signalen som avkodas är de fyra<br />

signalbitarna som kommer från sensorenheten.<br />

5.4 Sensorer<br />

5.4.1 Hårdvara<br />

Vårt sensorsystem består av tre ultraljudssensorer av typen SRF04, en placerad<br />

längst fram på roboten och en på vardera sida av roboten. Sensorerna har<br />

förutom en pinne för 0V/+5V även två pinnar för avläsning av sensorerna. Den<br />

ena kallas trigger-input och den andra för echo-out. För att läsa av sensorn<br />

skickar man först en kort puls till trigger-input. Sensorn skickar då i väg en<br />

puls av ultraljud som sedan reflekteras om det är något framför sensorn. Strax<br />

efter att pulsen skickas i väg sätts echo-out till hög av sensorn. Denna stannar<br />

sedan hög tills att sensorn får tillbaka ultraljudspulsen från något reflekterande<br />

objekt eller tills att mätningen gör en time-out. För att läsa av sensorerna<br />

används en åttabitars port på PIC:en. De lägsta bitarna är signalerna till triggeroutput<br />

och de höga är echo-out signalen från sensorerna. Denna port är alltså<br />

både en in- och utport. De höga bitarna input och de låga output.<br />

5.4.2 Namngivning<br />

Sensorerna har vi namngivit med siffror. Den högra sensorn har fått nummer 1,<br />

den vänstra nummer 2 och den främre sensorn har fått nummer 3, allt enligt<br />

figur 5.1.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 22


Platon<br />

2003-12-09<br />

3<br />

2<br />

1<br />

Figur 5.1<br />

Placering av sensorer på roboten.<br />

6 Användarhandledning<br />

Platon är en sexbent robot utförd i härligt gul plast. Roboten kan användas i två olika lägen;<br />

ett manuellt läge, där användaren kontrollerar dess beteende med hjälp av kommandon från en<br />

fjärrkontroll, och ett autonomt läge, i vilket roboten kan söka sig igenom en labyrint på egen<br />

hand. En översiktlig vy över den fjärrkontroll som används för att styra roboten visas i<br />

figur 6.1. I tabell 6.1 ges en förklaring av de kommandoknappar som behövs för att styra<br />

Platon.<br />

Figur 6.1 Fjärrkontrollen och dess knappar (se även tabell 6.1).<br />

Knapp nr<br />

Kommando<br />

1 autonomt läge på/av<br />

2 VCR (sätter fjärrkontrollen i rätt läge)<br />

3 sväng vänster<br />

4 gå framåt<br />

5 sväng höger<br />

6 stanna/filosofera<br />

7 gå bakåt<br />

8 Ljudsignal<br />

Tabell 6.1 Förklaring av knappar och kommandon (se även figur 6.1).<br />

Innan Platon startas, bör man förvissa sig om att fjärrkontrollen befinner sig i rätt läge genom<br />

att trycka på knappen VCR på fjärrkontrollen. Sedan startas roboten med hjälp av<br />

skjutomkopplaren längst fram på virkortet på robotens rygg. Om allting står rätt till tänds då<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 23


Platon<br />

2003-12-09<br />

en liten röd diod strax intill omkopplaren. Skjutomkopplaren och dioden är markerade i<br />

figur 6.2 nedan.<br />

Figur 6.2<br />

Platon sedd uppifrån.<br />

Roboten styrs i sitt manuella läge genom fjärrkontrollen. Genom knapptryckningar kan man<br />

då styra roboten. När man tryckt ner till exempel ”gå framåt” en gång, kommer sedan roboten<br />

att fortsätta gå framåt tills ett annat kommando, till exempel ”stanna” eller ”sväng vänster”<br />

ges. Undantaget från denna regel är kommandot ”ljudsignal”. När Platon mottar detta<br />

kommando, ger han en kort ljudsignal. Detta kommando påverkar inte robotens rörelser på<br />

något sätt. I vissa miljöer kan det finnas mycket störningar från till exempel lysrör. Då kan det<br />

vara svårt att få Platon att reagera på kommandon. Det lönar sig då att vara envis och trycka in<br />

rätt knapp ett antal gånger tills kommandot går fram. Knappen kan även hålls in kontinuerligt.<br />

Vill man att Platon ska söka sig igenom en labyrint, bör man först se till att han står rakt<br />

framför labyrintens ingång. Därefter väljer man autonomt läge, antingen med hjälp av<br />

knappen autonomt läge på/av på fjärrkontrollen eller med den knapp på roboten som har<br />

motsvarande funktion. När autonomt läge är valt, lyser den stora röda dioden på robotens<br />

virkort. Knappen och dioden finns utmärkta i figur 6.2. Medan roboten befinner sig i<br />

autonomt läge reagerar den endast på kommandona ”ljudsignal” och ”autonomt läge av” från<br />

fjärrkontrollen. För att åter välja manuellt läge, trycker man bara ännu en gång på knappen på<br />

fjärrkontrollen eller roboten. Den stora dioden kommer då att släckas.<br />

7 Referenser<br />

Designspecifikation, Landén, David, 2003.<br />

Kravspecifikation, Rees, Johan, 2003.<br />

Systemskiss, Fåk, Pia, 2003.<br />

Konstruktion med mikrodatorer Projektgrupp 15 - Platon LIPs<br />

Dokumentansvarig: David Landén martenson+stalin@lysator.liu.se Sida 24


Bilaga 1<br />

Hårdvarulista<br />

Fjärrstyrningsenhet<br />

fjärr1. en generell fjärrkontroll av modell BW0368 Remotec inställd på det Sonyprotokoll<br />

som specificeras i den tekniska beskrivningen av fjärrkontrollen<br />

fjärr2. en IR-mottagardiod från Everlight av modell IRM-86901S<br />

fjärr3. en mikrokontroller från Microchip av modell PIC16F870 med tillhörande<br />

fördröjd reset som består av två kondensatorer och en resistor.<br />

fjärr4. en tryckknapp<br />

fjärr5. en röd lysdiod med tillhörande motstånd<br />

fjärr6. en summer<br />

fjärr7. en avstudsarkrets till tryckknappen 74LS00<br />

Sensorenhet<br />

sensor1. ultraljudssensor från Devantech av modell SRF04<br />

sensor2.<br />

sensor3.<br />

sensor4. en mikrokontroller från Microchip av modell PIC16F870<br />

sensor5. ett sjusegment från Everlight av typen ELS-515EWA<br />

sensor6. en BCD till sjusegment avkodare 74LS47<br />

sensor7. två 6x inverterare 74LS04<br />

sensor8. ett motstånd 150 ohm<br />

Styrenhet<br />

styr1.<br />

styr2.<br />

styr3.<br />

en AVR Atmel Mega16 till styrlogik,<br />

en AVR Atmel Mega16 till steglogik samt<br />

ett robotskelett med förmonterade servon och ben.<br />

Samtliga enheter kommunicerar med varandra med hjälp av rättframma tråddragningar.<br />

Samma sorts informationsöverföring används även inom enheterna då olika komponenter<br />

anslutits till varandra, så när som på fjärrkontrollen och IR-detektorn som naturligtvis skickar<br />

och tar emot signaler i form av IR-ljus.<br />

I bilagorna A1, B1 och C1 visas hur de olika enheternas komponenter är anslutna till<br />

varandra.


Bilaga A1<br />

Kretsschema för fjärrstyrningsenheten


Bilaga B1<br />

Kretsschema för styrenheten<br />

Styrkommando<br />

från fjärrenhet<br />

Styrkommando<br />

till sensorenhet<br />

A1<br />

A2<br />

Strobe från<br />

fjärrenhet<br />

Styr1: styrlogik<br />

15<br />

16<br />

17<br />

18<br />

40<br />

39<br />

38<br />

37<br />

36<br />

35<br />

34<br />

33<br />

32<br />

31<br />

30<br />

29<br />

28<br />

27<br />

26<br />

25<br />

24<br />

23<br />

19 22<br />

20 21<br />

Styrkommando<br />

från sensorenhet<br />

B5<br />

B4<br />

B3<br />

B2<br />

B1<br />

Styr2: steglogik<br />

15<br />

16<br />

17<br />

18<br />

40<br />

39<br />

38<br />

37<br />

36<br />

35<br />

34<br />

33<br />

32<br />

31<br />

30<br />

29<br />

28<br />

27<br />

26<br />

25<br />

24<br />

23<br />

19 22<br />

20 21<br />

Styr3: servon


Bilaga C1<br />

Kretsschema för sensorenheten


Bilaga A2<br />

Assemblerkod för fjärrstyrningsenheten<br />

;**************************************************************<br />

;<br />

; PROGRAM fjarr<br />

;<br />

; Version 1.0<br />

;<br />

; Skapare Pia Fåk och Jessica Heyman, grupp15<br />

; Skapad 2003-11-07<br />

;<br />

; Ändringar<br />

; 2003-11-10 CLRF PORTA får portA att fungera<br />

;<br />

; 2003-11-11 tutkod tillagd<br />

;<br />

; 2003-11-12 skickar 000 på portA även vid autonomt<br />

; läge av<br />

;<br />

; 2003-11-27 skickar stoppkod till styrenhet<br />

; vid uppstart<br />

;<br />

;<br />

;**************************************************************<br />

;<br />

; Programmet ska ta emot signaler från en IR-diod och<br />

; skicka data till styrmodulen, samt sköta om tändning<br />

; och släckning av diod, tutning, signaler från<br />

; tryckknapp m.m.<br />

;<br />

; Version 1.0: programvaran används i färdig robot<br />

;<br />

; Programmet fungerar under förutsättning att de IR-signaler<br />

; som inkommer till enheten till någorlunda stor del består<br />

; en viss delmängd av signalerna i RC5-protokollet<br />

TITLE "fjarr"<br />

LIST P=16F870, F=INHX8M<br />

#INCLUDE "P16F870.INC"<br />

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON<br />

;**************************************************************<br />

; Definition av konstanter<br />

;**************************************************************<br />

; Konstanter som motsvarar specifika bitar i registren<br />

;<br />

KNAPP EQU 7 ; bitar i ut- och ingångar<br />

IRDET EQU 0<br />

STYR0 EQU 0<br />

STYR1 EQU 1<br />

STYR2 EQU 2<br />

STROBE EQU 3<br />

TUTA EQU 1<br />

DIOD EQU 5<br />

ONOFF EQU 0 ;inre tillstånd<br />

SECOND EQU 1 ;vill vi ha en likadan signal eller ej<br />

TOGG EQU 5 ;förra togglebiten<br />

; Egendefinierade registernamn<br />

STATREG EQU 0x20 ;autonomt läge av/på lagras här<br />

COMMAND EQU 0x21 ;här bor det som ev. ska skickas<br />

COUNTM EQU 0x22 ;räknar hur många metabitar vi fått<br />

COUNTS EQU 0x23 ;räknar hur många signalbitar vi fått<br />

SIGNAL EQU 0x24 ;viktig insignal från IR-detektorn<br />

META EQU 0x25 ;register för intstoppning av metadata<br />

LASTSIG EQU 0x26 ;den förra signalen ligger här<br />

LJUD EQU 0x27 ;här lägger vi ett ljud<br />

COUNTL EQU 0x28 ;räknar hur många tut vi tutat<br />

; signalbitsmönster<br />

STANNA EQU b'00001001'<br />

FRAM EQU b'00001010'<br />

BAK EQU b'00001111'<br />

VANSTER EQU b'00001101'<br />

HOGER EQU b'00001011'<br />

TUT EQU b'00001000'<br />

AUTON EQU b'00110011'


;**************************************************************<br />

; Program-yta<br />

;**************************************************************<br />

; Start av program-yta<br />

;<br />

ORG 0x00<br />

GOTO MAIN ; Gå till huvudprogram<br />

ORG 0x04<br />

GOTO ISR ; Gå till avbrottsrutin<br />

;**************************************************************<br />

; Avbrottsrutiner<br />

;<br />

; IRKOM<br />

; TMRAVB<br />

; TMR1AVB<br />

; TRYCKAVB<br />

;<br />

; som använder SKICKA<br />

; och SIGKOLL<br />

;**************************************************************<br />

;--------------------------------------------------------------<br />

; Subrutin IRKOM<br />

; anropas när en IR-signal först börjar komma in till processorn<br />

; Sätter igång en timer för att börja sampla signalen, stänger<br />

; av vidare avbrott pga av fallande flanker på RB0<br />

IRKOM BCF STATUS,RP0 ;byt till bank 0<br />

BCF STATUS,RP1 ;bank 0, ju.<br />

BCF INTCON,INTE ;INTE några fler RB0-avbrott<br />

MOVLW b'00000000' ;0 = lite mindre än 5T<br />

MOVWF TMR0 ;till TMR0!<br />

BCF INTCON,T0IF ;cleara TMR0-avbrottsflaggan så att<br />

;inget gammal skräp avbryter oss<br />

BSF INTCON,T0IE ;nu börjar vi lyssna efter TMR0-avbrott<br />

BCF INTCON,INTF ;cleara RB0-avbrottsflagga<br />

RETURN<br />

;--------------------------------------------------------------<br />

;--------------------------------------------------------------<br />

; Subrutin TMR1AVB<br />

; Sköter om tutningen.<br />

; ge 1 eller 0 till summer beroende på ljudregistrets LSB<br />

; stäng av vidare TMR1-avbrott om ljudsignal har getts färdigt<br />

TMR1AVB<br />

;bestäm ljud, LSB i LJUD ger 1=tut, 0=inget<br />

BCF<br />

PIR1,TMR1IF<br />

RRF LJUD,1 ;rotera ljudsignal<br />

BTFSS STATUS,C ;roterat ut en etta<br />

GOTO NOLLA ;ja, en etta, tuta<br />

;etta<br />

BSF PORTB,TUTA ;etta => tut!<br />

GOTO<br />

DONE<br />

NOLLA BCF PORTB,TUTA ;nolla, tuta inte<br />

DONE BCF STATUS,C ;nolla carryn<br />

RRF COUNTL,1 ;rotera räknaren, roterar in 0<br />

BTFSS STATUS,C ;färdigtutad<br />

RETURN<br />

;ej färdigtutad, bara att fortsätta<br />

;färdigtutat, stäng av timer1<br />

BCF PORTB,TUTA ;stäng av tutan, för nu är den färdig<br />

BCF T1CON,TMR1ON ;stäng av TMR1, färdiguttimrad!<br />

BSF STATUS,RP0 ;bank1<br />

BCF PIE1,TMR1IE ;stäng av TMR1-avbrott också,<br />

;för säkerhets skull<br />

BCF STATUS,RP1 ;bank0<br />

RETURN<br />

;--------------------------------------------------------------<br />

;--------------------------------------------------------------<br />

; Subrutin TMRAVB<br />

; Sköter det mesta av inläsningen av en IR-signal<br />

; Rutinen läser av RB0, och lagrar undan värdet och räknar upp<br />

; hur många gånger det skett. Är det metadata som kommer, läggs<br />

; det i registret META, annars lägger man det i DATA.<br />

; Har vi samplat signalen 14 ggr är vi färdiga. Då


; stänger vi av TMR0 och kollar om vi kanske har något<br />

; att skicka till styrenheten.<br />

; Annars sätts timern igen och förloppet kommer att upprepas.<br />

; IN: RB0 - signalen seriellt<br />

; UT: skickar via subrutin SKICKA kommando till styrenheten.<br />

TMRAVB BCF STATUS,RP0 ;Byt bank!<br />

BCF STATUS,RP1 ;Bank 0.<br />

BCF STATUS,C ;se till att carryn är 0.<br />

RRF COUNTM,0 ;låtsasuppdatera räknare<br />

BTFSS STATUS,C ;kolla vad carryn blev<br />

GOTO METADAT ;det är ju metadata som kommer nu!<br />

SDATA BTFSS PORTB,IRDET ;är det månne en etta vi har<br />

GOTO INTEOR2 ;nä, då ORAR vi inte.<br />

MOVF COUNTS,0 ;Flytta countervärdet till W<br />

IORWF SIGNAL,1 ;ORA W med SIGNAL<br />

INTEOR2 BCF STATUS,C ;carryn måste vara noll<br />

RRF COUNTS,1 ;ROTERA!<br />

BTFSS STATUS,C ;colla carryn!<br />

GOTO SCHLUT ;inte färdigmottagen signal än<br />

SIGREDY CALL SIGKOLL ;signal färdigmottagen, kolla om vi<br />

; tycker om den<br />

CLRF META ;nolla META för nu har den använts<br />

; färdigt<br />

CLRF SIGNAL ;nolla SIGNAL för den är lika<br />

; färdig som META<br />

MOVLW b'10000000' ;Metaräknaren ska förstås vara åtta,<br />

MOVWF COUNTM ; på ett mystiskt vis.<br />

MOVLW b'00100000' ;Signalräknaren ska förstås vara fem,<br />

MOVWF COUNTS ; på ett mystiskt vis, den med.<br />

BCF INTCON,T0IE ;stäng av vidare TMR0-interrupt<br />

BCF INTCON,INTF ;cleara RB0-avbrottsflaggan<br />

BSF INTCON,INTE ;sätt på vidare RB0-avbrott<br />

GOTO<br />

SCHLUT<br />

METADAT RRF COUNTM,1 ;uppdatera räknaren på riktigt<br />

BTFSS PORTB,IRDET ;kolla om vi har en etta att stoppa in<br />

GOTO<br />

SCHLUT<br />

MOVF COUNTM,0 ;flytta countervärdet till W<br />

IORWF META,1 ;ORA W med META.<br />

SCHLUT MOVLW d'36' ;36!<br />

MOVWF TMR0 ;till TMR0!<br />

BCF INTCON,T0IF ;cleara flaggan<br />

RETURN<br />

;--------------------------------------------------------------<br />

;--------------------------------------------------------------<br />

; Subrutin TRYCKAVB<br />

; Anropas vid tryck på tryckknappen. När man släpper upp knappen<br />

; kommer ett "extra" avbrott, som ska ignoreras<br />

; Om riktigt avbrott: toggla autonomt läge på/av i STATREG,<br />

; Om ON: tänd diod, skriv i COMMAND, skicka.<br />

; Om OFF: släck diod.<br />

TRYCKAVB BCF STATUS,RP0 ;byt till bank 0<br />

BCF<br />

STATUS,RP1<br />

BTFSC PORTB,KNAPP ;om biten är ett, är avbrottet falskt<br />

GOTO SLUT ;avbrottet falskt, gör inget mer!<br />

BTFSS STATREG,0 ;kolla hälsan<br />

GOTO ON ;Den var satt och tjock!<br />

;stäng av autonomt läge<br />

OFF BCF PORTA,DIOD ;släck dioden!<br />

BCF STATREG,ONOFF ;byt den mentala hälsan,<br />

;nu är vi oautonoma<br />

MOVLW b'00000000' ;skriv i command-reg!<br />

MOVWF COMMAND ;gör det på riktigt<br />

CALL SKICKA ;skicka. OBS! görs efter att<br />

;vi stängt av autonomt läge<br />

GOTO<br />

SLUT<br />

;sätt på autonomt läge<br />

ON BSF PORTA,DIOD ;tänd dioden!<br />

MOVLW b'00000000' ;skriv i command-reg!<br />

MOVWF COMMAND ;gör det på riktigt<br />

CALL SKICKA ;skicka. OBS! görs innan<br />

;vi sätter på autonomt läge<br />

BSF STATREG,ONOFF ;nu är vi autonoma<br />

SLUT BCF INTCON,RBIF ;cleara tryckavbrottsflaggan


BCF INTCON,T0IF ;cleara TMR0-avbrottsflaggan<br />

RETURN<br />

;--------------------------------------------------------------<br />

;--------------------------------------------------------------<br />

; Subrutin SIGKOLL<br />

; Tittar på mottaget signaldata och kontrollerar om det är<br />

; vettigt, dvs metadata stämmer och signalen är någon vi<br />

; lyssnar efter.<br />

; Är signalen vettig, läggs data i registret<br />

; COMMAND, varpå detta skickas mha SKICKA-rutinen.<br />

; Utom om det är tutkommandot som kommer in, då startas<br />

; tutningen.<br />

; Är signalen inte vettig, skrotas den bums.<br />

SIGKOLL MOVF META,0 ;lägg META i W<br />

ANDLW b'11011111' ;Cleara togglebiten<br />

SUBLW b'00011111' ;"jämför"<br />

BTFSS STATUS,Z ;var de lika<br />

GOTO SKROT ;nä, då skrotar vi värdet<br />

BRA BTFSS META,TOGG ;TOGGLE tjock<br />

GOTO<br />

SMAL<br />

MOVLW b'10000000' ;Tal att ora med<br />

IORWF SIGNAL,1 ;ORA in den där ettan<br />

SMAL MOVF SIGNAL,0 ;stoppa SIGNAL i W<br />

SUBWF LASTSIG,0 ;"jämför"<br />

BTFSC STATUS,Z ;feeeeett<br />

GOTO KOLLIK ;Vi har just haft en sån!<br />

;Kolla om de ska vara lika<br />

MOVF SIGNAL,0 ;lägg den i W igen.<br />

MOVWF LASTSIG ;Stoppa W (SIGNAL) i LASTSIG<br />

;för framtida bruk<br />

BSF STATREG,SECOND ;Vi vill att nästa signal som kommer<br />

;ska se likadan ut<br />

GOTO SKROT ;Vi är inte intresserade av en<br />

;signal som inte har kommit en gång<br />

;redan<br />

KOLLIK BTFSS STATREG,SECOND ;är det så att signalerna ska vara lika<br />

GOTO SKROT ;det ska de inte, så vi slänger signalen<br />

BCF STATREG,SECOND ;nu ska signalerna inte vara lika längre!<br />

HITTA BCF SIGNAL,7 ;återställ signal (ta bort togglebiten)<br />

MOVLW STANNA ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO STOP ;men gör stop då!<br />

MOVLW FRAM ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO FORWARD ;men gör forward då!<br />

MOVLW BAK ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO BACK ;men gör back då!<br />

MOVLW VANSTER ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO LEFT ;men gör left då!<br />

MOVLW HOGER ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO RIGHT ;men gör right då!<br />

MOVLW TUT ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO HORN ;men gör horn då!<br />

MOVLW AUTON ;Stoppa in testvärde i W<br />

SUBWF SIGNAL,0 ;"jämför"<br />

BTFSC STATUS,Z ;lika<br />

GOTO INDEPEN ;men gör indepen då!<br />

GOTO<br />

SKROT<br />

STOP MOVLW b'00000101' ;stoppkommandot in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL<br />

SKICKA


RETURN<br />

FORWARD MOVLW b'00000001' ;stoppkommandot in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL<br />

SKICKA<br />

RETURN<br />

BACK MOVLW b'00000010' ;stoppkommandot in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL<br />

SKICKA<br />

RETURN<br />

LEFT MOVLW b'00000100' ;stoppkommandot in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL<br />

SKICKA<br />

RETURN<br />

RIGHT MOVLW b'00000011' ;stoppkommandot in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL<br />

SKICKA<br />

RETURN<br />

HORN MOVLW b'11111011' ;ljudsignal består av 6 tut<br />

MOVWF LJUD ;in i ljudregistret<br />

MOVLW b'10000000' ;räknare<br />

MOVWF COUNTL ;in i ljudräknaren<br />

;sätt timer att timra ut om 0,26 s<br />

CLRF TMR1L ;nollställ TMR1<br />

CLRF TMR1H ;nollställ hela TMR1<br />

MOVLW b'00000001' ;prescale=4, TMR1=on<br />

MOVWF T1CON ;in i kontrollregistret<br />

BCF PIR1,TMR1IF ;cleara TMR1-avbrottsflaggan<br />

BSF INTCON,PEIE ;enabla perifera avbrott (TMR1)<br />

BSF STATUS,RP0 ;bank1<br />

MOVLW b'00000001' ;enabla TMR1-avbrott på riktigt<br />

MOVWF PIE1 ;in i kontrollregistret, oxå.<br />

BCF STATUS,RP0 ;bank0<br />

RETURN<br />

INDEPEN BTFSC STATREG,ONOFF ;autonomt läge på<br />

GOTO PA ; japps, gå till PA för att stänga av<br />

;sätt på autonomt läge<br />

AV BSF PORTA,DIOD ;tänd dioden, för vi var av<br />

MOVLW b'00000000' ;autonomt läge på in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL SKICKA ;skicka iväg också<br />

BSF STATREG,ONOFF ;sätt på.<br />

;OBS! skicka autonomt PÅ först!<br />

RETURN<br />

;stäng av autonomt läge<br />

PA BCF PORTA,DIOD ;släck dioden<br />

BCF STATREG,ONOFF ;stäng av autonomt läge, för vi var på!<br />

MOVLW b'00000000' ;autonomt läge på in i W<br />

MOVWF COMMAND ;in i COMMAND<br />

CALL SKICKA ;skicka iväg också.<br />

;OBS! skicka autonomt av efteråt!<br />

RETURN<br />

SKROT RETURN ;nä, precis. Inget var det.<br />

;--------------------------------------------------------------<br />

;--------------------------------------------------------------<br />

; Subrutin SKICKA<br />

; Lägg ut det som finns i COMMAND på STYR0-2<br />

; för att inte ändra värdena som ligger i PORTA i<br />

; onödan, vidtas visst krångel<br />

SKICKA BTFSC STATREG,ONOFF ;om vi är autonoma, skicka ej<br />

GOTO NEJ ; vi var autonoma och struntar i<br />

; att lyssna<br />

JA MOVLW b'11111000' ;stoppa en AND-vektor i W<br />

ANDWF PORTA,1 ;se till att det bor nollor<br />

; på rätt postioner i PORTA<br />

MOVF COMMAND,0 ;stoppa värdet i COMMAND i W<br />

IORWF PORTA,1 ;skriv rätt värden till PORTA<br />

BCF PORTA,STROBE ;Stroba!<br />

NOP<br />

;här har vi en massa NOPar


NOP<br />

;för att få längre strobe<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

BSF PORTA,STROBE ;sluta stroba!<br />

NEJ CLRF COMMAND<br />

RETURN<br />

;--------------------------------------------------------------<br />

;**************************************************************<br />

; Avbrottsrutin<br />

;**************************************************************<br />

; Avbrottskällor:<br />

; IRDET insignal från IR-detektor på RB0<br />

; avbryter på fallande flank<br />

; TRYCKKNAPP insignal från tryckknapp på portA,knapp<br />

; avbryter på change<br />

; TMR1 avbrott från tut-timern, som ändrar tut-<br />

; signal när det behövs<br />

; TMR0 avbryter med 4Ts mellanrum för att läsa<br />

; av signal<br />

;<br />

; Kollar på avbrottsflaggor i en Bra Ordning.<br />

;<br />

;Om RB0-avbrott är på, ska de servas. Annars måste vi strunta i<br />

; dess avbrottsflagga<br />

ISR BTFSC INTCON,INTE ;är RB0-avbrott på<br />

GOTO MAYBERB ;ja, det är de!<br />

NOTRB0 BTFSC INTCON,RBIF ;är det avbrott från tryckknappen<br />

CALL TRYCKAVB ; då går vi till TRYCKAVB<br />

BTFSC PIR1,TMR1IF ;är det timer1-avbrott<br />

CALL TMR1AVB ; då går vi till TMR1AVB<br />

BTFSC INTCON,T0IF ;är det timer0-avbrott<br />

CALL TMRAVB ; då går vi till TMRAVB<br />

RETFIE<br />

MAYBERB BTFSC INTCON,RBIF ;är det avbrott från tryckknappen<br />

CALL TRYCKAVB ; då går vi till TRYCKAVB<br />

BTFSC INTCON,INTF ;är det avbrott från RB0<br />

CALL IRKOM ; då går vi till IRKOM<br />

BTFSC PIR1,TMR1IF ;är det timer1-avbrott<br />

CALL TMR1AVB ; då går vi till TMR1AVB<br />

RETFIE<br />

;**************************************************************<br />

; Huvudprogram<br />

;**************************************************************<br />

; MAIN körs först av allt när processorn startar.<br />

; den initierar alla register och sådär, och fastnar sedan i en<br />

; oändlig loop som bara väntar på att bli avbruten.<br />

MAIN BCF STATUS,RP0 ;välj bank 0<br />

BCF STATUS,RP1 ;välj mer bank 0<br />

CLRF<br />

PORTA<br />

MOVLW b'10011000' ;Stoppa 11110000 i INTCON<br />

MOVWF INTCON ;ger interrupt på, p-interrupt av,<br />

;TMR0-overflow interrupt av,<br />

;rb-interrupt på, RB change-interrupt på.<br />

CLRF STATREG ;Auto-tillstånd ska vara AV<br />

MOVLW b'10000000' ;Metaräknaren ska förstås vara åtta,<br />

MOVWF COUNTM ; på ett mystiskt vis.<br />

MOVLW b'00100000' ;Signalräknaren ska förstås vara fem,<br />

MOVWF COUNTS ; på ett mystiskt vis, den med.<br />

CLRF COMMAND ;vi vill inte ha några ettor här.<br />

CLRF SIGNAL ;inte här heller.<br />

CLRF<br />

META<br />

CLRF<br />

LASTSIG<br />

CLRF<br />

LJUD<br />

BCF STATUS, RP1 ;välj bank 1<br />

BSF STATUS, RP0 ;bank1 definitivt<br />

MOVLW b'00000110' ;Stoppa en sexa i ADCON1<br />

;(inga analoga inputs här inte)


MOVWF ADCON1 ;Stoppa mer sexa i ADCON1<br />

MOVLW b'00000000' ;trisa: output = 0<br />

MOVWF<br />

TRISA<br />

MOVLW b'11111101' ;trisb: inputs = 1, RB1=TUTA<br />

MOVWF<br />

TRISB<br />

MOVLW b'10010010' ;sätt falling edge på RB0-interrupt,<br />

;TIMER0 ska lyssna på internal clock<br />

;prescalern ska höra till TMR0 och<br />

; ha skalan 1:8.<br />

MOVWF OPTION_REG ;ladda in i option_reg också, ju.<br />

BCF STATUS, RP0 ;välj bank0<br />

MOVLW b'00000101' ;vi vill skicka "stopp" till<br />

MOVWF PORTA ;styrenheten till att börja med<br />

BSF PORTA,STROBE ;stroben är aktivt låg, så nu ska<br />

;den vara hög<br />

LOOP GOTO LOOP ;här är en oändlig loop.<br />

END


Bilaga B2<br />

Assemblerkod för styrenheten<br />

;**************************************************************<br />

;<br />

; PROGRAM styr<br />

;<br />

; Version 1.1<br />

;<br />

; Skapare Johan Mårtenson och Johan Rees, grupp15<br />

; Skapad 2003-11-25<br />

;<br />

; Ändringar<br />

; 2003-11-25 Kodhuvud tillagt<br />

;<br />

; 2003-11-27 Justering av korsningsdetektion<br />

;<br />

; 2003-11-30 Gå längre in i korsningar<br />

;<br />

; 2003-12-04 Återvändsgränder är ett specialfall.<br />

;<br />

;<br />

;**************************************************************<br />

;<br />

; Programmet hämtar indata från fjärr- och sensorenhet<br />

; och styr utifrån dessa roboten. Algoritmen som används är<br />

; att alltid svänga vänster vilket garanterat för den ut<br />

; ur labyrinten.<br />

;<br />

; Version 1.0: programvaran används i färdig robot<br />

;<br />

; Programmet beror av att det är inkopplat till rätt moduler.<br />

;<br />

.include "m16def.inc"<br />

; Obs! Är KOMMANDO == 0x00 så är vi i autonomt!<br />

.def TEMP = R16<br />

.def LOOP_INDEX3 = R17<br />

.def KOMMANDO = R18<br />

.def AUTO_UT= R19<br />

.def LOOP_INDEX2 = R20<br />

.def SAVE_REGS = R21<br />

.def SENASTE_KORSNING = R22<br />

.def AUTONOM = R23<br />

.def LOOP_INDEX = R24<br />

.def APORTEN = R25<br />

rjmp INIT<br />

; ----- Definierar interruptadresser -----<br />

.org INT0addr<br />

rjmp INT0_INTERRUPT<br />

; Låt INIT börja på 0x50 så blir det inte så trångt i minnet.<br />

.org 0x50<br />

; ----- Init-funktionen ställer i ordning chipet och hoppar sedan till huvudloopen -----<br />

INIT:<br />

; Sätter stackpekaren<br />

ldi TEMP, HIGH(RAMEND)<br />

out SPH, TEMP<br />

ldi TEMP, LOW(RAMEND)<br />

out SPL, TEMP<br />

; Port a går till steg från styr<br />

ldi TEMP, 0xFF<br />

out DDRA, TEMP<br />

; Port b läser ifrån fjärren<br />

ldi TEMP, 0x00<br />

out DDRB, TEMP<br />

; Port d går till sensor<br />

ldi TEMP, 0b11110011 ; Ska vi använda int1 också<br />

out DDRD, TEMP<br />

; Port c går från sensor<br />

ldi TEMP, 0xE0<br />

out DDRC, TEMP


; Slår på externt interrupt på pinne int0.<br />

; Interruptet triggar på negativ flank.<br />

ldi TEMP, (1


out PORTA, TEMP<br />

call VANTA_MELLAN<br />

steg<br />

ldi TEMP, 0x01<br />

out PORTA, TEMP<br />

call VANTA_FJARDE<br />

ori AUTO_UT, 0x01<br />

out PORTD, AUTO_UT<br />

rjmp AUTO_SLUT<br />

; Vänta en stund så vi inte förvirrar steglogiken. Vanta2 måste vänta längre än ett<br />

; Sen så går vi rakt fram igen<br />

; Sätt A1 hög<br />

; Om vi ska justera höger så.<br />

AUTO_ADJ_RIGHT:<br />

; andi AUTO_UT, 0xFe ; A1 låg..<br />

; out PORTD, AUTO_UT<br />

ldi TEMP, 0x04 ; Sväng höger<br />

out PORTA, TEMP<br />

call VANTA_HALV ; Vänta en stund, tidigare halv<br />

ldi TEMP, 0x01 ; Sen så går vi framåt igen<br />

out PORTA, TEMP<br />

call VANTA_FJARDE<br />

ori AUTO_UT, 0x01 ; A1 sätts hög så vi får indata igen<br />

out PORTD, AUTO_UT<br />

rjmp AUTO_SLUT<br />

; Nu har en korsning hittats men vi vet inte vilken sort det är.<br />

AUTO_FOUND:<br />

andi AUTO_UT, 0xFE<br />

out PORTD, AUTO_UT<br />

ldi TEMP, 0x01<br />

out PORTA, TEMP<br />

call VANTA_FJARDE<br />

; call VANTA_HALV<br />

ori AUTO_UT, 0x02<br />

out PORTD, AUTO_UT<br />

; Lägg A1 låg<br />

; Gå framåt<br />

; Gå framåt i en sekund.<br />

; Lägg A2 hög<br />

; Nu har vi hittat en korsning så därför måste vi se<br />

; till att nästa inte kommer för snabbt inpå.<br />

KORSNINGSTYP:<br />

in TEMP, PINC<br />

cpi TEMP, 0x00<br />

breq KORSNINGSTYP<br />

cpi TEMP, 0x1F<br />

breq KORSNINGSTYP<br />

; Läs in från sensor<br />

; Jämför med 0x00<br />

; Loopa ett varv till<br />

nop<br />

nop<br />

nop<br />

in TEMP, PINC ; Förhoppningsvis är signalen stabil nu.<br />

andi AUTO_UT, 0b11111101 ; Lägg A2 låg<br />

out PORTD, AUTO_UT<br />

; Vilken sorts korsning är vi i Gå på lämpligt sätt!<br />

cpi TEMP, 0x02<br />

breq AUTO_LEFT_TURN<br />

cpi TEMP, 0x03<br />

breq AUTO_RIGHT_TURN<br />

cpi TEMP, 0x04<br />

breq AUTO_T_TURN<br />

cpi TEMP, 0x05<br />

breq AUTO_FORWARD_LEFT<br />

cpi TEMP, 0x06<br />

breq AUTO_FORWARD_RIGHT<br />

cpi TEMP, 0x07<br />

breq AUTO_FOUR_WAY<br />

rjmp HUVUDLOOP<br />

; Om vi råkar ut för en vänstersväng så snurrar vi vänster 90 grader.<br />

AUTO_LEFT_TURN:<br />

ldi TEMP, 0x0A ; Snurra 90 grader vänster.<br />

out PORTA, TEMP<br />

call VANTA_LANG ; Vänta så vi hinner svänga helt.<br />

rjmp AUTO_KORSNING_KLAR<br />

; Om vi råkar ut för en högersväng så snurrar vi höger 90 grader.<br />

AUTO_RIGHT_TURN:<br />

ldi TEMP, 0x09 ; Snurra 90 grader höger.<br />

out PORTA, TEMP<br />

call VANTA_LANG ; Vänta så vi hinner svänga helt.<br />

rjmp AUTO_KORSNING_KLAR


; Om vi hamnar i en t-korsning så svänger vi höger.<br />

AUTO_T_TURN:<br />

ldi SENASTE_KORSNING, 0xFF<br />

ldi TEMP, 0x09 ; Snurra 90 grader höger.<br />

out PORTA, TEMP<br />

call VANTA_LANG<br />

; Vänta så vi hinner svänga helt.<br />

rjmp AUTO_KORSNING_KLAR<br />

; Om vi hamnar i en korsning som svänger vänster och går framåt så går vi framåt.<br />

AUTO_FORWARD_LEFT:<br />

ldi TEMP, 0x01 ; Gå framåt.<br />

out PORTA, TEMP<br />

call VANTA_LANG<br />

rjmp AUTO_KORSNING_KLAR<br />

; Om vi hamnar i en korsning som går rakt fram eller höger så väljer vi höger.<br />

AUTO_FORWARD_RIGHT:<br />

ldi TEMP, 0x09 ; Snurra 90 grader höger.<br />

out PORTA, TEMP<br />

call VANTA_LANG<br />

; Vänta så vi hinner börja snurra.<br />

rjmp AUTO_KORSNING_KLAR<br />

; Om vi kommer in i en fyrvägskorsning så svänger vi höger.<br />

AUTO_FOUR_WAY:<br />

ldi SENASTE_KORSNING, 0xFF<br />

rjmp AUTO_FORWARD_RIGHT<br />

; Om vi vet att vi är i mål är det slut!<br />

AUTO_GOAL:<br />

cpi SENASTE_KORSNING, 0x00<br />

breq AUTO_SLUT<br />

ldi KOMMANDO, 0xFF<br />

ldi TEMP, 0x00<br />

out PORTA, TEMP<br />

rjmp HUVUDLOOP<br />

; Om inget behövde göras går vi framåt.<br />

AUTO_NOTHING:<br />

ldi TEMP, 0x01 ; Gå framåt.<br />

out PORTA, TEMP<br />

rjmp AUTO_SLUT<br />

; Efter att vi gått i en korsning går vi framåt igen.<br />

AUTO_KORSNING_KLAR:<br />

ldi TEMP, 0x01 ; Gå framåt.<br />

out PORTA, TEMP<br />

ori AUTO_UT, 0x01 ; Sätt A1 hög.<br />

out PORTD, AUTO_UT<br />

call VANTA_LANG<br />

call VANTA_LANG<br />

call VANTA_LANG<br />

call VANTA_LANG<br />

call VANTA_LANG<br />

call VANTA_LANG<br />

in TEMP, PINC<br />

andi TEMP, 0x1F<br />

cpi TEMP, 0x1F<br />

breq AUTO_GOAL<br />

; Vänta så vi hinner komma ut ur korsningen.<br />

; Vi läser in för att se om vi står i en korsning igen.<br />

; Stod vi i en korsning går vi till AUTO_GOAL<br />

ldi SENASTE_KORSNING, 0x00<br />

; Efter genomförd algoritm sätts A1 hög.<br />

AUTO_SLUT:<br />

ori AUTO_UT, 0x01 ; Sätt A1 hög.<br />

out PORTD, AUTO_UT<br />

rjmp HUVUDLOOP<br />

; Fjarrstyrt hanterar kommandon från fjärrkontrollen.<br />

FJARRSTYRT:<br />

; Hoppa till rätt ställe utifrån kommando<br />

cpi KOMMANDO, 0x00<br />

breq AUTO<br />

cpi KOMMANDO, 0x05<br />

breq STANNA<br />

cpi KOMMANDO, 0x01<br />

breq FRAM<br />

cpi KOMMANDO, 0x02<br />

breq BAK<br />

cpi KOMMANDO, 0x04<br />

breq SVANG_VANSTER<br />

cpi KOMMANDO, 0x03<br />

breq SVANG_HOGER


; Var kommando inget av ovanstående går vi ur fjarrstyrt.<br />

rjmp LOOP_SLUT<br />

; Gick vi precis in i autonomt läge så gör vi det.<br />

AUTO:<br />

ldi KOMMANDO, 0x00 ; Nu gick vi in i autonomt läge.<br />

rjmp HUVUDLOOP<br />

; Nu ska vi stå still.<br />

STANNA:<br />

ldi TEMP, 0x00<br />

rjmp LOOP_SLUT<br />

; Nu ska vi gå framåt.<br />

FRAM:<br />

ldi TEMP, 0x01<br />

rjmp LOOP_SLUT<br />

; Nu ska vi gå bakåt.<br />

BAK:<br />

ldi TEMP, 0x02<br />

rjmp LOOP_SLUT<br />

; Säg åt steg att inte göra någonting.<br />

; Säg åt steg att gå framåt.<br />

; Gå bakåt.<br />

; Nu ska vi svänga vänster.<br />

SVANG_VANSTER:<br />

ldi TEMP, 0x03 ; Sväng vänster.<br />

rjmp LOOP_SLUT<br />

; Nu ska vi svänga höger.<br />

SVANG_HOGER:<br />

ldi TEMP, 0x04 ; Sväng höger.<br />

rjmp LOOP_SLUT<br />

; Nu ska vi snurra 180 grader.<br />

; SNURRA:<br />

; ldi TEMP, 0x05<br />

; rjmp LOOP_SLUT<br />

; Förflytta parallellt höger.<br />

PARALLELL_HOGER:<br />

ldi TEMP, 0x06 ; Parallellförflytta höger.<br />

rjmp LOOP_SLUT<br />

; Förflytta parallellt vänster.<br />

PARALLELL_VANSTER:<br />

ldi TEMP, 0x07 ; Parallellförflytta vänster.<br />

rjmp LOOP_SLUT<br />

; Sista anhalten innan funktionen är klar.<br />

LOOP_SLUT:<br />

out PORTA, TEMP ; Lägg ut temp på porta, dvs kommandot till steg.<br />

rjmp HUVUDLOOP<br />

; ----- Vanta2 gör en busyloop i XX sekunder -----<br />

VANTA2:<br />

; Vi nollställer ett loopindex innan loopen.<br />

ldi LOOP_INDEX, 0x00<br />

; Här kommer den yttre loopen<br />

VANTA2_VANTA:<br />

; Jämför loopindex med 0xFF för att se om vi är klara.<br />

cpi LOOP_INDEX, 0xFF<br />

breq VANTA2_KLART<br />

; Annars ökar vi loopindex med 1.<br />

inc LOOP_INDEX<br />

; Nollställ andra loopindex-variabeln.<br />

ldi LOOP_INDEX2, 0x00<br />

; Här kommer den inre loopen.<br />

VANTA2_VANTA_INTERN:<br />

; Jämför andra loopindex med 0xFF för att se om vi är klara.<br />

cpi LOOP_INDEX2, 0xFF<br />

breq VANTA2_KLART_INTERN<br />

; Annars ökar vi andra loopindex med 1 och lägger till några nop:ar för att<br />

; förlänga loopen.<br />

inc LOOP_INDEX2<br />

nop<br />

nop<br />

nop<br />

nop<br />

; Loopa ett varv till i inre loopen.


jmp VANTA2_VANTA_INTERN<br />

VANTA2_KLART_INTERN:<br />

; Loopa ett varv till i yttre loopen.<br />

rjmp VANTA2_VANTA<br />

VANTA2_KLART:<br />

ret<br />

; ----- Vanta kör en loop och anropar inne i den vanta2 -----<br />

VANTA:<br />

ldi LOOP_INDEX3, 0x00<br />

VANTA_INTERN:<br />

cpi LOOP_INDEX3, 0x01<br />

breq VANTA_KLAR<br />

inc LOOP_INDEX3<br />

call VANTA2<br />

rjmp VANTA_INTERN<br />

VANTA_KLAR:<br />

ret<br />

; ----- Vanta_lang vantar en längre stund -----<br />

VANTA_LANG:<br />

ldi LOOP_INDEX3, 0x00<br />

VANTA_LANG_INTERN:<br />

cpi LOOP_INDEX3, 0x08<br />

breq VANTA_LANG_KLAR<br />

inc LOOP_INDEX3<br />

call VANTA2<br />

rjmp VANTA_LANG_INTERN<br />

VANTA_LANG_KLAR:<br />

ret<br />

; ----- Vanta_halv väntar hälften så länge som vanta_lang -----<br />

VANTA_HALV:<br />

ldi LOOP_INDEX3, 0x00<br />

VANTA_HALV_INTERN:<br />

cpi LOOP_INDEX3, 0x08<br />

breq VANTA_HALV_KLAR<br />

inc LOOP_INDEX3<br />

call VANTA2<br />

rjmp VANTA_HALV_INTERN<br />

VANTA_HALV_KLAR:<br />

ret<br />

; ----- Vanta_fjarde väntar hälften så mycket som vanta_fjarde -----<br />

VANTA_FJARDE:<br />

ldi LOOP_INDEX3, 0x00<br />

VANTA_FJARDE_INTERN:<br />

cpi LOOP_INDEX3, 0x04<br />

breq VANTA_FJARDE_KLAR<br />

inc LOOP_INDEX3<br />

call VANTA2<br />

rjmp VANTA_FJARDE_INTERN<br />

VANTA_FJARDE_KLAR:<br />

ret<br />

; ----- Vanta_mellan väntar nästan lika länge som vanta_halv -----<br />

VANTA_MELLAN:<br />

ldi LOOP_INDEX3, 0x00<br />

VANTA_MELLAN_INTERN:<br />

cpi LOOP_INDEX3, 0x07<br />

breq VANTA_MELLAN_KLAR<br />

inc LOOP_INDEX3<br />

call VANTA2<br />

rjmp VANTA_MELLAN_INTERN<br />

VANTA_MELLAN_KLAR:<br />

ret<br />

; ----- Interruptrutiner-----<br />

INT0_INTERRUPT:<br />

in SAVE_REGS, SREG<br />

mov R14, KOMMANDO<br />

in KOMMANDO, PINB<br />

andi KOMMANDO, 0x07 ;rees har ändrat från 03 till 07<br />

cpi KOMMANDO, 0x00<br />

breq INT0_KANSKE_INT ; Autonomt av/på<br />

out SREG, SAVE_REGS<br />

reti<br />

INT0_KANSKE_INT:<br />

mov KOMMANDO, R14 ; Lägg in r14 i kommando<br />

cpi KOMMANDO, 0x00 ; är kommando 0x00 ...<br />

breq INT0_TILL_AUTO ; .. så går vi till int0_till_auto<br />

cpi KOMMANDO, 0xFF<br />

breq INT0_TILL_AUTO<br />

ldi KOMMANDO, 0x00 ; Dessutom sätts KOMMANDO till 0x05 så att vi står still<br />

andi AUTO_UT, 0b11111100


out PORTD, AUTO_UT<br />

out SREG, SAVE_REGS<br />

reti<br />

INT0_TILL_AUTO:<br />

ori AUTO_UT, 0b00000001<br />

ldi KOMMANDO, 0x05<br />

out SREG, SAVE_REGS<br />

reti


Bilaga C2<br />

Assemblerkod för sensorenheten<br />

;**************************************************************<br />

;<br />

; PROGRAM sensor<br />

;<br />

; Version 1.0<br />

;<br />

; Skapare Mattias Lennartsson och David Landén, grupp15<br />

; Skapad ht2003<br />

;<br />

;**************************************************************<br />

;<br />

; Programmet hämtar mätvärden från tre sensorer (fram,<br />

; höger och vänster), beräknar medelvärdet av de två mätningar<br />

; som är bäst av tre och skickar utifrån dessa värden signaler<br />

; till styrenheten om hitta korsning, korrigering eller korsningstyp.<br />

;<br />

; Version 1.0: programvaran används i färdig robot<br />

; ******************************************<br />

; Definitioner<br />

; ******************************************<br />

#INCLUDE<br />

"P16f870.INC"<br />

TITLE<br />

"sensor"<br />

LIST P=16f870, F=INHX8M<br />

__CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON<br />

;Signaler (inte variabler)<br />

SIGN_FEL equ 0x00<br />

SIGN_ATERV equ 0x01<br />

SIGN_VANSTER equ 0x02<br />

SIGN_HOGER equ 0x03<br />

SIGN_T equ 0x04<br />

SIGN_FV equ 0x05<br />

SIGN_FH equ 0x06<br />

SIGN_FYRV equ 0x07<br />

;Variabler för main etc.<br />

COUNT equ 0x20 ;Räknarvariabel loopar<br />

DEBUG equ 0x21<br />

;Variabler för avb<br />

ST_TEMP equ 0x40 ;Undanlagrade STATUS och W<br />

W_TEMP equ 0x41<br />

TID_START equ 0x43 ;0xff -> Mätning av sensorer har startat<br />

;0x00 -> Mätningen väntar på svar från sensor<br />

NU_SENSOR equ 0x44 ;Aktuell sensor/mätning<br />

NU_MATNING equ 0x45<br />

MV1 equ 0x46 ;Tillfälliga mätvärden för mätningarna<br />

MV2 equ 0x47<br />

MV3 equ 0x48<br />

TEMP equ 0x49 ;Generell variabel<br />

SENSOR1_MV equ 0x50 ;Sensorernas mätvärden<br />

SENSOR2_MV equ 0x51<br />

SENSOR3_MV equ 0x52<br />

SENSOR4_MV equ 0x53<br />

;Sensor 1 -> Höger<br />

;Sensor 2 -> Vänster<br />

;Sensor 3 -> Fram (fd Vänster bak)<br />

V_AB equ 0x54 ;används av VALJ_VARDE<br />

V_AC equ 0x55<br />

V_BC equ 0x56<br />

MATNING_PA equ 0x57 ;Stänger av timer1 (mätningen) fast uppdaterar utvärdet<br />

;på timer interrupt<br />

MAT_BYTE equ 0x58 ;Används av UPPD_UTV


OK_MATV equ 0x59 ;är 0xff om det finns ett mätvärde i minnet<br />

; annars har den värdet 0x00<br />

; Blir inaktuellt då det används eller<br />

;om timerrutinern körs och värdet ligger kvar<br />

SENSOR1_SLAP equ 0x60 ;Släp-värden för sensor 1 resp 2.<br />

SENSOR2_SLAP equ 0x61 ; - -<br />

SENSOR1_SLAP1 equ 0x62 ;Släp värden, nivå 2<br />

SENSOR2_SLAP1 equ 0x63<br />

SENSOR1_SLAP2 equ 0x64 ;Släp värden, nivå 3<br />

SENSOR2_SLAP2 equ 0x65<br />

SENSOR1_SLAP3 equ 0x66 ;Släp värden, nivå 4<br />

SENSOR2_SLAP3 equ 0x67<br />

SENSOR1_SLAP4 equ 0x68 ;Släp värden, nivå 5<br />

SENSOR2_SLAP4 equ 0x69<br />

SENSOR1_SLAP5 equ 0x6a ;Släp värden, nivå 6<br />

SENSOR2_SLAP5 equ 0x6b<br />

SENSOR1_SLAP6 equ 0x6c ;Släp värden, nivå 7<br />

SENSOR2_SLAP6 equ 0x6d<br />

SENSOR1_SLAP7 equ 0x6e ;Släp värden, nivå 8<br />

SENSOR2_SLAP7 equ 0x6f<br />

SENSOR1_SLAP8 equ 0x70 ;Släp värden, nivå 9<br />

SENSOR2_SLAP8 equ 0x71<br />

SENSOR1_SLAP9 equ 0x72 ;Släp värden, nivå 10<br />

SENSOR2_SLAP9 equ 0x73<br />

dMV equ 0x74 ;Diff mellan mv 1 och mv 2<br />

Hmin equ 0x75<br />

Vmin equ 0x76<br />

KORSNING_ALLERT equ<br />

0x77<br />

; *** OBS 0x7F sista adress för General Perpose Registers ***<br />

; ******************************************<br />

; Programminnet<br />

; ******************************************<br />

ORG<br />

GOTO<br />

ORG<br />

GOTO<br />

0x00<br />

MAIN<br />

0x04<br />

AVB<br />

; ******************************************<br />

; Avbrottsrutin<br />

; ******************************************<br />

AVB MOVWF W_TEMP ;Spara undan W<br />

MOVF STATUS,W ;Spara undan STATUS<br />

MOVWF ST_TEMP ; - -<br />

BTFSC INTCON,T0IF ;Avbrotts flagga för timer 0<br />

CALL TIMER0_AVB ;Hoppa till timer avbrott<br />

BTFSC PIR1,0 ;Avbrotts flagga för timer 0<br />

CALL TIMER1_AVB ;Hoppa till timer avbrott<br />

MOVLW 0xF8 ;Maska ut interrupt bitarna (0-3)<br />

ANDWF INTCON,F ;i INTCON registret (avbrottsflaggor)<br />

BCF INTCON,INTE ;Inge interrupts från RB0/INT<br />

BCF PIR1,0 ;Nollställ avbrottsflaggan för timer1<br />

BSF INTCON,7 ;GIE på<br />

MOVF ST_TEMP,w ;Återställ W och STATUS<br />

MOVWF<br />

STATUS<br />

MOVF<br />

W_TEMP,w<br />

RETFIE<br />

;Returnera från avbrott<br />

; ******************************************<br />

; Subrutin Timer0 Avbrott


; ******************************************<br />

TIMER0_AVB<br />

BCF STATUS,5 ;Bank 0<br />

BCF STATUS,6 ; - -<br />

MOVF PORTB,w ;Läs porten till W<br />

MOVWF TEMP ;W -> TEMP<br />

BCF STATUS,C ;Rotera temp 4bit höger<br />

RRF<br />

TEMP,f<br />

BCF<br />

STATUS,C<br />

RRF<br />

TEMP,f<br />

BCF STATUS,C ;Rotera temp 4bit höger<br />

RRF<br />

TEMP,f<br />

BCF STATUS,C ;Rotera temp 4bit höger<br />

RRF<br />

TEMP,f<br />

MOVF TEMP,W ;TEMP->W<br />

ANDWF NU_SENSOR,w ;Maska ut biten från sensorn<br />

BTFSC STATUS,Z ;Mät av sensorn<br />

;maskades alla bitar bort -> 0, annars -> 1<br />

GOTO KLAR ;om sensorns utvärde är 0, gå till klar<br />

MOVLW<br />

0xFF<br />

MOVWF TID_START ;Markera att vi tagit emot en puls<br />

;BTFSC NU_MATNING,0 ;Räkna upp rätt mätvärde<br />

;INCF<br />

MV1,f<br />

;BTFSC NU_MATNING,1 ; - -<br />

;INCF<br />

MV2,f<br />

;BTFSC NU_MATNING,2 ; - -<br />

;INCF<br />

MV3,f<br />

BTFSC NU_MATNING,0 ;Läs ned till TEMP<br />

MOVF<br />

MV1,w<br />

BTFSC NU_MATNING,1 ; - -<br />

MOVF<br />

MV2,w<br />

BTFSC NU_MATNING,2 ; - -<br />

MOVF<br />

MV3,w<br />

MOVWF TEMP ;Läs W till TEMP<br />

INCF TEMP,f ;Öka TEMP<br />

MOVLW 0x7f ;Ladda W med 0xff<br />

BTFSC TEMP,7 ;Är högsta biten satt<br />

MOVWF TEMP ;Skriv 0x7f till MV (alltså öka inte mer)<br />

MOVF<br />

TEMP,w<br />

BTFSC NU_MATNING,0 ;Läs upp till mätvärdet<br />

MOVWF<br />

MV1<br />

BTFSC NU_MATNING,1 ; - -<br />

MOVWF<br />

MV2<br />

BTFSC NU_MATNING,2 ; - -<br />

MOVWF<br />

MV3<br />

;BTFSC STATUS,Z ;Är zero biten satt<br />

;GOTO FULL<br />

;Räkna tillbaka detta värde<br />

RETURN<br />

KLAR<br />

BTFSS TID_START,0 ;Har vi inte ännu tagit emot en puls så är<br />

RETURN<br />

;vi inte klara ännu.<br />

;Vänta tills det kommer en puls<br />

BCF INTCON,T0IE ;Stäng av timern (mätningen klar)<br />

RETURN<br />

; ******************************************<br />

; Subrutin Timer1 Avbrott<br />

; ******************************************<br />

TIMER1_AVB<br />

BTFSS MATNING_PA,0 ;Är matningen på eller avslagen<br />

GOTO MATNING_AR_AV ;Är den av -> MATNING_AR_AV


CLRF TID_START ;nollställ tidmätningen<br />

;aktiveras av att pulsen kommer från sensorn<br />

BCF STATUS,C ;Rotera in nolla<br />

RLF NU_MATNING,f ;Nästa mätning (roter vänster en bit)<br />

BTFSC NU_MATNING,3 ;Har nu_matning gjort overflow (sensor 5)<br />

GOTO OF_MATN ;I så fall -> OF_MATN (=OverFlow_Matning)<br />

FORTS_MATN<br />

;Forts, NU_MATN och NU_SENSOR ska vara uppdaterade<br />

;till nästa mätning, nästa sensor<br />

; *** Läs av rätt sensor ***<br />

BTFSC NU_SENSOR,0 ;Sätt sensorn trigger-signal till hög<br />

BSF<br />

PORTB,0<br />

BTFSC<br />

NU_SENSOR,1<br />

BSF<br />

PORTB,1<br />

BTFSC<br />

NU_SENSOR,2<br />

BSF<br />

PORTB,2<br />

BTFSC<br />

NU_SENSOR,3<br />

BSF<br />

PORTB,3<br />

CALL WAIT_LOOP ;Vänta ett litet tag<br />

BCF<br />

BCF<br />

BCF<br />

BCF<br />

PORTB,0<br />

PORTB,1<br />

PORTB,2<br />

PORTB,3<br />

; *** starta timern ***<br />

CLRF TMR0 ;Nollställ interrupt räknaren<br />

BSF INTCON,T0IE ;Slå på timer 0<br />

MOVLW 0xf8 ;Interruptbitarna av<br />

ANDWF<br />

INTCON,f<br />

RETURN ;*** Klar!! Återgå till avbrottsrutin ***<br />

OF_MATN<br />

;Overflow mätning (subrutin utan CALL)<br />

;Mätning av nästa sensor ska startas<br />

CALL VALJ_VARDE ;Välj ut vilket värde som ska sparas<br />

;(och spara detta)<br />

MOVLW 0x01 ;Börja med nästa mätning<br />

MOVWF NU_MATNING ;Mätning 1<br />

BCF STATUS,C ;Rotera in nolla<br />

RLF NU_SENSOR,f ;Nästa sensor<br />

CLRF MV1 ;Nollställ mätvärdet<br />

CLRF<br />

MV2<br />

CLRF<br />

MV3<br />

MOVLW<br />

0xff<br />

BTFSC NU_SENSOR,4 ;Har sensor gjort overflow<br />

MOVWF OK_MATV ;Ett OK mätvärde ligger i minnet<br />

BTFSC NU_SENSOR,4 ;Har sensor gjort overflow<br />

CALL<br />

UPPD_UTV<br />

MOVLW<br />

0x01<br />

BTFSC NU_SENSOR,4 ;Har sensor gjort overflow<br />

MOVWF NU_SENSOR ;Sätt sensor till sensor 1<br />

GOTO FORTS_MATN ;Fortsätt (NU_MATN, NU_SENSOR uppdaterade)<br />

WAIT_LOOP<br />

;Gör en torrloop i ett par operationer<br />

;(min 10us)<br />

MOVLW 0x30 ;i 0x30 x 2 operationer<br />

MOVWF<br />

COUNT<br />

LOOP0 decfsz COUNT,1 ; - -<br />

goto LOOP0<br />

MOVLW 0xfc ;Starta med högt värde i räknar reg.<br />

BTFSC<br />

DEBUG,0


MOVWF<br />

TMR1H<br />

RETURN<br />

MATNING_AR_AV ; *+*+*+* Mätningen är av, ingen mätning ska göras *+*+*+*<br />

;endast uppdatering av utvärden och nollställ mätvärden<br />

CALL UPPD_UTV<br />

;Uppdatera utvärden på portarna<br />

CLRF OK_MATV ;Det gamla mätvärdet är inaktuellt<br />

MOVLW 0x01 ;Nollställ sensor och matning<br />

MOVWF NU_MATNING ;(förbered för ny mätning)<br />

MOVWF NU_SENSOR ; - -<br />

CLRF MV1 ; - -<br />

CLRF<br />

MV2<br />

CLRF<br />

MV3<br />

CLRF SENSOR1_MV ; - -<br />

CLRF<br />

SENSOR2_MV<br />

CLRF<br />

SENSOR3_MV<br />

CLRF<br />

SENSOR4_MV<br />

MOVLW<br />

0xfc<br />

BTFSC DEBUG,0 ;Snabba upp timern i DEBUG mode<br />

MOVWF<br />

TMR1H<br />

RETURN<br />

;Returnera till avbrottsrutinen...<br />

;Denna rutinen anropas med GOTO<br />

; ******************************************<br />

; Välj Mätvärde (och spara undan det)<br />

; ******************************************<br />

VALJ_VARDE<br />

MOVF MV1,w ; * Beräkna differensen mellan mätvärdena *<br />

MOVWF V_AB ;MV1->AB<br />

MOVF MV2,w ;MV2->w<br />

SUBWF V_AB,f ;AB(mv1) - w(mv2) -> V_AB<br />

BTFSC V_AB,7 ;Är talet negativt<br />

COMF V_AB,f ;Invertera talet (så det blir positivt)<br />

MOVF MV1,w ; - - (med AC)<br />

MOVWF V_AC ; - -<br />

MOVF<br />

MV3,w<br />

SUBWF<br />

V_AC,f<br />

BTFSC<br />

V_AC,7<br />

COMF<br />

V_AC,f<br />

MOVF MV2,w ; - - (med BC)<br />

MOVWF V_BC ; - -<br />

MOVF<br />

MV3,w<br />

SUBWF<br />

V_BC,f<br />

BTFSC<br />

V_BC,7<br />

COMF<br />

V_BC,f<br />

;V_AB, V_AC, V_BC inehåller<br />

;(den positiva) differensen mellan mätvärdena<br />

MOVF V_AB,w ;** Vilken av differenserna är minst **<br />

SUBWF V_AC,w ;Börja med att jämföra AB och AC<br />

MOVWF TEMP ;Skriv (AC-AB) till TEMP<br />

BTFSS TEMP,7 ;Om negativt AB > AC<br />

GOTO AB_MINST_AV ;Alltså skippa om negativt<br />

MOVF V_BC,w ;Vilken är minst av AC, BC<br />

SUBWF V_AC,w ; - -<br />

MOVWF TEMP ;TEMP = (AC-BC)<br />

BTFSS TEMP,7 ;Om negativt (BC > AC)<br />

GOTO BC_MINST ;Inte negativt BC är minst<br />

GOTO AC_MINST ;Negativt BC är störst -> AC är minst<br />

AB_MINST_AV<br />

; Differensen AB är minst (av AB och AC)<br />

MOVF V_BC,w ;Vilken är minst av AB, BC<br />

SUBWF V_AB,w ; - -<br />

MOVWF TEMP ;TEMP = (AB-BC)<br />

BTFSS TEMP,7 ;Om negativt (BC > AB)<br />

GOTO BC_MINST ;Inte negativt BC är minst<br />

GOTO AB_MINST ;Negativt BC är störst -> AB är minst<br />

; *** Beräkna medel ***


AB_MINST<br />

MOVF MV1,w ;mv1 -> w<br />

ADDWF MV2,w ;mv1 + mv2 -> w<br />

MOVWF<br />

TEMP<br />

BCF<br />

STATUS,C<br />

RRF TEMP,f ;Dividera talet med 2 (heltalsdivision)<br />

GOTO<br />

FORTS_VALJ0<br />

AC_MINST<br />

MOVF MV1,w ;mv1 -> w<br />

ADDWF MV3,w ;mv1 + mv3 -> w<br />

MOVWF<br />

TEMP<br />

BCF<br />

STATUS,C<br />

RRF TEMP,f ;Dividera talet med 2 (heltalsdivision)<br />

GOTO<br />

FORTS_VALJ0<br />

BC_MINST<br />

MOVF MV2,w ;MV2 -> w<br />

ADDWF MV3,w ;MV2 + MV3 -> w<br />

MOVWF<br />

TEMP<br />

BCF<br />

STATUS,C<br />

RRF TEMP,f ;Dividera talet med 2 (heltalsdivision)<br />

GOTO<br />

FORTS_VALJ0<br />

FORTS_VALJ0 ; *** Forts ***<br />

;Skriv TEMP till rätt sensorvärde<br />

MOVF TEMP,w ;Läs mätvärdet till W<br />

BTFSC NU_SENSOR,0 ;Skriv värdet till rätt adress<br />

MOVWF<br />

SENSOR1_MV<br />

BTFSC<br />

MOVWF<br />

BTFSC<br />

MOVWF<br />

BTFSC<br />

MOVWF<br />

NU_SENSOR,1<br />

SENSOR2_MV<br />

NU_SENSOR,2<br />

SENSOR3_MV<br />

NU_SENSOR,3<br />

SENSOR4_MV<br />

RETURN<br />

;Klar - Valt och sparat värdet<br />

; ******************************************<br />

; Huvudprogram<br />

; ******************************************<br />

MAIN<br />

MOVLW 0x00 ;DEBUG på eller av 0x00 av, 0xff på<br />

MOVWF<br />

DEBUG<br />

;----------------------<br />

;Initiera portarna<br />

;Port A - Output (signal till styrenhet)<br />

;RA5 Strobe<br />

;RA4 Signaltyp<br />

;RA0-3 Signal<br />

;Port C - Input (signal från styrenhet)<br />

;RC4 Korridor (A1, korsning)<br />

;RC5 Korsning (A2, korridor)<br />

;Port B - Input/Output (signal till/från sensorer)<br />

;RB4-7 Input (mätvärde från sensorerna, echo-out)<br />

;RB0-3 Output (trigger-signal till sensorerna)<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF STATUS,6 ; - -<br />

CLRF<br />

PORTA<br />

CLRF PORTB ;sätt utvärden till 0x0<br />

CLRF<br />

PORTC<br />

BSF STATUS,5 ;Byt till bank 1<br />

BCF STATUS,6 ; - -<br />

MOVLW 0x00 ;Ladda W med 0x00


MOVWF TRISA ;Skriv 0x00 till TRISA<br />

;Port A output<br />

MOVLW 0xF0 ;Ladda W med 0xF0<br />

MOVWF TRISB ;Skriv 0xF0 till TRISB<br />

;Port B input/output<br />

MOVLW 0xFF ;Ladda W med 0xFF<br />

MOVWF TRISC ;Skriv 0xFF till TRISC<br />

;Port C input (tristate)<br />

BCF STATUS, RP1 ;Initiera port A som digital input<br />

BSF STATUS, RP0 ;Bank 1<br />

MOVLW 0x06<br />

MOVWF ADCON1<br />

;Configure all pins<br />

;as digital inputs<br />

;----------------------<br />

;Initiera timer 0<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF<br />

STATUS,6<br />

CLRF TMR0 ;Nollställ timerns räknarregister<br />

BSF STATUS,5 ;Byt till bank 1<br />

BSF INTCON,GIE ;GIE på<br />

BCF INTCON,T0IE ;T0IE av, sätts på av T1<br />

BCF INTCON,T0IF ;Avbrottsflagga av<br />

MOVLW 0xf8 ;Interruptbitarna av<br />

ANDWF<br />

INTCON,f<br />

MOVLW 0x48 ;Ingen prescaler...<br />

MOVWF<br />

OPTION_REG<br />

BCF STATUS,5 ;Byt till bank 0<br />

;----------------------<br />

;Initiera Timer 1<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF STATUS,6 ; - -<br />

CLRF TMR1L ;Nollställ avbrottsräknaren<br />

CLRF TMR1H ; - -<br />

;DEBUG - Snabba upp TMR1 lite så det går att debugga...<br />

MOVLW 0xfc ;Starta med högt värde i räknar reg.<br />

BTFSC<br />

DEBUG,0<br />

MOVWF<br />

TMR1H<br />

BSF INTCON,6 ;Periperal Interrupt Enable på<br />

BCF PIR1,0 ;Avbrottsflaggan av<br />

(för säkerhets skull)<br />

MOVLW 0x15 ;OSC av, inte ext sync, internal clock<br />

MOVWF T1CON ;delning med 1:2!! + Timer ON:<br />

BSF STATUS,5 ;Byt till bank 1<br />

BCF STATUS,6 ; - -<br />

BSF PIE1,0 ;Timer1 Interrupt enable<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF STATUS,6 ; - -<br />

;----------------------<br />

;Initiera input (B4-B7)<br />

;Stäng av interupt från port<br />

BCF<br />

INTCON,RBIE<br />

BCF INTCON,INTE ;Inga interrupts från RB0/INT<br />

;BSF INTCON,GIE ;Antas redan vara satt,<br />

;behöver inte sättas<br />

BSF STATUS,5 ;Byt till bank 1<br />

BCF STATUS,6 ; - -


BCF OPTION_REG,INTEDG ;Trigga interrupt på positiv flank<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF STATUS,6 ; - -<br />

;----------------------<br />

;Övrigt<br />

CLRF MV1 ;Nollställ mätvärdena<br />

CLRF MV2 ; - -<br />

CLRF MV3 ; - -<br />

CLRF OK_MATV ;Inget OK mätvärde ännu...<br />

MOVLW<br />

0x01<br />

MOVWF NU_SENSOR ;aktuell sensor 1<br />

MOVWF NU_MATNING ;aktuell mätning 1<br />

MOVLW<br />

0x00<br />

MOVWF SENSOR1_SLAP ;0 till släpvärdet (korrigering)<br />

MOVWF<br />

SENSOR2_SLAP<br />

MOVLW<br />

0x00<br />

MOVWF SENSOR1_SLAP1 ;0 till släpvärdet (korrigering)<br />

MOVWF<br />

SENSOR2_SLAP1<br />

MOVLW<br />

0x00<br />

MOVWF SENSOR1_SLAP2 ;0 till släpvärdet (korrigering)<br />

MOVWF<br />

SENSOR2_SLAP2<br />

MOVLW<br />

0x00<br />

MOVWF SENSOR1_SLAP3 ;0 till släpvärdet (korrigering)<br />

MOVWF<br />

SENSOR2_SLAP3<br />

MOVLW 0x7f ;ettställ minvärdet<br />

MOVWF Hmin ;från början<br />

MOVWF<br />

Vmin<br />

CLRF<br />

KORSNING_ALLERT<br />

CLRF MATNING_PA ;Mätningen av från början....<br />

;DEBUG - slå på mätningen<br />

MOVLW<br />

BTFSC<br />

MOVWF<br />

0xff<br />

DEBUG,0<br />

MATNING_PA<br />

STOP NOP ;Stanna och vänta på avbrott...<br />

NOP ; - -<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

NOP<br />

GOTO STOP<br />

; ******************************************<br />

; Uppdatera utvärden<br />

; ******************************************<br />

UPPD_UTV<br />

;Denna funktionen ska köras när (1) styrenheten ändrar invärde<br />

;eller (2) när sensor-mätvärdet är klart eller (3)<br />

;vid timerinterrupt (tmr1) och MATNING_PA är av.<br />

;(0x00) I fall att vi skulle råka missa<br />

;positiv flank... (annat avbrott)<br />

BCF STATUS,5 ;Byt till bank 0<br />

BCF STATUS,6 ; - -<br />

BTFSC PORTC,4 ;Eller A2 på -> A2 (korsning)<br />

GOTO<br />

A2<br />

;Eller ingen:<br />

BTFSC PORTC,5 ;Vilket invärde har vi<br />

GOTO A1 ;Är A1 på -> A1 (korridor)<br />

CLRF PORTA ;Ingen utsignal<br />

CLRF MATNING_PA ;Ingen mätning då ingen pinna är på<br />

CLRF OK_MATV ;Mätvärdet inaktuellt (gammalt)


RETURN<br />

;Från UPPD_UTV!!<br />

A1 ; *** A1 hög, vi befinner oss i en korsning ***<br />

BTFSS OK_MATV,0 ;Finns det ett OK mätvärde<br />

GOTO EJ_MATV ;om inte -> EJ_MATV<br />

;1. Bestäm vilka sensorer som är aktiva<br />

CLRF<br />

MAT_BYTE<br />

MOVLW 0x2d ;Ladda W med 0x2d = 45 =~ 50cm<br />

SUBWF SENSOR3_MV,w ;Ligger mätvärdet under fram(),<br />

;sätt biten till 1<br />

MOVWF TEMP ;(0x2d-w) = TEMP<br />

BTFSC TEMP,7 ;Om TEMP negativt, MV över<br />

BSF MAT_BYTE,2 ;Skippa ej negativt (sign-biten är satt)<br />

MOVLW 0x28 ;Ladda W med 0x14 = 40 =~ 45cm<br />

SUBWF SENSOR1_MV,w ;Ligger mätvärdet under, sätt biten till 1<br />

MOVWF TEMP ;(0x14-w) = TEMP<br />

BTFSC TEMP,7 ;Ar TEMP negativt, mätvärdet större<br />

BSF MAT_BYTE,0 ;allts[ skippa om negativt<br />

MOVLW 0x28 ; - -<br />

SUBWF SENSOR2_MV,w ; - -<br />

MOVWF<br />

TEMP<br />

BTFSC<br />

TEMP,7<br />

BSF<br />

MAT_BYTE,1<br />

;2. Bestäm vilket värde den sensoruppställningen ger<br />

;Denna koden för återvändsgränd skulle kunna tas bort...<br />

MOVLW 0x7 ; Återvändsgränd<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_ATERV<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x5 ; Vänsterkorsning<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_VANSTER<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x6 ; Högerkorsning<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_HOGER<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x4 ; T-Korsning<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_T<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x1 ; Fram & Vänster<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_FV<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x2 ; Fram & Höger<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_FH<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x0 ; Fyrvägskorsning<br />

SUBWF MAT_BYTE,w ; - -<br />

BTFSC STATUS,Z ; - -<br />

MOVLW<br />

SIGN_FYRV<br />

BTFSC STATUS,Z ; - -<br />

MOVWF<br />

PORTA<br />

MOVLW 0x3 ; Mätfel...<br />

SUBWF MAT_BYTE,w ; - -


BTFSC STATUS,Z ; - -<br />

GOTO<br />

SKRIV_FEL<br />

GOTO FORTS_KORSN ;Hoppa över skrivfel<br />

SKRIV_FEL<br />

MOVLW SIGN_FEL ;Annan korsning, skriv fel...<br />

MOVWF<br />

PORTA<br />

FORTS_KORSN<br />

BCF PORTA,5 ;Utsignalen är av typ korsning<br />

CLRF OK_MATV ;Det gamla mätvärdet är inaktuellt<br />

RETURN<br />

;Klar - Signal på utporten<br />

A2 ; *** A2 hög, vi befinner oss i en korridor ***<br />

BTFSS OK_MATV,0 ;Finns det ett OK matvärde<br />

GOTO EJ_MATV ;om inte -> EJ_MATV<br />

;Högerkorsning<br />

MOVLW 0x4b ;Ladda W med 0x4b = 75 =~ 80cm<br />

SUBWF SENSOR1_MV,w ;Ligger mätvärdet över,<br />

;sätt utvärdet till korsning<br />

MOVWF TEMP ;0x16 minus mv = temp<br />

BTFSS TEMP,7 ; - -<br />

GOTO<br />

KORSN_UT<br />

;Vänsterkorsning<br />

MOVLW 0x4b ; - -<br />

SUBWF SENSOR2_MV,w ; - -<br />

MOVWF TEMP ; - -<br />

BTFSS TEMP,7 ; - -<br />

GOTO<br />

KORSN_UT<br />

CLRF<br />

KORSNING_ALLERT ;Ingen korsning den här gången,<br />

;-> false alarm<br />

;Återvändsgränd (lägst prioritet = ej länge)<br />

MOVLW 0x0d ;Ladda W med 0x08 = 8 =~ 10cm<br />

SUBWF SENSOR3_MV,w ;Ligger mätvärdet under,<br />

;sätt utvärdet till korsning<br />

MOVWF TEMP ;0x19 minus mv = temp<br />

BTFSC TEMP,7 ; - -<br />

GOTO<br />

KORSN_AT_UT<br />

;Hoppa till INGEN_KORR om värdet ökar,<br />

;i så fall ska ingen korrigering göras<br />

;DEN NYA KODEN...<br />

testa<br />

MOVLW 0x09 ;a till w ;ob förut<br />

SUBWF SENSOR2_MV,w ;sensor2-a<br />

MOVWF<br />

TEMP<br />

BTFSC<br />

TEMP,7<br />

GOTO KORR_H ;sensor2 - a0, alltså allt är OK<br />

SUBWF SENSOR1_MV,w ;sensor1-a istället för W<br />

MOVWF<br />

TEMP<br />

BTFSC<br />

TEMP,7<br />

GOTO KORR_V ;sensor1 - a


;Undersök om mätvärdet ligger under minvärdet<br />

MOVF TEMP,w ;Ladda W med minvärdet<br />

SUBWF SENSOR2_MV,w ;Substrahera.. ;Kommentarer fel igen...<br />

MOVWF TEMP ;(min - mv) -> TEMP<br />

BTFSS TEMP,7 ;Om TEMP negativt, ingen korrigering<br />

GOTO INGEN_KORR ;Om negativt, hoppa inte över denna<br />

MOVF SENSOR2_MV,w ;Sätt nytt minvärde<br />

MOVWF<br />

Vmin<br />

GOTO FORTS_NICKLAS ;Korrigera...<br />

S2_STORST<br />

MOVLW 0x7f ;Aktivera korrigering vänster (igen)<br />

MOVWF<br />

Vmin<br />

MOVF Hmin,w ;Minvärdet till TEMP<br />

MOVWF<br />

TEMP<br />

MOVLW 0x01 ;Lägg till 2, måste vara lite under....<br />

SUBWF<br />

TEMP,f<br />

MOVLW 0x00 ;Ej TEMP<br />

BTFSS TEMP,7 ;Om TEMP negativt, ingen korrigering<br />

GOTO INGEN_KORR ;Om negativt, hoppa inte över denna<br />

MOVF SENSOR1_MV,w ;Sätt nytt minvärde<br />

MOVWF<br />

Hmin<br />

GOTO FORTS_NICKLAS ;Korrigera...<br />

FORTS_NICKLAS<br />

;Korrigering vänster<br />

MOVLW 0x14 ;Ladda W med 0x0a = 12 =~ 16cm:<br />

;0x0c. Tidigare 15<br />

SUBWF SENSOR1_MV,w ;Ligger mätvärdet under,<br />

;sätt utvärdet till korsning<br />

MOVWF TEMP ;0x0a minus mv = temp<br />

BTFSC TEMP,7 ; - -<br />

GOTO<br />

KORR_V<br />

;Korrigering höger<br />

MOVLW 0x14 ; - -<br />

SUBWF SENSOR2_MV,w ; - -<br />

MOVWF TEMP ; - -<br />

BTFSC TEMP,7 ; - -<br />

GOTO<br />

KORR_H<br />

INGEN_KORR<br />

;Hoppa hit om det inte behövs någon korrigering<br />

;Här ska återvändsgränd stå om den ska ha lägre prioritet än<br />

;korrigering<br />

MOVLW<br />

0xe0<br />

ANDWF PORTA,f ;Ingen korsning, maska ut de<br />

;4 sista bitarna<br />

GOTO FORTS_KORR<br />

KORSN_UT<br />

;Vi är i en korsning,<br />

;skicka det till styrenheten<br />

BTFSS KORSNING_ALLERT,0 ;Om ingen tidigare varning,<br />

;ge varning<br />

GOTO<br />

VARNING_KORS<br />

CLRF<br />

KORSNING_ALLERT ;Ta bort varningen till nästa gång...<br />

MOVLW 0xef ;Skriv korsning<br />

MOVWF<br />

PORTA<br />

GOTO FORTS_KORR


VARNING_KORS<br />

MOVLW<br />

0xff<br />

;Ett ställ korsnings alert, ge en ;varning, korsning igen<br />

MOVWF<br />

KORSNING_ALLERT<br />

; -> skicka signal<br />

GOTO<br />

FORTS_KORR<br />

KORSN_AT_UT<br />

;Återvändsgränd<br />

;MOVLW 0x7f ;ettställ min värdet<br />

;MOVWF Hmin ;aktivera korrigering igen...<br />

;MOVWF<br />

Vmin<br />

MOVLW 0xee ;skriv återvändsgränd<br />

MOVWF<br />

PORTA<br />

GOTO FORTS_KORR<br />

KORR_V<br />

;MOVWL 0xe1 ;Maska ut den gamla signalen<br />

;ANDWF<br />

PORTA,f<br />

MOVLW 0xe1 ;Skriv korrigera vänster<br />

MOVWF<br />

PORTA<br />

;IORWF<br />

PORTA,f<br />

GOTO FORTS_KORR<br />

KORR_H<br />

;MOVWL 0xe2 ;Maska ut den gamla signalen<br />

;ANDWF<br />

PORTA,f<br />

MOVLW 0xe2 ;Skriv korrigera höger<br />

;(utan att cleara signaltyp)<br />

;IORWF<br />

PORTA,f<br />

MOVWF<br />

PORTA<br />

GOTO FORTS_KORR<br />

FORTS_KORR<br />

;CALL<br />

MIN_FIX korrigera om vi är i mitten och på väg åt något håll<br />

;Lagra undan tidigare värden<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

SENSOR1_SLAP8,w ;S8 -> S9<br />

SENSOR1_SLAP9<br />

SENSOR2_SLAP8,w<br />

SENSOR2_SLAP9<br />

SENSOR1_SLAP7,w ;S7 -> S8<br />

SENSOR1_SLAP8<br />

SENSOR2_SLAP7,w<br />

SENSOR2_SLAP8<br />

SENSOR1_SLAP6,w ;S6 -> S7<br />

SENSOR1_SLAP7<br />

SENSOR2_SLAP6,w<br />

SENSOR2_SLAP7<br />

SENSOR1_SLAP5,w ;S5 -> S6<br />

SENSOR1_SLAP6<br />

SENSOR2_SLAP5,w<br />

SENSOR2_SLAP6<br />

SENSOR1_SLAP4,w ;S4 -> S5<br />

SENSOR1_SLAP5<br />

SENSOR2_SLAP4,w<br />

SENSOR2_SLAP5<br />

SENSOR1_SLAP3,w ;S3 -> S4<br />

SENSOR1_SLAP4<br />

SENSOR2_SLAP3,w<br />

SENSOR2_SLAP4<br />

SENSOR1_SLAP2,w ;S2 -> S3<br />

SENSOR1_SLAP3<br />

SENSOR2_SLAP2,w<br />

SENSOR2_SLAP3<br />

SENSOR1_SLAP1,w ;S1 -> S2<br />

SENSOR1_SLAP2<br />

SENSOR2_SLAP1,w


MOVWF<br />

MOVF<br />

MOVWF<br />

MOVF<br />

MOVWF<br />

SENSOR2_SLAP2<br />

SENSOR1_SLAP,w ;S0 -> S1<br />

SENSOR1_SLAP1<br />

SENSOR2_SLAP,w<br />

SENSOR2_SLAP1<br />

MOVF SENSOR1_MV,w ; MV -> 0<br />

MOVWF SENSOR1_SLAP ; - -<br />

MOVF SENSOR2_MV,w ; - -<br />

MOVWF<br />

SENSOR2_SLAP<br />

; ----- ÄNDA HIT -----<br />

BSF<br />

CALL<br />

CALL<br />

CALL<br />

CALL<br />

BCF<br />

PORTA,4<br />

WAIT_LOOP<br />

WAIT_LOOP<br />

WAIT_LOOP<br />

WAIT_LOOP<br />

PORTA,4<br />

BSF PORTA,5 ;Utsignalen är av typ korrigering<br />

CLRF OK_MATV ;Det gamla mätvärdet är inaktuellt<br />

RETURN<br />

;Från UPPD_UTV!!<br />

EJ_MATV ;* Körs om det inte ännu ett ok mätvärde i minnet *<br />

MOVLW 0xff ;Slå på mätningen<br />

MOVWF<br />

MATNING_PA<br />

MOVLW 0x7f ;ettställ min värdet<br />

MOVWF Hmin ;aktivera korrigering igen...<br />

MOVWF Vmin ;Det här är original nollställningen...<br />

;då A2 (a1) varit låg<br />

CLRF PORTA ;Inget utvärde till styrenheten (ännu)<br />

CLRF OK_MATV ;Det gamla mätvärdet är inaktuellt<br />

RETURN<br />

;Returnera från UPPD_UTV<br />

; ******************************************<br />

; Subrutiner för min fix-algoritm<br />

; ******************************************<br />

MIN_FIX<br />

;Beräkna diffen<br />

MOVF<br />

SENSOR1_MV,w<br />

MOVWF<br />

dMV<br />

MOVF<br />

SENSOR2_MV,w<br />

SUBWF<br />

dMV,f<br />

BTFSC dMV,7 ;Invertera om talet är negativt<br />

COMF<br />

dMV,f<br />

MOVLW<br />

0x10<br />

MOVWF TEMP ;16 -> temp<br />

MOVF dMV,w ;dMV -> w<br />

SUBWF TEMP,f ;TEMP (10) - dMV<br />

BTFSC TEMP,7 ;Om negativt<br />

GOTO FIX_FIX ;om inte, få til fix-fix<br />

RETURN<br />

FIX_FIX ;Avståndet mellan mv1 och mv2 är mindre än 16<br />

;alltså roboten är i mitten<br />

MOVF<br />

SENSOR1_SLAP9,w ;Beräkna diffen mellan mv och släp<br />

MOVWF<br />

TEMP<br />

MOVF<br />

SENSOR1_MV,w<br />

SUBWF TEMP,f ;diffen till temp<br />

BTFSC TEMP,7 ;Invertera om talet är negativt<br />

COMF<br />

TEMP,f<br />

MOVLW 0x0a ;10 -> w<br />

SUBWF TEMP,f ;TEMP - 10


BTFSS TEMP,7 ;kolla om negativt,<br />

RETURN<br />

;om så fallet, return,<br />

;differensen ligger under 10<br />

MOVF<br />

SENSOR1_SLAP9,w<br />

MOVWF TEMP ;(SLAP9-NEW) = TEMP<br />

MOVF<br />

SENSOR1_MV,w<br />

SUBWF<br />

TEMP,f<br />

BTFSC TEMP,7 ;Om TEMP negativt, MV över<br />

GOTO FIX_KORR_V ;om negativt, fortsätt, annars<br />

GOTO<br />

FIX_KORR_H<br />

FIX_KORR_V<br />

MOVLW 0xe1 ;Skriv korrigering på porten<br />

MOVWF<br />

PORTA<br />

RETURN<br />

FIX_KORR_H<br />

MOVLW 0xe2 ;Skriv korrigering på porten<br />

MOVWF<br />

PORTA<br />

RETURN<br />

; ******************************************<br />

; Slut på koden<br />

; ******************************************<br />

END

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!