www.mikrocontroller.net

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


Autor: Cristian Grigoruta (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber vom Programmaufbau stimmt es ?
 Verwende einen 12MHz Quarz.

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist bitte IMHO?

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie weiß ich wie lange die ISR dauert?

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Cristian Grigoruta (Gast)
Datum:

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

Autor: Cristian Grigoruta (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cristian Grigoruta (Gast)
Datum:

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

Mfg Cri

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bzw. wie man sowas in C schreibt!

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cristian Grigoruta (Gast)
Datum:

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

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

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

Nein.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Henning (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Sepp -o- (sepp_o)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sepp -o- (sepp_o)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Sepp -o- (sepp_o)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz Buchegger
Du hast recht.

Diesen Fehler habe ich übersehen.

Dass kommt wenn man nur auf Kleinigkeiten schaut.

mfg Sepp

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Henning (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Cristian Grigoruta (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.