AtMega soll Servo steuern

Gast #2174229
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
Angehängte Dateien:
#2175025
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
Angehängte Dateien:
#2175061
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...
Gast #2175085
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.
#2175088
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.
#2175108
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.
#2175137
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.
#2175154
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren