Räkna ut skillnad på två kompass-kurser? Assembler AVR

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Nu har det kört ihop sig igen! Detta borde vara enkelt :?:

Jag har två kompasskurser som ligger i varsin 16-bitars variabel:
"Kurs_ar" 0-359 (ÄR-värdet i grader)
"Kurs_bor" 0-359 (BÖR-värdet i grader)

Jag vill få fram skillnaden och om östlig eller västlig korrigering krävs.
Jag trodde att jag hade kommit på en smart lösning när jag lade till 360 på ÄR-värdet först och sedan drog ifrån BÖR-värdet. Fick ihop ett program som jag trodde fungerade, men näää naturligtvis fungerar det inte på alla kurser.
Är jag på rätt spår eller finns det enklare sätt att göra det?

Kod: Markera allt

Main:
	ldsw	Y, Kurs_ar		;Lägg Kurs_ar i Y
	addiw	Y, 360			;och lägg till 360
	ldsw	Z, Kurs_bor		;Lägg Kurs_bor i Z...
	subw	Y, Z			;...och subtrahera från Y
	ldiw	Z, 180			;
	cpw		Y, Z			;Jämför Y med 180...
	brsh	East			;...om samma eller högre så fodras östlig eller ingen korrigening av kursen
	rjmp	West			;...om lägre så fodras västlig korrigening av kursen
East:
	ldiw	Z, 360			;
	cpw		Z, Y			;Jämför 360 med Y...
	brlo	East_hi			;...och om lägre(Y är högre alltså) hoppa till East_hi
	subw	Z, Y			;...annars subtrahera Y från 360
	mov		skillnad, ZL	;och lägg resultatet(som nu är mellan 0-180) i "skillnad"
	rjmp	Main
East_hi:
	subw	Y, Z			;Subtrahera 360 från Y
	ldiw	Z, 360			;
	subw	Z, Y			;Subtrahera Y från 360
	mov		skillnad, ZL	;och lägg resultatet(som nu är mellan 0-180) i "skillnad"
	rjmp	Main
West:
	mov		skillnad, YL	;lägg resultatet(som är mellan 0-180) i "skillnad"
	rjmp	Main
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Låg i sängen och funderade. Kom på en grej som jag var tvungen att testa. Upp ur sängen och på med en tröja medan datorn startade :mrgreen:

Kom fram till detta:

Kod: Markera allt

Main:
	ldsw	Y, Kurs_ar		;Lägg Kurs_ar i Y
	ldsw	Z, Kurs_bor		;Lägg Kurs_bor i Z
	cpw		Y, Z			;och jämför dom
	breq	Kurs_eq			;...hoppa om lika
	brsh	Kurs_ar_bor		;...hoppa om Kurs_ar är större än Kurs_bor
	brlo	Kurs_bor_ar		;...hoppa om Kurs_bor är större än Kurs_ar
Kurs_eq:
	clr		skillnad		;Nollställ "skillnad"
	rjmp	Main
Kurs_ar_bor:
	subw	Y, Z			;Dra Kurs_bor från Kurs_ar för att få differansen
	ldiw	Z, 181			;
	cpw		Y, Z			;Jämför differansen med 181...
	brsh	Diff_hi_ar		;...hoppa om lika eller högre
	mov		skillnad, YL	;...om lägre, lägg differansen i "skillnad"
	rjmp	Main
Diff_hi_ar:
	ldiw	Z, 360			;
	subw	Z, Y			;Dra differansen från 360 (vilket ger skillnaden från andra hållet)
	mov		skillnad, ZL	;och lägg nya differansen i "skillnad"
	rjmp	Main
Kurs_bor_ar:
	subw	Z, Y			;Dra Kurs_ar från Kurs_bor för att få differansen
	ldiw	Y, 181			;
	cpw		Z, Y			;Jämför differansen med 181...
	brsh	Diff_hi_bor		;...hoppa om lika eller högre
	mov		skillnad, ZL	;...om lägre, lägg differansen i "skillnad"
	rjmp	Main
Diff_hi_bor:
	ldiw	Y, 360			;
	subw	Y, Z			;Dra differansen från 360 (vilket ger skillnaden från andra hållet)
	mov		skillnad, YL	;och lägg nya differansen i "skillnad"
	rjmp	Main
Koden verkar fungera i alla fall. Skillnaden mellan "Kurs_ar" och "Kurs_bor" hamnar i "skillnad".
Jag tar bara skillnaden mellan kurserna och om den är mer än 180 så tar jag skillnaden från andra hållet. Har inte brytt mig om att hålla koll på om det blir östlig eller västlig skillnad, mest för att jag inte bryr mig om det just nu. :vissla: Imorn ska jag prova att lägga in någon typ av flagga som kan sättas beroende på om det är östlig eller västlig skillnad. Det är nog ganska enkelt :)

Jösses, det var ju som jag trodde! Enkelt, bara man kommer på det :D
Gonatt!
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Swech »

Du har lite macro kommando
ldsw
subw
som det inte framgår exakt hur de är definierade, men det går att gissa :D

Kod: Markera allt

   ldi    r16,low(360)
   ldi    r17,high(360)
   ldsw  y,kurs_ar
   ldsw  z,kurs_bor
   subw y,z
   brcc  storre
   addw y,r16,r17 
storre:
   cpw  y,r16,r17
   brlo  mindre
   subw y,r16,r17
mindre:
swech
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Swech: Aaaa, så kan man ju också göra. Ibland krånglar jag verkligen till det :shock:
Ja, det är makron men du gissar nog rätt. De hanterar 16-bitar istället för 8-bitar, det går mycket fortare att skriva så, man måste ju ta lite genvägar för att väga upp alla senvägar :roll:
labmaster
Inlägg: 2919
Blev medlem: 5 april 2011, 01:10:25

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av labmaster »

Jag har inte funderat något djupare i detta men det kan vara värt för dig att kolla vad som händer med storleken och hastigheten på programkoden om du gör på följande sätt:

if (Kurs_ar > 180) Kurs_ar -= 360; // Ifall du inte kan C så betyder detta Kurs_ar = Kurs_ar - 360
if (Kurs_bor > 180) Kurs_bor -= 360;

skillnad = Kurs_bor - Kurs_ar;

Fundera också på om tecknet på skillnaden berättar om det är östlig eller västlig.
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

labmaster: Grymt coolt! Jag har väll varit lite för inställd på att det aldrig ska bli några negativa tal, mest för att jag inte har hållit på med det i assembler förr men någon gång måste man ju börja :D
labmaster
Inlägg: 2919
Blev medlem: 5 april 2011, 01:10:25

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av labmaster »

Jag har inte sagt att det fungerar, bara att du skall undersöka om det fungerar.

Jag minns inte om vad du håller på med men om det är en autopilot så borde nedanstående fungera givet att det är rätt med de två if-satserna.

Kod: Markera allt

While (autopiloteOn) {
    Kurs_ar = // Hämta kurs

    if (Kurs_ar > 180) Kurs_ar -= 360;
    if (Kurs_bor > 180) Kurs_bor -= 360;

    skillnad = Kurs_bor - Kurs_ar;
    styr(skillnad);
    delay(samplingTime);
    styr(-skillnad);
    delay(samplingTime);
}
Jag har inte funderat speciellt mycket på detta men är det rätt så ser du bland annat att det är mycket lättare att jobba med C än assembler. Sannolikt lägger kompilatorn ut effektivare programkod än den du skriver själv i assembler.
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

labmaster: Jo, jag testade din kod och den fungerade ju bra vad jag kunde se, resultatet blev positivt eller negativt beroende på om det var öst eller väst. Och tanken är att det ska bli en kurs-hållare till båten.
Jag började lära mig C när jag började programmera AVR men sedan blev det assembler, för det var lättare att förstå. Men kanske det vore ide att börja med C istället. Nu har man ju glömt det mesta. Jag använder ju bara AVR till lite små-prylar ibland så man uppdaterar ju inte kunskaperna så ofta.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av jesse »

När det gäller sådana här uppgifter brukar jag först ta ett papper och en penna och skriva ner de olika alternativen och de formler jag kommer på. Och om jag inte är säker på hur det ska vara gör jag ett litet program i miniräknaren, eller ett C-program som jag kör i datorn , med indata som jag antingen matar in med tangentbordet eller så loopar igenom jag ett antal indata och skriver ut en lista på utdata. Då sysn det snabbt om algoritmen stämmer. Sedan översätter jag till assembler eller vad det nu ska skrivas i.

Det är bra att veta om det är själva algoritmen som innehåller ett logiskt fel eller om det bara är skrivfel / felkodat.
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

jesse: Jag brukar prova det, papper och penna. Även denna gång men ändå kom jag inte på något som fungerade :shock: Skrev då en assembler-kod som inte fungerade så bra på alla kurser. Men kl halv 3 på natten så kommer man på det utan både papper och dator. Då klev jag upp och skrev rakt av koden som faktiskt fungerade, även om den var onödigt lång(dock behövs inga negativa tal i det programmet). Men över lag är jag nog lite dålig på att använda papper och penna INNAN jag börjar koda(inte ovanligt vad jag har förstått) :lol:

Men nu blev jag lite sugen på att lära mig C eftersom jag ofta brukar krångla med uträkningar av olika slag i assembler. Det ser ju smidigt ut i C så nu har jag börjat göra ett C-program istället för denna kurs-hållare, och det går faktiskt över förväntan :razz:
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Hmmm...det verkar som att jag hade testat labmasters exempel lite för dåligt.

Extremfallet:

Kod: Markera allt

	Kurs_ar = 180;
	Kurs_bor = 181;
    if (Kurs_ar > 180) Kurs_ar -= 360;
    if (Kurs_bor > 180) Kurs_bor -= 360;
    Skillnad = Kurs_bor - Kurs_ar;
Det ger Skillnad -359, vilket ju är rätt kurs men åt fel håll. Man vill ju ha skillnad +1 i det fallet :humm: Jag får lura på det ett tag till :doh:
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Nu har jag lurat lite på det.

Såhär kanske:

Kod: Markera allt

	Kurs_ar = 180;
	Kurs_bor = 181;
    if (Kurs_ar > 180) Kurs_ar -= 360;
    if (Kurs_bor > 180) Kurs_bor -= 360;
	Temp = Kurs_bor - Kurs_ar;
	if (Temp < -180) Temp += 360;
	if (Temp > 180) Temp -= 360;
    Skillnad = Temp;
Ursäkta användandet av Temp, vet inte hur en C:are brukar göra :roll:
labmaster
Inlägg: 2919
Blev medlem: 5 april 2011, 01:10:25

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av labmaster »

Att du får -359 grader i skillnad är ju inte så konstigt men min magkänsla säger mig att det kan finnas något beroende i för hållande till om fören pekar mot nord eller syd. Det är möjligt att detta beroende får den konsekvens som du löst i titt tillägg.

Du kan köra varvet runt med det två variablerna är och bör så kanske du upptäcker detta.

I din kod kan du skippa Temp och skriva som följer:

Kod: Markera allt

Skillnad = Kurs_bor - Kurs_ar;

if (Skillnad < -180) {
   Skillnad += 360;
} else if (Skillnad > 180) {
   Skillnad -= 360;
}
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av Glattnos »

Ja just det, det är det som är fint med C! Jag var inne lite på det först men det kändes som att det var bättre att använda nått annat än "Skillnad". Nu vet jag inte hur det är i C, men om man tex. använder "Skillnad" i ett avbrott. Är det inte "farligt" att använda "Skillnad" i beräkningen då, om avbrott sker mitt i beräkningen så stämmer inte "Skillnad"?
Fast i C kan väll funktionen returnera "Skillnad" som resultat av beräkningen och då kanske det inte blir något avbrott innan det är klart? Jag har som sagt bestämt mig för att lära mig lite mer C nu, så jag kommer nog underfun med hur det hänger ihop så småningom :)
labmaster
Inlägg: 2919
Blev medlem: 5 april 2011, 01:10:25

Re: Räkna ut skillnad på två kompass-kurser? Assembler AVR

Inlägg av labmaster »

Om du använder en global variabel som du uppdaterar utanför en avbrottsrutin så kan du inte veta om variabeln är korrekt när den skall användas. Det är dock lite knepigt att ge råd när man inte har tillgång till helheten. Jag skulle nog använda en flagga som sätts när variabeln har ett innehåll och då interuptrutinen har hämtat innehållet i variabeln så nollställer den flaggan.

Vilket interrupt är det du tänker på?
Skriv svar