Forum: Mikrocontroller und Digitale Elektronik attiny2313 als Servocontroller über I2C


von MICHEL (Gast)


Lesenswert?

Hallo liebe Forenmitglieder,
Ich will momentan ein kleines System zusammenbasteln und hänge bei der 
Servosteuerung. Mein "HauptµC" ist ein ATmega 16. Es sollen bis zu 8 
servos angesteuert werden. Da der ATmega 16 mit anderen Aufgaben 
beschäftigt ist und deswegen nicht die ganze zeit die Servopositionen 
nachstellen kann hab ich mir gedacht ich könnte einen attiny2313 als 
Servocontroller verwenden.

Am besten wäre es wenn der ATmega 16 die Position eins Servos die sich 
verändert hat an den attiny2313 übergibt und dieser dann einfach beim 
nächsten Durchgang den Servo neustellt.

Ich hab nur noch nie mit I2C gearbeitet und habe deswegen ein paar 
Fragen:

1. Macht das ganze überhaupt Sinn?

2. Wie übertrage ich am besten die Daten (Programmierung in Assembler) ?

3. Ist es zu lange wenn die Servos 140ms auf ein neues Signal warten 
müssen.

4. Gibt es eventuell Servos mit "Save position" wo einmal eine Position 
bekommen und diese halten ?

Würde mich über Antworten freue
und wenn eine Frage unnötig oder einfach nur blöd ist möchte ich mich 
schonmal entschuldigen. Bin noch ein Newbie lerne aber gern :D

Mfg MICHEL

von Karl H. (kbuchegg)


Lesenswert?

MICHEL schrieb:
> Hallo liebe Forenmitglieder,
> Ich will momentan ein kleines System zusammenbasteln und hänge bei der
> Servosteuerung. Mein "HauptµC" ist ein ATmega 16. Es sollen bis zu 8
> servos angesteuert werden. Da der ATmega 16 mit anderen Aufgaben
> beschäftigt ist und deswegen nicht die ganze zeit die Servopositionen
> nachstellen kann hab ich mir gedacht ich könnte einen attiny2313 als
> Servocontroller verwenden.

Warum?
Ein Mega16 kann mit einem Timer 8 Servos relativ problemlos nebenher 
versorgen.

Modellbauservo Ansteuerung
Punkt 4: Signalerzeugung für mehrere Servos mittels Timer

> Am besten wäre es wenn der ATmega 16 die Position eins Servos die sich
> verändert hat an den attiny2313 übergibt und dieser dann einfach beim
> nächsten Durchgang den Servo neustellt.

Das ist in Summe für den Mega16 mehr Aufwand, als wie wenn er gleich 
selber die Servosignale generiert :-)

von MICHEL (Gast)


Lesenswert?

Ich dacht nur es wird ein problem wenn der ATmega 16 gerade alle Servos 
neustellt , was ja 160 ms dauert und ein input ,Tastendruck etc., kommt. 
Ich noch ein bischen verwirrt :D. Bei Servos müssen ja alle 20 ms die 
Position wieder aufgefrischt werden oder.

von Karl H. (kbuchegg)


Lesenswert?

MICHEL schrieb:
> Ich dacht nur es wird ein problem wenn der ATmega 16 gerade alle Servos
> neustellt , was ja 160 ms dauert

Falsch gedacht.
Sieh dir den Link an. Der Mega hat alle (durchschnittlich) 1.5ms ein 
paar Takte lang damit zu tun einem Servo den Puls abzuschalten und dem 
nächsten Servo den Puls zuzuschalten. Mehr ist das nicht.
Geschätzer Rechenzeitverbrauch für 8 Servos: Weniger als 1% der komplett 
verfügbaren Rechenzeit.
Das die Zeiten eingehalten werden, dafür sorgt der Timer, der nebenher 
die Zeit runterzählt. Damit hat die Recheneinheit nichts zu tun. Sie 
muss sich nur quasi 'den Wecker stellen', wann der Puls des gerade 
aktuellen Servos wieder abzuschalten ist.

> Ich noch ein bischen verwirrt :D. Bei Servos müssen ja alle 20 ms die
> Position wieder aufgefrischt werden oder.

Lies den Link. Am besten von Anfang an.
(Dann lernst du auch, dass dir diese 20ms am allerwenigsten 
Kopfzerbrechen machen müssen. Die sind bei einer Servoansteuerung so 
ziemlich das Unwichtigste.)

von R. M. (rmax)


Lesenswert?

Karl Heinz Buchegger schrieb:
> (Dann lernst du auch, dass dir diese 20ms am allerwenigsten
> Kopfzerbrechen machen müssen. Die sind bei einer Servoansteuerung so
> ziemlich das Unwichtigste.)

Nur zu kurz sollten sie nicht sein. Wir hatten erst neulich den Fall 
(allerdings mit Brushless-Controllern, die über Servo-Signale gesteuert 
werden), daß bei zu hoher Refresh-Rate der Motor anfing zu "zappeln".

Mag sein, daß das bei echten Servos nicht so kritisch ist, aber ich 
würde, wenn die "Schleife" nur wenige Servos zu bedienen hat, zur 
Sicherheit nach jedem Durchlauf noch eine Pause einlegen, um zumindest 
in die Nähe der 20ms zu kommen.

von Karl H. (kbuchegg)


Lesenswert?

R. Max schrieb:

> Nur zu kurz sollten sie nicht sein.

Richtig.
Ich hab alle meine Servos durchprobiert. Alle haben bei 10ms noch 
mitgespielt, die meisten machten auch 8ms noch mit.

> Wir hatten erst neulich den Fall
> (allerdings mit Brushless-Controllern, die über Servo-Signale gesteuert
> werden), daß bei zu hoher Refresh-Rate der Motor anfing zu "zappeln".

Das kann ich mir schon vorstellen.
In den Servocontrollern ist ja eine Regelschleife drinnen, die auf eine 
Zykluszeit angewiesen ist.
Allerdings muss die auch recht großzügig ausgelegt sein, denn selbst 
Fernsteuerungen halten sich nicht daran. Eine alte PPM 4 Kanal Anlage 
erzeugt ein anderes Timing Diagramm als eine 9 Kanal.

> Sicherheit nach jedem Durchlauf noch eine Pause einlegen, um zumindest
> in die Nähe der 20ms zu kommen.

Bei 8 Servos mit im Schnitt 1.5ms Pulszeiten, hast du automatisch 
bereits 8*1.5 = 12ms durchscnittliche Zykluszeit von einem Puls zum 
näschsten. Für normale Servos sollte das reichen.
Wenn nicht, kann man in der Timerlösung auch einfach ein 'virtuelles' 9. 
Servo einführen, welches dann die restliche Zeit auf 20ms frisst. Aber 
normal sollte das nicht notwendig sein.

von MICHEL (Gast)


Lesenswert?

Den Link hab ich gar nicht gesehen :D. Werd ihn mir gut durchlesen und 
bin dann hoffentlich schlauer. Vielen Dank.

von MICHEL (Gast)


Lesenswert?

Ich hab mir den text durchgelesen und habe nur eine Verständnis Frage: 
Es heißt im Text das der Positions impuls also die 2ms bzw 1.5 oder egal 
was am wichtigsten ist und die pause relativ gelassen angegangen wird. 
Sprich ich habe einem Servo eine Position gegeben und auch wenn ich ihm 
eine ganze Zeit lang die Position nicht wiederhole bleibt er in seiner 
Position, außer natürlich die Last ist zu groß oder weiß gott was. 
Stimmt das so oder hab ich noch ein Poblem in meinem Gedankenmodel?

Mfg MICHEL

von Karl H. (kbuchegg)


Lesenswert?

MICHEL schrieb:
> Ich hab mir den text durchgelesen und habe nur eine Verständnis Frage:
> Es heißt im Text das der Positions impuls also die 2ms bzw 1.5 oder egal
> was am wichtigsten ist und die pause relativ gelassen angegangen wird.
> Sprich ich habe einem Servo eine Position gegeben und auch wenn ich ihm
> eine ganze Zeit lang die Position nicht wiederhole bleibt er in seiner
> Position, außer natürlich die Last ist zu groß oder weiß gott was.
> Stimmt das so oder hab ich noch ein Poblem in meinem Gedankenmodel?

Ho, ho, ho
Immer langsam mit den jungen Pferden.

'relativ gelassen' heißt jetzt nicht, dass du eine halbe Stunde lange 
keine Pulse schicken brauchst.
'relativ gelassen' bedeutet: Ob 20ms oder 19 oder 21 oder 15 ist relativ 
wurscht. Also ein bischen Augenmass bei den tolerierbaren Fehlern walten 
lassen. Wenn du die 'akademische Viertelstunde' zu spät kommst, wird das 
in den meisten Fällen toleriert. Wenn du aber zum Abendessen 2 Stunden 
zu spät kommst, hängt der Haussegen schief.

von R. M. (rmax)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Bei 8 Servos mit im Schnitt 1.5ms Pulszeiten, hast du automatisch
> bereits 8*1.5 = 12ms durchscnittliche Zykluszeit von einem Puls zum
> näschsten.

Das Timing sollte aber so ausgelegt sein, daß es auch im Extremfall noch 
funktioniert, also muß man die minimale Zykluszeit betrachten und die 
liegt bei 8ms und wenn man die Reserven nutzt sogar darunter. Kann sein, 
daß das immer noch reicht, aber für weniger als 6-8 Servos sollte auf 
jeden Fall eine Wartezeit hinein.

von Karl H. (kbuchegg)


Lesenswert?

R. Max schrieb:
> Karl Heinz Buchegger schrieb:
>
>> Bei 8 Servos mit im Schnitt 1.5ms Pulszeiten, hast du automatisch
>> bereits 8*1.5 = 12ms durchscnittliche Zykluszeit von einem Puls zum
>> näschsten.
>
> Das Timing sollte aber so ausgelegt sein, daß es auch im Extremfall noch
> funktioniert, also muß man die minimale Zykluszeit betrachten und die
> liegt bei 8ms und wenn man die Reserven nutzt sogar darunter. Kann sein,
> daß das immer noch reicht, aber für weniger als 6-8 Servos sollte auf
> jeden Fall eine Wartezeit hinein.

D'accord.

(Hmm. Da sollte ich den Artikel mal dahingehend nachbearbeiten. Der Code 
ist eigentlich Abfallprodukt aus der Ansteuerung von 12 Servos.
MICHEL: probier den Code einfach mal so aus wie er ist. Eine 
entsprechende Änderung ist an für sich trivial, aber ich will den lieber 
vorher am realen Objekt mit ein paar Servos drann testen)

von MICHEL (Gast)


Lesenswert?

Ok ich versteh jetzt was ihr meint. Was ich noch nicht verstanden hab 
ist wie ich diese Routine die ganze zeit neben dem "Hauptprogramm" 
laufen lassen kann. Das ich einen Timer brauch ist klar. Dieser löst 
,wenn ich richtig bin, einen interrupt aus der zur entsprechenden 
funktion verzweigt. Der Code im Beispiel ist dummerweise in C ich würde 
gern in assembler bleiben. Ist das ein Problem.

von Karl H. (kbuchegg)


Lesenswert?

MICHEL schrieb:
> Ok ich versteh jetzt was ihr meint. Was ich noch nicht verstanden hab
> ist wie ich diese Routine die ganze zeit neben dem "Hauptprogramm"
> laufen lassen kann.

Die läuft ganz von alleine :-)

> Das ich einen Timer brauch ist klar. Dieser löst
> ,wenn ich richtig bin, einen interrupt aus der zur entsprechenden
> funktion verzweigt.

ganz genau

> Der Code im Beispiel ist dummerweise in C ich würde
> gern in assembler bleiben. Ist das ein Problem.

Nö. Im wesentlichen ist das ja nur ein bischen rumrechnen und Register 
befüllen. Ob du
1
   OCR2 = 123;
in C schreibst oder
1
  ldi r16, 123
2
  out OCR2, r16
kommt sich ja aufs gleiche raus. Entscheidend ist, dass der Wert im OCR2 
Register landet. Wie ich das hinschreibe ist ja zweitrangig.

Nur schreib ich lieber in C, weil ich mich da um den ganzen Kleinkram 
nicht kümmern muss. Ich hab da halt einfach ein paar Variablen im SRAM 
und wenn ich darauf zugreife kümmert sich der Compiler um den ganzen 
Kleinkram wie Adresse in Register laden und dergleichen. Was soll ich 
mir den Kopf zerbrechen, welche Register ich für eine 8-Bit * 8 Bit 
Multiplikation brauche? Ich schreib einfach a*b hin und überlass es dem 
Compiler, dafür die Instruktionen zu finden. Im Normalfall macht der das 
auch nicht schlechter, als wie wenn ich selbst durch die ganze Sequenz 
in Assembler durchgehe:
   Werte aus dem SRAM in Register laden (die vorher u.U freigeschaufelt
       werden müssen)
   Multiplizieren
   mit dem Ergebnis etwas machen, zb in ein Timerregister laden
Nur mit dem einen Unterschied, dass ich in Assembler erst mal 25 Fehler 
reinbaue, während der Compiler
   OCR2 = wert1 * wert2;
auf Anhieb korrekt übersetzt :-)

Die Zeiten, in denen ich beim Autofahren höchstpersönlich jede Zündkerze 
händisch gezündet habe, sind vorbei :-) Das überlass ich lieber dem 
Automaten. Der mag in Extremsituationen vielleicht nicht immer den 
besten Zündwinkel einstellen, aber im Schnitt schlägt er sich nicht 
schlecht.

von R. M. (rmax)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Da sollte ich den Artikel mal dahingehend nachbearbeiten.

Genau dahin wollte ich Dich bringen. ;)

> Der Code ist eigentlich Abfallprodukt aus der Ansteuerung von 12 Servos

Klar, da ist eine künstliche Pause überflüssig.

von R. M. (rmax)


Lesenswert?

Da fällt mir eben noch was auf an dem Artikel:
Du schreibst, der verwendete Timer muß den CTC-Mode beherrschen. Spricht 
denn ewtas dagegen, einen Timer im Normal-Mode zu verwenden und das OCR 
jeweils um den Wert für den nächsten Puls zu erhöhen? Dabei würde als 
Nebenprodukt sogar noch ein periodischer Timer anfallen, falls man einen 
braucht, z.B. für Tastenabfragen und -entprellung.

von Karl H. (kbuchegg)


Lesenswert?

R. Max schrieb:
> Da fällt mir eben noch was auf an dem Artikel:
> Du schreibst, der verwendete Timer muß den CTC-Mode beherrschen. Spricht
> denn ewtas dagegen, einen Timer im Normal-Mode zu verwenden und das OCR
> jeweils um den Wert für den nächsten Puls zu erhöhen?

Nein, spricht nix dagegen. In der ISR hat man Zeit genug. Der nächste 
Interrupt kommt ja frühestens erst nach 1ms. Das ist nicht wirklich 
zeitkritisch.

> Dabei würde als
> Nebenprodukt sogar noch ein periodischer Timer anfallen, falls man einen
> braucht, z.B. für Tastenabfragen und -entprellung.

Gute Idee. Könnte man als Alternative ausprogrammieren.

von R. M. (rmax)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Der nächste Interrupt kommt ja frühestens erst nach 1ms.
> Das ist nicht wirklich zeitkritisch.

Eben.

CTC hat aber eh nur einen minimalen Vorteil, denn durch die Änderung 
(ersetze "OCR2 =" durch "OCR2 +=") verlängert sich der Assembler-Output 
für die ISR um gerade mal zwei Instruktionen, von 53 auf 55. Wenn es 
also zeitktitisch wäre, müßte man sich ohnehin etwas anderes einfallen 
lassen.

von Stefan Frings (Gast)


Lesenswert?

Ich habe das schon vor einigen Monaten gemacht:
http://stefanfrings.de/servocontroller/index.html

Da kannst du abgucken oder gleich 1:1 kopieren.

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.