Forum: Compiler & IDEs AtMega soll Servo steuern


von Kristian (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
vorneweg: Ja, ich habe die SuFu genutzt und ich weis dass es dieses 
Thema schon 1000x gab, aber ich finde seit Tagen keine Antwort.

Ich will mit dem Timer0 (8-Bit reichen mir vorerst zum verstehen/lernen) 
ein Servo ansteuern.

Ich lasse ihn bei 8MHz und einem Presaler von 64 immer von 6 bis 265 
zählen (sind dann genau 2ms), und das 10x, so dass ich einen 
Gesamt-Durchlauf von 20ms habe, was ja der Länge eines Servo-"Befehls" 
entspricht.

Trotzdem will der Servo nicht das machen was er soll.

Kann mir da wer helfen?

Danke :)

Kristian

von Kristian (Gast)


Lesenswert?

Ich sollte erwähnen dass ich auf einem AtMega 168 programmiere, was 
einer meiner Probleme ist, da alle Hilfen etc meist für den AtMega8 
geschrieben wurde...

MfG

von Stefan E. (sternst)


Lesenswert?

Kristian schrieb:
> Ich lasse ihn bei 8MHz und einem Presaler von 64 immer von 6 bis 265
> zählen

CTC-Modus wäre besser.

Kristian schrieb:
> Trotzdem will der Servo nicht das machen was er soll.

Und was soll er machen?
Und was macht er stattdessen?

von MWS (Gast)


Lesenswert?

counter und on volatile deklarieren.

von Stefan E. (sternst)


Lesenswert?

MWS schrieb:
> counter und on volatile deklarieren.

Unsinn. Es gibt keinen Grund dafür.

von Kristian G. (kristian_g)


Angehängte Dateien:

Lesenswert?

So, danke erstmal für die Antworten.
Ich hab mich mal in den CTC Modus reinarbeitet, sollte theoretisch 
richtig sein, denke ich.

Eigentlich sollte der Servo jetzt auf eine Stellung fahren und da ruhig 
verharren. Aber alles was er macht ist ungesund knirschen (was nicht an 
dem Servo liegt, der ist funktionstüchtig).

Ich hab leider kein Oszi um zu sehen was da wirklich aus dem Atmega 
kommt und ich habe keine Schimmer was ich falsch mache.

MfG

von Klaus W. (mfgkw)


Lesenswert?

Kristian G. schrieb:
> Eigentlich sollte der Servo jetzt auf eine Stellung fahren

Verstehst du denn selbst, was dein Programm machen soll?
Ich verstehe es nicht.

Z.B. soll Stellung Werte ab 0 annehmen können; OCR0A wird aber auf 
(256-Stellung) gesetzt und hätte mit 256 damit ggf. einen Wert,
der nicht mehr in 8 Bit passt. Ist das so beabsichtigt?

Welchen Sinn hat on bzw. wieso hat sie diesen Namen?
Sie ist immer an, wenn der Port aus ist und umgekehrt.

Ein paar Worte zur Erklärung, wie das alles zusmmenspielen soll,
würde dir vielleicht selbst helfen...

von Michel (Gast)


Lesenswert?

Kristian G. schrieb:
> Ich hab leider kein Oszi um zu sehen was da wirklich aus dem Atmega
> kommt und ich habe keine Schimmer was ich falsch mache.

Werden denn im Simulator die richtigen Signale für den Servo erzeugt?

ATmega8 und ATmega168 sind so was von ähnlich, dass die Programme mit 
minimalen Änderungen übertragbar sind.

von Kristian G. (kristian_g)


Lesenswert?

Ich denke schon dass ich mein Programm verstehe.

Zuerst danke, ja, es müsste 255 heißen, nicht 256.

Zu "on": Ich hatte vor ein genau 20ms lange Durchlaufzeit zu haben, bis 
ich wieder mit dem Impuls für den Servo beginne. Um das zu gewährleisten 
habe ich 10 Durchläufe durch "servo_counter". Da jetzt aber das Servo 
"High" Signal auch nur 1ms lang sein kann, muss ich die fehlende 1ms 
noch nachschieben. Dafür ist das "on" gedacht. Das erste IF behandelt 
das high-Sognal, das das zweite IF den fehlenden Anteil der 2ms.

Mir ist vorhin aufgefallen, dass der Durchlauf aber gar nicht 20ms lang 
sein muss, sonder 10-20ms. Das würde bedeuten, ich brauche den "on" Teil 
garnicht, was den Quelltext erheblich vereinfacht.
1
SIGNAL(TIMER0_COMPA_vect)
2
{ 
3
  int Stellung = 64;         //nur noch 1.5ms! (0-128)
4
  servo_counter++;         //Zählt bis 10 -> max. 20ms
5
  if (servo_counter == 1)
6
  {
7
    PORTB = 0x00;         //An, also Signal auf "high"
8
    OCR0A = 255 - Stellung;      //Wie lange auf High lassen? Min 1ms, max 2ms -> Min ~128, max ~255
9
  }
10
  if (servo_counter == 2)      
11
  {
12
    PORTB = 0xFF;         //Ist die "High-Zeit" für Servo um -> Signal für die restlichen 18-19ms auf "low"
13
  }
14
  if (servo_counter == 10)    
15
  {
16
    servo_counter = 0;       //10ter Durchlauf -> von vorne (ca 20 ms sind rum).
17
  }
18
}

Nichts desto trotz surrt mein Servo ungesund und bewegt sich 
unkontrolliert hin und her.

von Kristian G. (kristian_g)


Lesenswert?

Ich bin nochmal mit dem Debugger durch alles gegangen, dabei ist mir 
zwar aufgefallen, dass bei "if (servo_counter == 2)" ein "OCR0A   = 
0xFF;". Sonst stimmen die Timings, aber es ändert immer noch nichts an 
der Tatsache, dass mein Servo nicht das tut was er soll, ruhig auf einer 
Stelle stehen.

von Stefan E. (sternst)


Lesenswert?

Was noch fehlt, ist OCR0A wieder zurückzusetzen:
1
SIGNAL(TIMER0_COMPA_vect)
2
{ 
3
  int Stellung = 64;         //nur noch 1.5ms! (0-128)
4
  servo_counter++;         //Zählt bis 10 -> max. 20ms
5
  if (servo_counter == 1)
6
  {
7
    PORTB = 0x00;         //An, also Signal auf "high"
8
    OCR0A = 249 - Stellung;      //Wie lange auf High lassen? Min 1ms, max 2ms -> Min ~128, max ~255
9
  }
10
  if (servo_counter == 2)      
11
  {
12
    PORTB = 0xFF;         //Ist die "High-Zeit" für Servo um -> Signal für die restlichen 18-19ms auf "low"
13
    OCR0A = Stellung;
14
  }
15
  if (servo_counter == 3)      
16
  {
17
    OCR0A = 249;
18
  }
19
  if (servo_counter == 11)    
20
  {
21
    servo_counter = 0;       //10ter Durchlauf -> von vorne (ca 20 ms sind rum).
22
  }
23
}

PS: 249 für genau 2ms pro Interrupt.

von Kristian G. (kristian_g)


Lesenswert?

Jopp, danke, hatte ich ja gerade gemeint, aber auch ohne dem Fehler 
kommt kein richtiges Signal an, obwohl der Timer im Debugger nun 
verdammt genau ist. Das versteh ich irgendwie nicht.

Ja, die 0.048ms hatte ich vorerst vernachlässigt, aber danke, ich habe 
nun "OCR0A = 249;" eingefügt.

von Stefan E. (sternst)


Lesenswert?

Kristian G. schrieb:
> Jopp, danke, hatte ich ja gerade gemeint,

Sorry, bin beim Schreiben unterbrochen worden, und hatte daher etwas 
länger gebraucht (als ich anfing, war dein Beitrag noch nicht da). ;-)

Dann checken, ob der Controller auch tatsächlich mit 8 MHz läuft, und 
nicht vielleicht doch noch mit 1 MHz.

von Kristian G. (kristian_g)


Lesenswert?

Hab ich gecheckt, ich hab auch eben ein anderes Programm auf einem 
AtMega8 getestet, um zu sehen ob der Servo eine Macke hat: Nein, hat er 
nicht. Ich hab auch den AtMega168 gegen ein anderen getauscht, auch 
daran liegts nicht.

Ein UART habe ich gerade eingefügt, der sendet ohne Probleme, also am 
Takt kanns nicht hängen.

von Kristian G. (kristian_g)


Lesenswert?

Ich könnt mir so in den Aller wertesten beißen. -.-

Ich habe überall PORTB = 0x00; mit PORTB = 0xFF; verdreht. Und ich 
zerbrech mir hier seit Tagen den Kopf und war schon kurz davor alles in 
den Kamin zu werfen.

Ich danke euch allen vielmals und danke Gott dafür, das Dummheit doch 
nicht weh tut... =)

Schönen sonnigen Sonntag noch.

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.