Type casting - Et problem?

Tags:    c microcontroller avr atmega casting

Hej udviklere.

Jeg og en makker er i gang med et robotprojekt Project Hilde, hvor vi er stødt på et problem som vi har lidt svært ved at debug'e.

Robotten er opbygget som en tripod, hvor de to forreste hjul trækker robotten uafhængigt af hinanden. Det tredje hjul (baghjulet) er er fastgjort til en servo. Meningen er så at ved hjælp af vores manuelle kontrol kan styre hastighed ved hjælp af et potentiometer og vha et andet potentiometer kan vi styre forholdet mellem hastigheden på de to trækhjul. Når vi så justerer hastigheds-forholdet mellem trækhjulene er det meningen at baghjulet skal justeres trinløst, men den kode vi har brygget sammen virker ikke helt efter hensigten når den bruges på vores ATmega88 microcontroller.

Koden nedenunder er de to funktioner vi bruger til at beregne en vinkel (Grader) med 1 grads nøjagtighed.

Den første funktion tager et argument som er et tal mellem 0 og 110 og returnerer en vinkel i grader. Den beregner principielt omdrejningspunktet og den trekant som dannes af omdrejningspunktet, baghjulet og punktet i mellem de to forhjul. Herved kan vinklen beregnes for baghjulet.

Er klar over, at vi faktisk risikerer at dividere med nul, men det er ikke problemet.

Fold kodeboks ind/udC kode 


Funktionen nedenunder er en Lagrange interpolation af ArcTan ved 3 punkter. Den tager et argument som er forholdet mellem de to sidder i en trekant som står vinkelret på hinanden og returnerer en vinkel i radianer.

Fold kodeboks ind/udC kode 


Meningen med koden er at beregne en vinkel i forhold til det forhold der er mellem hastighederne på forhjulene, og når denne justeres skal baghjulet gerne følge med. Der ved ønsker vi altså en trinløs justering. Denne trinløse justering opnår vi dog ikke, men vi kan kun stå i midterstilling og de to yderstillinger.

Vi har snakket om hvad problemet er og vi er nået frem til vi muligvis mister noget information idet vi kun kan opnå yderstillingerne eller midterstillingen. Det virker som om vi mister alt decimal informationen, altså det tyder på at det er et casting problem, som om at ATmega'en ikke kan håndtere den kode jeg har postet her i tråden.

Denne konklusion er baseret på, at vi har prøvet at kopiere vores to ovenstående funktioner og bruge dem i et konsol program hvor i sagtens kan beregne individuelle vinkler for et hvert tal fra 0 - 110, men på vores ATmega88 virker det ikke. Vu har sågar tjekket det ved at sende vinkel information til en terminal på computeren og den viser også at microcontrolleren kun kan beregne vinklerne for yderpositionerne og midten.

Håber der er nogle herinde som har erfaring med microcontroller-programmering og kan hjælpe os.

På forhånd tak.

Med Venlig Hilsen
Kent



4 svar postet i denne tråd vises herunder
2 indlæg har modtaget i alt 6 karma
Sorter efter stemmer Sorter efter dato
Ved ikke meget om programmering til microcontrollere men ved en del om C.

Det virker som om at castingen bliver brugt de forkerte steder.
Fold kodeboks ind/udC kode 

Baseret på denne linje virker det for mig som om at HEIGHT, og derfor WIDTH, er et slags heltal. Denne linje er korrekt, du behøver dog ikke castingen her (og en god del af de andre steder) siden i et regnestykke med en int og en float vil int-værdien bliver lavet om til en float.

Her er der dog risiko for tab:
Fold kodeboks ind/udC kode 

(WIDTH / 2) er heltalsdivision (hvis altså WIDTH er en slags heltal). Først efter division bliver det castet til float, dvs.:
(float)(7 / 2) = 3.00...f.

Noget andet jeg ikke ved om er et problem er de "literal" værdier du har. F.eks.: 1.04415 og 0.253662. Jeg er temmelig sikker på at compileren fortolker det som doubles og ikke som floats. Hvis de skal fortolkes som floats skal der et 'f' til sidst på:
0.253662f
På en moderne processor vil det nok ikke være noget problem siden floating point værdier beregnes med op til 80 bits før de bliver formindsket til en float eller double igen. Men ved ikke med mikrocontrollere og deres FPU/FP-software-library.

Denne linje gør mig nysgerrig:
Fold kodeboks ind/udC kode 

En float (double faktisk, tror jeg) castes til en char. Hvad menes der? Kunne måske forestille mig at en float værdi af 123.343 blev castet til en signed byte på 123. Men hvad med 142.XX eller 340.XX?

Håber noget af det måske kunne bruges.



Indlæg senest redigeret d. 05.05.2011 17:56 af Bruger #14645
Fold kodeboks ind/udC kode 

(HEIGHT / r):
Dette er korrekt. Her er r deklaret som en float. Derfor vil C implicit caste HEIGHT til en float i dette regnestykke og resultat vil være en float.

(WIDTH / 2):
Her er et problem. Her er begge værdier heltal. C vil derfor smide eventuelt rest væk. Dvs. 3 / 2 = 1. Her skal der være mindst en float. Afhængig af hvilke værdier WIDTH er kan den godt være skyldig eller medskyldig i jeres problem. 2 forskellige måder er:
((float)WIDTH / 2)
(WIDTH / 2.0f)

Selv ville jeg nok bruge den første metode (eller begge).

Da jeg sagde at du havde nogle overflødige casts til float var det ikke fordi du nødvendigvis skulle jeg fjerne dem, ville bare påpege at de var ikke var nødvendige. Selvom det ikke er nødvendigt her (HEIGHT / r) fordi r er en float vil nogle måske finde koden lettere forståeligt hvis der var ((float)HEIGHT / r).

Hvis det er en AVR microcontroller kan der måske bruges AVRstudio til debugging. Måske kan du få compileren til at genere assembly og så køre det gennem AVRstudio og debug der.




Indlæg senest redigeret d. 05.05.2011 19:21 af Bruger #14645
Hej Søren.

Hverken min makker eller jeg er nogle vilde hajer til det C programmering, så det er mægtigt fint med dine inputs, f.eks var der ingen af os der umiddelbart vidste det med de tal-"literals", altså at en normal c compiler fortolker dem som doubles. Jeg har efterfølgende siddet og prøvet at finde ud af hvad avr-gcc gør med literals, men indtil videre uden held desværre. Er nok nød til at grave lidt dybere i manualen til compileren. Men jeg har forsøgt at lave de ændringer som du indirekte foreslår, men stadigvæk uden held...

Koden nedenfor viser de ændringer jeg har lavet efter at have læst dit svar samt hurtigt googlet avr-gcc contra literals. Google popper så op med en masse om string literals, men ikke noget om number literals, ihvertfald ikke umiddelbart.

Fold kodeboks ind/udC kode 


Det er rigtigt antaget at HEIGHT og WIDTH er heltal, det er defines som fortæller om nogle fysiske afstande på robotten.

Mht den char casting jeg lavede før er det meningen at calculateAngle funktionen skal returnere en værdi mellem 0 og 60 så derfor skulle dens range ikke være noget problem.

Tak for hjælpen så langt, skal nok udele karma, hvis jeg altså kan.

Med venlig hilsen



Hej Søren.

Tak for hjælpen. Har ikke lige haft mulighed for at teste dine sidste forslag til løsning af problemet, men det er i hvert fald et udgangspunkt. Angående AVR-studio, så burde vi nok selv have tænkt på at bruge det til debugging. Vi bruger det nemlig i vores undervisning til assembler programmering og er egentlig bekendte med dets funktionalitet. Men det er jo altid rart at få nogle fagligt gode indspark.

Som sagt, så har vi et par fine udgangspunkter at arbejde ud fra, så tror jeg lader den ligge her, udeler karma og der efter får styr på skidtet.

Med Venlig Hilsen



t