Forum: Mikrocontroller und Digitale Elektronik (Servo-) Impulse mit AVR intelligent ausgeben


von UBoot-Stocki (Gast)


Lesenswert?

Hallo,

meine ersten AVR Gehversuche sind gar nicht schlecht geworden. Ich habe 
z.B. einen AVR so programmiert, daß er die Gültigkeit eines 
Servo-Signals überprüfen kann (Capture-Interrupt und Timer)

Jetzt aber zu meiner Frage:

Was könnte eine intelligente Methode sein, einen 1-2ms langen Impuls 
alle ca. 20 ms wiederholt mit einem AVR auszugeben?

Das "dumme" ausführen einer Warteschleife kann ich nicht machen, da der 
AVR zwischenzeitlich noch andere Dinge machen soll ... Leider habe ich 
keine Methode über den Timer gefunden (das mit dem PWM-Ausgang scheint 
für meinen Anwendungsfall nicht geeignet zu sein ...)

Wer hat eine Idee ?

Gruß

UBoot-Stocki

von André Füßer (Gast)


Lesenswert?

Timerinterrupt alle 20ms aufrufen lassen, anfangs Pegel setzen, 1-2ms 
"dumm" warten, Pegel löschen... so bleiben fürs Hauptprogramm 18ms bis 
zum nächsten Interrupt übrig.

André.

--
CAN@home - http://www.CANathome.de - Hausautomation mit AVR + CAN

von Siegfried (Gast)


Lesenswert?

Aus der Hüfte geschossen würde ich sagen, mach doch einen 
Timer-Interrupt genügend klein um dann mit einem entsprechend 
softwaremässig eingestellten Counter die Impulsweite bzw. -Pause zu 
bestimmen.

Bei näherer Betrachtung taucht ein Problem auf:

1-2 ms = 1000 - 2000 µS.
Mal angenommen, zwischen den beiden Vollausschlägen des Servos sollen 
100 Schritte liegen !?. Dann muss die Software Impulsweiten von 1000, 
1010, 1020, .... 2000 µS. Mit anderen Worten, der Timer muss auf 10µS 
eingestellt werden. Die Zeit ist doch recht knapp, um den 
Interrupservice auszuführen. Ein Atmel mit 8 MHZ macht zwar 4 Befehle 
pro µS = 40 Befehle pro 10µS. Das wird immerhin noch knapp genug für die 
Anwendung.

Anderer Ansatz:
Mit einem Timer erzeugt man wie bereits von Andre beschrieben einen 20ms 
Interrupt und ein anderer Timer wird immer mit der jeweilig 
einzustellenden Impulszeit aufgezogen. Der 20 ms Timer sorgt dafür, das 
die gesammte Steuersequenz im 20ms Takt angeschossen wird.

Wieviel Servos sollen denn angesteuert werden?
Bei Fernsteuerempfängern folgen die Impulse nacheinander an die Servos. 
Falls der Impuls zeitgleich für alle Servos kommt, könnte es Probleme 
mit Stromspitzen geben.

Siegfried

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

vielen Dank für die Antworten. Sie haben mich doch schon nachdenklich 
gemacht....

@Siegfried: Ich arbeite an einem Regler für die UBoot-Tiefe. Über einen 
Drucksensor soll der Istwert (noch aufzubauendes ADC-Programm) ermittelt 
werden. Der Sollwert kommt von der Fernsteuerung ( Capture mit Timer 1 
s.o.). Ausgegeben werden soll das ganze an die Tauchzelle (das sind 2 
Ltg. eines Ports) und an die zwei Tiefenruder -> zwei Servos. Die 
Impulse für die Servos sollen nacheinander erzeugt werden.

Was haltet Ihr von folgender Idee:

Der 1-2ms Impuls wird mittels 8BIT-Timer (Timer 1) erzeugt. der 
"CPU-Teiler" wird so eingestellt, daß in 1 ms (2ms - 1ms = 1ms :-) ) 
möglichst 255 Schritte gemacht werden können.
Nach dem Timerüberlauf in der Interrupt-Routine wird die Timer-Zeit neu 
eingestellt  (für das 2. Servo).
Danach wird in der Int-Routine der Teiler und die Zeit so verstellt, daß 
ca. 16ms Ablaufen können.

Frage: Ist es "üblich / erlaubt" den Timer sowie den Teiler zur Laufzeit 
ständig zu verstellen ?

Gruß

Andreas

von A.Füßer (Gast)


Lesenswert?

> Was haltet Ihr von folgender Idee:
gut.

>Frage: Ist es "üblich / erlaubt" den Timer sowie den Teiler zur Laufzeit ständig 
zu verstellen ?
Ja/ja. Anhalten während des Umstellens schadet nicht.

André.

--
CAN@home - http://www.CANathome.de - Hausautomation mit AVR + CAN

von Siegfried (Gast)


Lesenswert?

Gute Idee.

oder so:

1. 20000 merken (= 20 ms)
2. 20000 - 1500 (abzgl. Impulslänge 1,5 ms des Servo1)
3. 18500 - 1400 (abzgl. Impulslänge 1,4 ms des Servo2)
4. 17100 ( = 17,1 ms) Restzeit bis zum Schritt 1.

Ob es die Servos den Impuls nach genau 20ms brauchen, weis ich leider 
nicht. Es würde mich allerdings auch interessieren.

Siegfried

von Björn Jonas (Gast)


Lesenswert?

Hallo,

es müssen nicht genau 20ms sein. Ich hab die Zeit mal auf 40ms 
hochgeschraubt, weil ich sonst nicht mehr genug Rechenleistung hatte.
Wenn der Servo keine Impulse bekommt bleibt er meist in Position, regelt 
aber nicht mehr nach. D.h. man kann den Servo dann verstellen.

-> Ausprobieren bis zu welchem Implusabstand das Ergebnis noch 
zufriedenstellen ist.

Bei Timern sollte man die Interruptlatenzzeit berücksichtigen, Stichwort 
Jitter. Ein rumzitternder Servo ist ja meist nicht erwünscht.

Björn

von UBoot-Stocki (Gast)


Lesenswert?

Hi,

ich habe gestern mal ein bischen rumexperimentiert. Das Problem war 
folgendes:

Bei 4 MHz AVR-Taktfrequenz und 1ms Servo-Impuls (von ganz rechts bis 
ganz links) möchte ich schon die vollen 8 BIT Auflösung des Timers haben 
(-> 255 Servoschritte). Dies bedeutet das der Zähler auf 0,001s / 
1/4.000.000Hz = 4000 zählen müsste. Da er nur 8 BIT hat, brauche ich 
einen Teiler von 4000 / 256 = 15,.. = 16. Dummerweise bietet der Zähler 
aber nur einen Teiler von 8 :-(

Ich habe es erstmal so gelöst, daß ich mit Teiler 8 arbeite und die 
Interrupt-Routine einfach 4x aufrufe...  (2x um 1ms zu erzeugen und 2x 
für die Zeit für das Servo (0-1ms) ) :-)))
Die (in diesem Beispiel) 18ms bis zum nächsten impuls bekomme ich dann 
über den Teiler 1024 (0,018s / 1/4000000Hz)

Das funktioniert gut. Was mir nicht gefällt, ist die Tatsache, daß wenn 
man von zwei oder drei oder gar mehreren Servos ausgeht, die 
Interrupt-Routine ganz schön kompliziert wird. Ich müßte ja für jedes 
Servo quasi zuerst 1ms ausgeben und dann Servo-spezifisch den Impuls 
verlängern. Hätte also 8 (bei 8 Servos) Interrupt-Routinen oder eine mit 
einem gigantischen "if case" ......

Frage:

In C löst man sowas mit einer Routine und einem Zeiger ! Wie macht man 
einen Zeiger auf eine Tabelle (mit Werten für die Servos) in Assembler ? 
Wie legt man die Werte für die Servos in dieser Tabelle (RAM?) ab ?

Wer hat Anregungen ?

Gruß

UBoot-Stocki

von H. Howey (Gast)


Lesenswert?

Hallo...
beim durchstöbern von Zeitschriften, bin ich auf einen Bericht aus der 
Zeitschrift Elektor 09/2001 gestoßen. Dort wird über eine I2C 
Schnittstelle ein Servointerface mit acht Servos beschrieben 
(erweiterbar bis 64 Servos). Das Ganze besteht aus ein paar NE 555 bzw. 
NE 556 und dem I2C IC TDA8444 (mit D/A).
Diese Schaltung kann man auch so modifizieren, das man sich das 
Interface spart und sofort an den MC ran geht (wenn man will :-). Die 
Funktion ist, das die Timer (556) durch den Control Eingang CV die 
Impulsbreite vergrößert wird.
Zumindest reduziert sich der Aufwand durch den Einsatz von 
Hardware-Timern erheblich.
Gruß
H. Howey

von H. van Gils (Gast)


Lesenswert?

es gibt bijspiel code fur 8 servo stuerung im background auf seite 
http://www.dvanhorn.org/AvrSoftware/Index.php
.

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.