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
Tja... da werden wohl die Zeiten nicht stimmem.. endweder bist du zu schnell, oder zu langsam
>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.
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...
wow....hab vorher noch nie von IMHO gehört und schon garnet die Befehle gezählt :)
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
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
Sorry Peter,aber ich verstehe nicht was du meinst. Kannst es mir, blutigen Anfänger, etwas genauer erklären? Mfg Cri
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.
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
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.
@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.
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
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.
> 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.
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
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.
> 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.
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.
[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]
Um es noch klarer auszudrücken: es werden ENTWEDER Anweisungen1 ODER Anweisungen2 ausgeführt. Es kann nie vorkommen, dass beide Anweisungsteile ausgeführt werden.
sorry Leut...deshalb habe ich ja auch nachgefragt.hmm...nicht sauer werden.Man lernt ja. Versuch es nun ohne ez++
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?
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?
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.
>Kanns vielleicht daran liegen dass ich den Servo (signalleitung) direkt am µC hängen hab? >Muss ich da evetuell einen Transistor vorschalten? Nein.
@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.
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
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
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.
@ 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.
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).
@Karl Heinz Buchegger Du hast recht. Diesen Fehler habe ich übersehen. Dass kommt wenn man nur auf Kleinigkeiten schaut. mfg Sepp
@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 ...
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!!!
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
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
Die Impulslänge zwischen 1ms und 2ms ist ein "alter" Standard (sollten alle Servos unterstützen). Inwzwischen wird das Telegramm wohl etwas besser ausgenutzt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.