PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitverögerung im ms Bereich



The Man
18.10.2007, 13:31
Hallo,

ich möchte ein Servosignal mit nem µC generieren. Das einzige was ich noch brauche ist eine Möglichkeit 18ms zu stoppen. Wie zeitstabil sind Monostabile Kippstufen?
Oder gibt es neben DEM NE555 auch IC´s die genau für sowas da sind?

THX
The Man

Lunarman
18.10.2007, 13:32
ääääääääh...
geht das nicht auch in Software via timer?

MfG
Lunarman

radbruch
18.10.2007, 16:42
Hallo

Möglichkeiten gibts da eine Menge, ich steuere z.b. 3 Servos mit einem 8MHz-ATMega8 ohne Interrupts (also blockierend) mit Zählschleife so:

https://www.roboternetz.de/phpBB2/viewtopic.php?p=321483#321483

Gruß

mic

The Man
18.10.2007, 18:29
@ radbruch,

wenn du auf einen Dummy Wert die Pulslänge aufaddierst, ist das doch nach definition kein echtes PWM mehr, weil sich ja die Periodendauer ändert. Sofern ich deine Programmbeschreibung korrekt verstanden habe.
Also braucht ein Servo kein echtes PWM? Und es kommt vorallem auf die Dauer des HIGH Pegels an?

Ich wollte die ms extern machen, um den Chip davon zu entlasten.

radbruch
18.10.2007, 18:51
Hallo

Streng genommen ist es schon eine Pulsweitenmodulation, allerdings nicht so wie man es von Antriebsmotoren kennt:

https://www.roboternetz.de/wissen/index.php/Servo

Entscheidend für die Position ist die Länge des High-Impulses (0,5-1,5ms). Mit der Low-Pause kann man beeinflußen, wie "aggressiv" das Servo die gewünschte Position ansteuert. Zum Austesten der Werte finde ich solche Zählschleifen prima, weil man genau weiß, was man da tut. Die Servos brauchen diese Puls/Pause-Folge übrigens bis sie die Position erreicht haben.

Viel eleganter und für mehr Servos geeignet ist der Beispielcode mit dem 100kHz-Timer in dem RNWissen-Beitrag oben. So erledigt der Prozessor die Servoaufgabe locker nebenher.

Übrigens hat die dummy-Zuweisung in den Schleifen keine pwm-Funktion. Sie dient nur dazu den Kompiler zu zwingen, den Code nicht wegzuoptimieren und die Schleife etwas zu verzögern.

Gruß

mic

The Man
18.10.2007, 19:03
ich nehme an mit "Viel eleganter und für mehr Servos geeignet ist der Beispielcode mit dem 100kHz-Timer in dem RNWissen-Beitrag oben. meinst du deinen verlinkten Beitrag?
Mein Prog soll über Kanalwechsel vier AD Werte ermitteln und die an vier Servos geben. Ich wollte das haben, um für zukünftige Projekte einen Simulator zu haben und nicht auf den RC Kasten angewiesen zu sein.

radbruch
18.10.2007, 21:21
Am Ende des Servo-Artikels im RNWissen ist ein Beispiel mit Timer und Interrupt. Aber das macht man nur so, wenn der µC zusätztlich auch noch viele andere Dinge tun soll.

Wenn du nur die 4 ADC-Werte an je ein Servo weitergeben möchtest, würde die Zählvariante vollkommen ausreichen. Mit wenig Mehraufwand könnte man auch noch eine einfache Trimfunktion einbauen und den Servoweg bei Vollausschlag beeinflussen.

mic

oberallgeier
18.10.2007, 23:22
Hi, radbruch,

Die Servos brauchen diese Puls/Pause-Folge übrigens bis sie die Position erreicht haben.
.. und dann? Ich dachte immer, Servos halten ihre Position nur, solange sie ein Signal bekommen!? Aber man hat doch sowieso bei EINEM Servo rund 18 bis 19 ms Pause - da kann man bei paar MHz einiges machen . . .

radbruch
19.10.2007, 00:22
Und dann werden die Servos nur durch die Selbsthemmung von Motor und Getriebe auf Position gehalten. Selbstverständlich kann man die Servos auch durchgehend mit dem Signal ansteuern. Ich wollte nur drauf hinweisen, weil die Servos eben auch eine Stellzeit benötigen. Aber das ist wohl eher unnötig, denn das hast du ja schon selbst gut im Griff.

Gruß

mic

oberallgeier
19.10.2007, 07:59
... dann werden die Servos nur durch die Selbsthemmung ... gehalten ...Ja schon. Da gehts den Servos wie mir :-b , aber irgendwo hat diese Selbsthemmung bei den Servos natürlich ;-) ein Ende. Und das ist relativ bald. Bei den Servos :lol: .

Na ja, im Griff ist übertrieben. Ich versuche immer noch einen PWM-Kanal für nur einen Schuss in der nötigen Länge hinzukriegen. Das könnte dann prächtig in einer ISR von 20 ms fahrbar sein. Weil ich doch in (m)einem tiny blos einen 8bit-timer habe :cry: .

The Man
19.10.2007, 11:37
Ich bin mit C für Controler nicht vertraut und bin nicht sicher, ob ich das aus dem Prog des RN Wissen Bereiche richtig erkenne. Aber das ist doch nur für einen Servo oder?
Ich hab das in Assembler gemacht. Das Prinzip ist, vier Ad Werte wandeln und im Ram speichern. Dabei wird immer Wert und dann dazugehöriger Pin abwechselnd gespeichert. Also der Kanal, auf dem der AD Wert entstand. Im nächsten Schritt wird alles der Größe nach sortiert. Zum Schluss muss noch der Fall behandelt werden, dass selbe Werte vorkommen. Dann wird der Timer2 mit IRQ alle bei 8 MHz, OCR2 = 32 gestartet und die Interrupte gezählt. stimmt die Anzahl mit einer Sollstellung überein, wird der entsprechende PIN LOW gesetzt und der nächste PIN sammt Stellung aus dem RAM gelesen.

oberallgeier
19.10.2007, 13:28
... ist doch nur für einen Servo oder? ... Im nächsten Schritt wird alles der Größe nach sortiert ...Stimmt wohl schon. So ungefähr will ich es angehen - weil mein kleiner tiny13 eben etwas beschränkt ist mit 5 Pinnen - ohne VCC, GND und notRESET.
Aber warum die Daten sortieren? Ein Servo braucht maximal 2 ms Aktivzeit und hat danach etwa 18 ms Pause. Dahinein würden also locker 7 weitere Servos (mit ein bisschen Puffer für IRS etc.) hineinpassen. ICH will das mit nur zwei Servos am tiny13 machen und arbeite (manchmal) dran.

radbruch
19.10.2007, 15:07
ICH will das mit nur zwei Servos am tiny13 machen und arbeite (manchmal) dran.
Und ich will das mit 3-5 Servos am tiny13 machen (und kann den Kleinen noch mal nicht flashen *heul*).


Ich versuche immer noch einen PWM-Kanal ... hinzukriegen.
Deshalb verwende ich vorerst die Zählschleifen, weil ich denke, das kann ich dann am einfachsten vom Mega8 auf den Tiny übertragen. Später ist dann schon ein Timer geplant, aber solange das Programm nur die Servos ansteuern muss, reicht die Zählerei vollkommen.


.. OCR2 = 32 gestartet und die Interrupte gezählt. Stimmt die Anzahl mit einer Sollstellung überein ..
Genau so würde ich das auch lösen. Man könnte die Impulse auch gleichzeitig für alle Servos starten und dann nacheinander ausschalten.

mic

oberallgeier
19.10.2007, 19:07
... am tiny13 machen (und kann den Kleinen noch mal nicht flashen *heul*) ... micHmmm, könnt ich (sollt ich) helfen? bitte PM

The Man
20.10.2007, 13:43
radbruch hat folgendes geschrieben: "Genau so würde ich das auch lösen. Man könnte die Impulse auch gleichzeitig für alle Servos starten und dann nacheinander ausschalten. " So mache ich das auch und deshalb müssen die Werte sortiert werden. Auf die Art bekommt man viel Zeit in der der µC noch anderes machen könnte. Bin mir aber nicht sicher, ob ich die optimale Lösung habe, ich verwende alle drei RAM Pointer.
(wie zitiere ich?)

Ich denke es ginge auch, während man zum einen servos stellt, mit dem selben Prinzip umgekehrt auch mehrere eingehende Signale zu erfassen.

oberallgeier
20.10.2007, 14:30
Hi, Man,

zitieren ist einfach (viel einfacher als PWM programmieren).


...(wie zitiere ich?)...Einfach in dem Beitrag, aus dem Du zitieren willst, rechts oben auf den button (zitat) knipsen. Dann geht ein Fenster auf mit allen möglichen buttons zum breitschreiben, zum Einfügen von code, für smilies etc.

Der Inhalt des Beitrags ist dann gleich in einem weissen Fenster - darin kannst Du editieren, damit Du nur genau das zitierst, was Du möchtest
Hallo,

ich möchte ein Servosignal mit nem µC generieren. OK? Ist das Zitieren jetzt klar?

Und das mit dem Sortieren - ich mach meine Parallel-Servos auf einem Tiny13 (womit arbeitest Du?), der hat nur einen Timer und nur mit 8 Bit - und das ist dann zu langsam für den High-Pegel der "Servo-PWM". Obwohl ich noch andere Probleme mit dem Prozessortakt habe: - ich hab gerade DEN Erfolg der Woche hinter mir - nach ewiger Suche (fast die ganze Nacht und heute vormittags) und nachdem ich einen Oskar ausgeliehen und einen neuen Servo gekauft hatte, habe ich festgestellt, dass meine Servo-Routine nicht funzt, weil ich den Prozessortakt umgestellt hatte, von 4,8 MHz auf 1,2 ](*,) ](*,) .

The Man
20.10.2007, 15:07
[quote="oberallgeier"]

Und das mit dem Sortieren - ich mach meine Parallel-Servos auf einem Tiny13 (womit arbeitest Du?), der hat nur einen Timer und nur mit 8 Bit - und das ist dann zu langsam für den High-Pegel der "Servo-PWM". [quote]

hm... irgendwas habe ich net verstanden

Ich benutzte dem mega8, hab das mit dem 16 Bit Timer aber noch nicht drauf => Timer2
ich hab mir das so ausgerechnet: 32/8000000Hz = 4*10^-6 s
und das multipliziert mit 250 ergibt dann 1ms was ja dem Delta des HIGH Pegels entspricht. daher lasse ich die schleife zuvor einmal "sinnlos" bis 250 durchlaufen, um sozusagen die 1ms offset zu kriegen.

oberallgeier
20.10.2007, 15:31
Hi, Man,

... hm... irgendwas habe ich net verstanden....Ist ja nicht wirklich wichtig. Dir fehlt im Text der slash - das ist der / ... der Schrägstrich über der "7" - vor dem zweiten "quote" - also direkt nach der zweiten eckigen Klammer-auf. Du hast einfach zuviel gelöscht :(. Das ist an HTML angelehnt. Ohne Schrägstrich = BefehlsANFANG, mit slash = Befehlsende. Alles was dazwischen ist, wird "ge-quotet".


Ich benutzte dem mega8, hab das mit dem 16 Bit Timer aber noch nicht drauf => Timer2...Siehste - ich hab eben NUR den 8 bittigen Timer. Aber demnächst ... in zwei, drei Wochen ... Aber Weihnachten ist ja erst in zwei Monaten :cry:

The Man
20.10.2007, 15:54
ich glaub, wir reden an einander vorbei.
die sache mit den 8 Bit hat doch nur Auswirkung auf die Auflösung.
Oder was meinst du mit



ich hab eben NUR den 8 bittigen Timer.

Weltherrschaft ein Stück näher - MUHAHA!

radbruch
20.10.2007, 15:58
Warum man die Werte sortieren muss, ist mir auch nicht klar. In C sieht meine ISR jetzt so aus:


ISR(TIMER0_COMP_vect)
{
static int count;
if(count>x) PORTA &= ~16; // E_INT1 (Pin8)
else PORTA |= 16;
if(count>y) PORTC &= ~1; // SCL (Pin10)
else PORTC |= 1;
if(count>z) PORTC &= ~2; // SDA (Pin12)
else PORTC |= 2;
if(count<2000)count++;
else count=0;
};


Und die Timer-Initialisierung sieht so aus:


DDRA |= 16; // E_INT1 als Ausgang
DDRC |= 3; // SCL und SDA als Ausgang

TCCR0 = (0 << WGM00) | (1 << WGM01)
| (0 << COM00) | (0 << COM01)
| (0 << CS02) | (1 << CS01) | (0 << CS00);
OCR0 = 9;
TIMSK = (1 << OCIE0);
sei();

Weil ich zu faul war um im Datenblatt nachzuschauen (bin Timer-Anfänger) verwende ich als Basis das Beispiel aus dem RN-Wissen und den auf 100kHz "aufgebohrten" Timercode aus der RP6-Library. Das ist aber nur mein aktueller Zwischenstand, ich bin da noch am testen. Soweit ich das Datenblatt durchschaue ist der Timer0 beim ATMega32 einer der 8bitigen Sorte: "8-bit Timer/Counter0 with PWM"

@oberallgeier:
Mein ISP-Problem mit dem tiny13:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=34808

Gruß

mic

The Man
20.10.2007, 20:50
wie gesat, in C für Controler bin ich net ganz fit und kann nur erahnen was da passiert.

Bei mir ist jeder Poti an einem ADC Pin von 0 bis 3 verunden (logisch).
Die werden in der langen LOW Phase gewandelt und in den Ramadressen 108 - 111 abgelegt.
Jetzt muss ja nicht der Wert vom Pin 0 bis 3 zunehemen - kann ja auch wild durcheinander sein. Also sortier ich sie.
Dabei kommt in die Adresse 100 der kleinste und in 101 der zu dem Wert gehörige Kanal. Diesen kann ich aus der Höhe der Ramadresse ableiten, wo ich den kleinsten Wert gefunden habe. Dann wird diese Adresse mit 255 überschrieben, denn aufgrund meiner Schaltung kann der ADC höchstens 250 sein.
Das passiert dann bis Adresse 107. Wert - Kanal - Wert - Kanal - Wert - Kanal - Wert - Kanal -
Jetzt muss ich schauen, ob es selbe Werte gibt.
Ich lade also den kleinsten Wert und vergleiche ihn mit dem nächsten. Ist er gleich addiere ich noch die Kanäle - die sollen ja dann auch zur selben Zeit ausgeschaltet werden. Diese landen in den Adressen 108 - 115

Nun kommt ein HIGH mit dem Offset 1ms und danach fange ich an die Adressen 108 bis 115 zu laden. Das dauert solange, bis alle PINs LOW sind.
Hier mal der Ker des Programmes, im Simulator des AVR Studio sieht man an den Registern 0 bis 15 ganz gut, was ich meine:


.include "m8def.inc"

.def tmp = r16
.def lowe = r17
.def lowz = r18
.def highe = r19
.def merker = r20
.def konst = r21
.def pin = r22

.def xlow = r26
.def xhigh = r27
.def ylow = r28
.def yhigh = r29
.def zlow = r30
.def zhigh = r31

ldi xlow,108
ldi lowe,20 ;PIN0 => WENN 1 => BYTEWERT = 1
st x+,lowe
ldi lowe,30 ;PIN1 => WENN 1 => BYTEWERT = 2
st x+,lowe
ldi lowe,30 ;PIN2 => WENN 1 => BYTEWERT = 4
st x+,lowe
ldi lowe,10 ;PIN3 => WENN 1 => BYTEWERT = 8
st x,lowe

ldi konst,4

ldi xlow,100
ldi ylow,108 ;von 108 bis 111 (112)
add ylow,konst ;von 112 bis 116
ldi tmp,1
st y+,tmp
ldi tmp,2
st y+,tmp
ldi tmp,4
st y+,tmp
ldi tmp,8
st y+,tmp
subi ylow,8
ldi zlow,108

ldi lowe,255


schleife2:

schleife1:

ld lowz,y
cp lowe,lowz
brlo istkleiner
mov lowe,lowz
mov zlow,ylow
istkleiner:
inc ylow

cpi r28,112
brlo schleife1
add r30,konst ;0b10000000 => Bereich 136 bis 139
ld merker,Z ;dort ist der PIN Wert gespeichert
subi r30,4

st x+,lowe
st x+,merker
ldi lowe,255

st z,lowe
ldi ylow,108
ldi zlow,108

cpi xlow,108
brlo schleife2

ldi r26,100
ld r0,x+;100 zyclus
ld r1,x+;101 pin
ld r2,x+;102
ld r3,x+;103
ld r4,x+;104
ld r5,x+;105
ld r6,x+;106
ld r7,x+;107
ldi r26,100
ldi r30,108
ldi tmp,0
sorten:

ld lowe,x+
st z+,lowe
ld pin,x+
add pin,tmp
mov tmp,pin
st z+,pin
ld lowz,x

cp lowz,lowe
brne diff
dec r30
dec r30
rjmp gleich
diff:
ldi tmp,0
gleich:
cpi r26,108
brne sorten

ldi r26,108
ld r8,x+;100 zyclus
ld r9,x+;101 pin
ld r10,x+;102
ld r11,x+;103
ld r12,x+;104
ld r13,x+;105
ld r14,x+;106
ld r15,x+;107
nop
nop
nop

The Man
25.10.2007, 14:40
Stimmt, keine Ahnung, warum ich die Dinger sortiere...muss nicht sein^^

Ah, ja doch, da war was. Mein Gedanke war, das während der min. 18ms die meiste Zeit ist. Während ich die Pins LOW setzte, muss das Prog nichts machen, außer die Zeiger auf den nächsten Wert und Pin hochzuzählen. Angenommen, man würde die Auflösung stark erhöhen, währe das eine gute Möglichkeit in der zeitkritischsten Phase möglichst schnell zu sein.

Für meine 8 BIT natürlich zu kompliziert.

oberallgeier
25.10.2007, 20:16
Ohhhh Man (auf deutsch Ohhhh Mannnn),

ich glaub, ich versteh Dich jetzt. Vermutlich. Du willst wohl in den aktiven Phasen die Servo-Rampen (1..2 ms) HINTEREINANDER ausgeben ! ? Um die Belastung der Stromquelle zu verringern? Aber dazu bräuchtest Du doch nix zu sortieren.

ICH guck in meinem Programm in der ISR nach, ob der (irgendein) Port an ist - und dann KÖNNTE ich NUR DIESEN EINEN Port bedienen, bis die Rampe aus ist ( - ich habe es aber so gelöst, dass ich alle Rampen gleichzeitig anknipse, und dann je nach Anforderung an die Länge abschalte) . Danach käme der nächste Port in der Reihe dran. JEDER in einer beliebigen zeitlichen Rampenlänge und in beliebiger Reihenfolge. Und das mach ich am tiny13 (aber ich hab keine vier Potis dran, weil ich ja nur fünf Pinne zum Datentransfer habe - na ja, sechs gingen mit dem notRES).

>>> MERKE <<< Fauhlheit ist eine der Wurzeln innovativen Arbeitens =D>