Forum: Mikrocontroller und Digitale Elektronik Servoprogi läuft net richtig!


von Cristian Grigoruta (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen!

Hab mal ein kleines Progi geschriebne welches mir den Servo TS 222
(viell. bekannt) steuern sollte. Leider klappt es nicht richtig. Der
Servo dreht sich LANGSAM bis zum linken(oder rechts -> Sichtweise)
Anschlag,kann dann logischerweise nicht weiter, aber der Motor will
noch immer drehen. Anstatt der 400mA die er sonst entnimmt braucht er
jetzt nur mehr 130mA.
hmm....mein Progi ist im Anhang.Könntet ihr mal rein schauen?
Verwende den Timer 2 vom 89C52.

Mfg Cri

von Peter (Gast)


Lesenswert?

Tja... da werden wohl die Zeiten nicht stimmem.. endweder bist du zu
schnell, oder zu langsam

von Rahul (Gast)


Lesenswert?

>da werden wohl die Zeiten nicht stimmem..

Da du mit dem Timer-Überlauf arbeitest, musst du IMHO bei den 1,5ms
noch die Dauer deiner Interrupt-Routine dazurechnen.

von Cristian Grigoruta (Gast)


Lesenswert?

aber vom Programmaufbau stimmt es ?
 Verwende einen 12MHz Quarz.

von Cristian Grigoruta (Gast)


Lesenswert?

Was ist bitte IMHO?

von Cristian Grigoruta (Gast)


Lesenswert?

Wie weiß ich wie lange die ISR dauert?

von Rahul (Gast)


Lesenswert?

IMHO = in my humble opinion

Die Dauer der ISR bekommst du mit Hilfe der .lst-Datei heraus, indem du
die Anzahl der Assemblerbefehle und deren Dauer feststellst...

von Cristian Grigoruta (Gast)


Lesenswert?

wow....hab vorher noch nie von IMHO gehört und schon garnet die Befehle
gezählt :)

von Cristian Grigoruta (Gast)


Angehängte Dateien:

Lesenswert?

OK.Hab die LST Datei mal aufgemacht und da steht die Zeilennummer und
bei der ISR steht auch ne andere Nummer.Muss ich die nebrigen Nummern
einfach addieren? sind das µs oder was bezeichnen die?

LST ist im Anhang.

Mfg Cri

von Peter (Gast)


Lesenswert?

Ist es nicht fast egal, wie lannge die ISR dauert??
du nutzt doch einen timer, da musst du dann die IOclock  Prescaler 
Overflow -1 rechnen
steht aber sicher alles im datenblatt

von Cristian Grigoruta (Gast)


Lesenswert?

Sorry Peter,aber ich verstehe nicht was du meinst.
Kannst es mir, blutigen Anfänger, etwas genauer erklären?

Mfg Cri

von Cristian Grigoruta (Gast)


Lesenswert?

bzw. wie man sowas in C schreibt!

von Rahul (Gast)


Lesenswert?

ich bin von irgendnem anderen Compiler ausgegangen. In dem File, das ich
meinte, steht das C-Programm mit dem Assembler-Code, den der Compiler
daraus macht.

von Peter (Gast)


Lesenswert?

Du solltest mal das Kapitel Timer dir durchlesen, dann wirst sicher
etwas schlauer

Das Forum ist nicht da, um jemanden alles vorzukauen
eigeniniative ist gefragt

von Cristian Grigoruta (Gast)


Lesenswert?

sorry wollt ja nur wissen wie es geht da im DATENBLATT nichts von
prescaler drin steht.Das Datenblatt habe ich außerdem gelesen sonst
wüßte ich ja net mal wie ich den Timer initialisiere. Habe schon
Eigeninitiative aber wenns mal nicht klappt braucht man HILFE.

von Rahul (Gast)


Lesenswert?

@Peter: es handelt sich um einen 8051er und icht um einen AVR (auch wenn
beide von Atmel sind, haben sie nichts miteinander zutun.)

@Crisitan: Da ich eher im Bereich AVR zuhause bin, stochere ich
eigentlich auch nur rum...
Deine ISR würde ich eher so schreiben:


void T0_int(void) interrupt 5
{
  if(ez ==1)
  {
  Servo_out = 1;
  RCAP2L = 0x23;  // T2 mit 64 035 = 0xFA23 vorladen = 1.5ms
  RCAP2H = 0xFA;
        ez = 0;
  }
  else
  {
         Servo_out = 0;
  RCAP2L = 0xDF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
  RCAP2H = 0xB1;
  ez=1;
  }

Das ist für mich einfach schlüssiger.

von Cristian Grigoruta (Gast)


Lesenswert?

hmm...Dein Vorschlag funzt nicht. Ist aber irgendwie klar. EZ wird nie
größer als 1 in deinem Progi da du hier

if(ez ==1)
  {
  Servo_out = 1;
  RCAP2L = 0x23;  // T2 mit 64 035 = 0xFA23 vorladen = 1.5ms
  RCAP2H = 0xFA;
        ez = 0;
  }

EZ immer auf null zurücksetzt.
Das Programm startet ja mit EZ=0.
void main (void)
{
  ez=0;
  Servo_out = 0;
.
.
.
.
.

Aber Danke für deinen Versuch.
Ich hab schon einiges probiert aber leider ohne Erfolg.
Mfg Cri

von Rahul (Gast)


Lesenswert?

Wieso sollte es auch grösser als 1 werden?
Man hat doch nur 2 Zustände (und zwei Zeiten):
Wenn ez = 0, wird beim nächsten ISR-Aufruf der Ausgangspin auf H-Pegel
gesetzt und die entsprechende Zeit (1,5ms) für den Timer eingestellt.
Wenn ez = 1, wird beim nächsten ISR-Aufruf (Ende der 1,5ms) der Pin auf
L-Pegel gesetzt und die andere Zeit (20ms) eingestellt.

von Karl H. (kbuchegg)


Lesenswert?

> EZ wird nie größer als 1 in deinem Progi da du hier
Schau dir den Vorschlag noch mal an.
ez ist eine Flag-Variable. Wenn sie 0 ist, wird der else
Zweig ausgeführt. Im Rahmen des else Zweiges wird ez auf
1 gesetzt. D.h. Beim nächsten Aufruf der Funktion wird
dann der if Teil ausgeführt der u.A. ez wieder auf 0 setzt, woraufhin
beim nächsten Aufruf wieder der else Zweig ausgeführt wird,
der ez wieder umschaltet um im nächsten Aufruf wieder den if Zweig
auszuführen, etc.

von Cristian Grigoruta (Gast)


Lesenswert?

Also ich habe mich schlecht ausgedrückt.

void T0_int(void) interrupt 5
{
  ez++;
  if(ez ==1)
  {
  Servo_out = 1;
  RCAP2L = 0x23;  // T2 mit 64 035 = 0xFA23 vorladen = 1.5ms
  RCAP2H = 0xFA;
        ez = 0;
  }
  else
  {
         Servo_out = 0;
  RCAP2L = 0xDF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
  RCAP2H = 0xB1;
  ez=1;
  }

Ich habe ez++; noch dazu geschrieben.
Also,wenn die ISR aufgeruffen wird dann wird ja ez inkrementiert und
auf 1 gesetzt.Dadurch ist die 1.if-Bedingung erfüllt.
Nun wird der If-Zweig abgearbeitet und ez=0 gesetzt.

Nun denke ich,dass else gleichbedeutend mit if(ez !=1) zu sehen
ist,oder?
Wenn ja, würde die else-Bedingung ja ebenfalls erfüllt sein da ja ez =0
ist.somit wird die else_anweisung abgearbeitet und alles ist beim
Alten.

Stimmt das so?

Ahm...das Prgoi funzt aber leider nicht .
Mfg Cri

von Cristian Grigoruta (Gast)


Lesenswert?

mit....Alles ist beim Alten meinte ich,dass nun der Reloadwert wieder
  RCAP2L = 0xDF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
  RCAP2H = 0xB1;

ist und ich nie meine 1,5ms erhalte.

von Karl H. (kbuchegg)


Lesenswert?

> Ich habe ez++; noch dazu geschrieben

Nein, nicht!
Du hast die Funktion von ez immer noch nicht verstanden.
ez ist ein Schalter, der sich quasi selbst betätigt und dafür
sorgt, dass die beiden Funktionsteile im Wechsel ausgeführt
werden.

von Rahul (Gast)


Lesenswert?

Vielleicht solltest du dir mal C-Grundlagen antun:

if (Bedingung)
{
  Anweisungen1;
}
else
{
  Anweisungen2;
}

Bedeutet: Wenn Die Bedingung erfüllt ist (z.B. "ez == 1") werden
Anweisungen1 ausgeführt.
Ist die Bedingung nicht erfüllt, werden Anweisungen2 ausgeführt.
Es handelt sich nur um EINE Abfrage mit einer Alternative, die bei
Nichterfüllung ausgeführt wird.

von Rahul (Gast)


Lesenswert?

[etwas angesäuert]

>Du hast die Funktion von ez immer noch nicht verstanden.

Ist schon schade, wenn man sein eigenes Programm nicht versteht...

[/etwas angesäuert]

von Rahul (Gast)


Lesenswert?

Um es noch klarer auszudrücken:
es werden ENTWEDER Anweisungen1 ODER Anweisungen2 ausgeführt. Es kann
nie vorkommen, dass beide Anweisungsteile ausgeführt werden.

von Cristian Grigoruta (Gast)


Lesenswert?

sorry Leut...deshalb habe ich ja auch nachgefragt.hmm...nicht sauer
werden.Man lernt ja.
Versuch es nun ohne ez++

von Cristian Grigoruta (Gast)


Lesenswert?

Leder geht es so auch net.
Ist bei mir im timing was falsch??

der interne Takt ist doch fosc (also 12MHz) / 12  => 1MHz

1MHz = 1µs d.f.: jeder Takt dauert eine µs. Bei 65536 wären das ja
65,536ms oder?
Bin ihc schon wieder komplett falsch unterwegs?

von Cristian Grigoruta (Gast)


Lesenswert?

seid ihr nun verärgert? Kommt schon :)

Kanns vielleicht daran liegen dass ich den Servo (signalleitung) direkt
am µC hängen hab?
Muss ich da evetuell einen Transistor vorschalten?

von Karl H. (kbuchegg)


Lesenswert?

Ich kenn den Chip nicht, kann daher nicht entschlüsseln was
du da beim Timer-Setup treibst, aber:

> der interne Takt ist doch fosc (also 12MHz) / 12  => 1MHz

Das kommt mir spanisch vor. Solche Teiler sind normalerweise
2-er Potenzen. Bitte, möglich ist alles, aber glauben tu ich's
nicht.

von Rahul (Gast)


Lesenswert?

>Kanns vielleicht daran liegen dass ich den Servo (signalleitung) direkt
am µC hängen hab?
>Muss ich da evetuell einen Transistor vorschalten?

Nein.

von Rahul (Gast)


Lesenswert?

@Karl Heinz: Das ist beim 8051er aber so... Es handelt sich dabei um
einen unveränderlichen Vorteiler, der den externen Takt (12MHz) durch
12 teilt. Moderne 8051er arbeiten teilweise ohne diese Taktteilung.

von Henning (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

erstens das wichtigste: umbedingt am Anfang der Routine das
Interrupt-Flag löschen, für Timer2 TF2 = 0. sonst springt er nach
beendigung der Routine direkt wieder in den Interrupt. Dann arbeitest
du Im Reload-Modus, d.h. der Wert aus RCAP2 wird erst bei dem nächsten
Überlauf in den Timer geschrieben. Also muss Servo_out getauscht werden
=1 zu =0 und umgekehrt.
Und um die Sache etwas schöner zu geschtalten, kann man auch statt
einer Integerzahl ein Bit nehmen, wenn man eh nur 2 Zustände haben
will. bei Flag = ~Flag wird das Bit invertiert. Geht schneller, braucht
weniger Platz und ist verständlicher.
Es sieht so aus, als ob du mit Keil arbeitest. Wenn du sowas hast nutze
den Debuger. Bei Keil µVision3 ist auch ein Logicanalyser drin.

Henning

von Sepp -. (sepp_o)


Lesenswert?

Ich habe den Code nur mal kurz überflogen.

Mir ist da aber etwas aufgefallen.

Muß da nicht die Dauer der LowZeit 20ms-HighZeit betragen?

Denn so die es aussieht bekommt man hier 20ms+1,5ms = 21,5ms Pulslänge
zusammen und dass schlucken nicht alle Servos.

mfg Sepp

von Henning (Gast)


Lesenswert?

Nochmal ich,

Servos fressen fast alles. In meinem Wagen betreiber ich die Servos mit
100Hz statt den üblichen 50Hz. Kein analoger oder digitaler Servor hat
sich darüber beschwert. Ob 15 oder 25 ms Pause ist nicht schlimm.

von Karl H. (kbuchegg)


Lesenswert?

@ Henning

Muesstest du nicht du Polarität des Servo_out-Signals umdrehen?

void T2_int (void) interrupt 5
{
  static bit flag;
  //TF2 = 0;

  if(flag)
  {
    Servo_out = 0;
    RCAP2L = 0x23;  // T2 mit 64 035 = 0xFA23 vorladen = 1.5ms
    RCAP2H = 0xFA;
  }
  else
  {
    Servo_out = 1;
    RCAP2L = 0xDF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
    RCAP2H = 0xB1;
  }
  flag = ~flag;
}

Servos wollen normalerweise einen 1.5ms High-Puls sehen. Wenn
ich mich nicht vertan habe, dann produziert das hier aber ein
invertiertes Signal.

von Sepp -. (sepp_o)


Lesenswert?

Salve

Bei meinen analiogen Servos mit denen ich's versucht habe, macht schon
eine Abweichung von mehr als 0,5ms bei de Pulsintervalls einen
gewaltigen Unterschied.

Es handelt sich dabei um Servos von Robbe.

Wenn da der Pulsintervall um mehr als 0,5ms abweicht, fängt der Servo
gewaltig an zu vibirieren, was den Verschleiß erhöht und den Verbrauch
um fast das Doppelte anhebt.

Wenn der Pulsintervall um mehr als 1ms abweicht, fängt der Servo an so
richtig zu flattern(+/- 20°).

Dafür schluckt das Servo eine Pulsbreite von 0,2ms bis 3ms.
Dabei hat das Servo einen Schwenkbereich von +/- 90° (von Anschlag zu
Anschlag).

von Sepp -. (sepp_o)


Lesenswert?

@Karl Heinz Buchegger
Du hast recht.

Diesen Fehler habe ich übersehen.

Dass kommt wenn man nur auf Kleinigkeiten schaut.

mfg Sepp

von Karl H. (kbuchegg)


Lesenswert?

@Henning

Hab mir Deinen Beitrag noch mal durchgelesen. Dort erklärst
Du warum du die Werte für serve_out getauscht hast.
Wie gesagt, ich kenne den Chip nicht und du wirst schon wissen
wovon du redest. Ich sollte besser meinen Mund halten ...

von Henning (Gast)


Lesenswert?

Uups!! Ich hab nen Fehler in dem Code. Ich hatte zum testen das TF2=0
als Kommentar markiert. Die Beiden Schrägstriche müssen natürlich
weg!!!

von Cristian Grigoruta (Gast)


Lesenswert?

WOW!!!!!!!!  Super!!!!Leute es klappt :)

das ist das Progi:
/* --*******************************************-- */
/* --  Servoansteuerung mittels AT89C52 / T2    -- */
/* --  12MHz Quarz         -- */
/* --*******************************************-- */

#include <AT89x52.h>


sbit Servo_out = P1^0;


void T2_int (void) interrupt 5
{
  static bit flag;

  TF2 = 0;

  if(flag)
  {
    Servo_out = 0;

    RCAP2L = 0x23;  // T2 mit 64 035 = 0xFA23 vorladen = 1.5ms
    RCAP2H = 0xFA;
  }
  else
  {
        Servo_out = 1;

    RCAP2L = 0xDF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
    RCAP2H = 0xB1;
  }
  flag = ~flag;
}


void main (void)
{

  Servo_out = 0;
  RCAP2H = 0xB9;
  RCAP2L = 0xAF;  // T2 mit 45 535 = 0xB1DF vorladen  = 20ms
  //RCAP2H = 0xB1;

//### TIMER initialisieren ###
  RCLK = 0;
  TCLK = 0;
  CP_RL2 =0;
  C_T2 =0;
  TR2 = 1;  // Start
  ET2 =1;         // Timer-Freigabe
  EA = 1;    // Allg. Interrupt-Freigabe

  while(1);
}

Echt toll dass ihr euch so ins Zeug gelegt habt. Vielen Dank!!!
Mfg Cri

von Cristian Grigoruta (Gast)


Lesenswert?

Hi. Ich bins nochmal :)

Ist das öfter der Fall dass der Servo bei 0.6ms den Linksanschlag hat
und bei 2.4 den Rechtsanschlag?

Sorry wegen dieser banalen Frage aber ich wollt mal nachfragen.
Mfg Cri

von Rahul (Gast)


Lesenswert?

Die Impulslänge zwischen 1ms und 2ms ist ein "alter" Standard (sollten
alle Servos unterstützen).
Inwzwischen wird das Telegramm wohl etwas besser ausgenutzt.

von Cristian Grigoruta (Gast)


Lesenswert?

Ja,wird wohl so sein.
Hab jetzt ganz genau eingestellt und die Zeiten vareieren von 0.57 -
2.43!  Mitte ist wie gehabt bei 1.5!

Mfg Cri

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.