Forum: Mikrocontroller und Digitale Elektronik Servo-Steuerung


von Axel L. (ligonap)


Lesenswert?

Hallo Zusammen

ich habe folgende Problem bei der Servo-Steuerung (mittels ATMega644):
Ein Servo soll 300 Positionen (Zahlen) darstellen und fährt über eine 
Strecke von 350 Positionen (200 bis 550).
Sobald der erste Wert s aus der zweiten Gleichung berechnet wird, 
springt der Servo. Danach nicht mehr.
Dabei ist es egal, ob ich für die ersten Positionen (z.b. bis 280) eine 
vereinfachte Rechnung nehme oder nicht.

Woran liegt dies???

Zusammengesetzter Programmausschnitt:
1
uint16_t a; 
2
uint16_t s;
3
4
a = 300; 
5
6
while(1) {
7
8
a--;  // bis a=0
9
10
if(a >= 280)
11
s = - a + 500 ;
12
13
else
14
s = - ((1167 / 1000) * a ) + 550;
15
16
    
17
OCR1A = ICR1 - s;
18
19
_delay_ms(100);
20
21
}

von Easylife (Gast)


Lesenswert?

warum compilierst du diesen code nicht einfach auf deinem rechner, und 
fügst ein printf ein, mit dem du dir die werte am schirm angucken 
kannst?

der kommentar "a--;  // bis a=0"
verhindert nicht, dass a irgendwann mal kleiner als null werden will, 
und da es ein unsigned ist, läuft a in einen sehr großen wert über.
evtl. ist das ja der fehler.

von Mike (Gast)


Lesenswert?

Axel L. schrieb:
> s = - ((1167 / 1000) * a ) + 550;

Warum schreibst du statt dessen nicht a + 550?

Dann läßt sich das Programm leichter lesen (und der Compiler macht das 
sowieso daraus)

von Kaj (Gast)


Lesenswert?

Axel L. schrieb:
> s = - ((1167 / 1000) * a ) + 550;

Das ist eine Integer Division, d.h. 1167/1000 ergibt 1, weil die 
kommastellen abgeschnitten werden. also vom prinzip steht da:
s = - (1*a) + 550;

Wenn sich die werte in der Klammer eh nicht ändern ( 1167/1000 ), warum 
schreibst du dann nicht einfach direkt: s = - (1.167 * a) + 550; ?

von Axel L. (ligonap)


Lesenswert?

Kaj schrieb:
> Axel L. schrieb:
>> s = - ((1167 / 1000) * a ) + 550;
>
> Das ist eine Integer Division, d.h. 1167/1000 ergibt 1, weil die
> kommastellen abgeschnitten werden. also vom prinzip steht da:
> s = - (1*a) + 550;
>
> Wenn sich die werte in der Klammer eh nicht ändern ( 1167/1000 ), warum
> schreibst du dann nicht einfach direkt: s = - (1.167 * a) + 550; ?+

Yo, das wars. Danke Kai.

Man, ich glaub es nicht. Ich dachte erst, mein µC kann nicht mit 
Kommazahlen umgehen, daher die Division.

Nun läuft der Servo so wie er soll. :-))

von Easylife (Gast)


Lesenswert?

Ja, funktioniert, Akte kann geschlossen werden.

Der Code ist Mist.

a) was soll das
if(a >= 280) s = - a + 500 ;
gibt es einen Grund diese Unlinearität zu machen?

b) der uC "kann" natürlich keine Fließkommazahlen, sondern das macht 
eine C-Bibliothek für dich, die Fließkomma mit Integer macht -> 
furchtbar langsam.


Du willst doch eigentlich nur einen Eingangswert a, der von 300 bis 0 
läuft auf einen Ausgangswert s, der von 200 bis 550 läuft linear 
skalieren.

Wie du richtig erkannt hast, ist der Faktor dieser Funktion 350/300, was 
man gleich mal auf 7/6 kürzen kann.
Damit ergibt sich die Funktion, die deine Umrechnung komplett in Integer 
und auch komplett linear macht:

s = 550 - ((a * 7) / 6);

Ohne if's und but's.

von Easylife (Gast)


Lesenswert?

Achso, jetzt kapiere ich auch das if(a >= 280)

weil (281 * 1167) nicht mehr in den uint16 gepasst hätte.

ROFL. Ganz geil.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.