PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Viele Servos an einem Chip



Feratu
05.11.2007, 14:54
Sers
Ich bin grad dabei meinem Robbi Beine zu bauen
An jedem Bein sind 6 Servos angeschlossen wobei das für ausreichende Beweglichkeit genügen sollte ;P

Ich habe momentan den Chip "Atmel ATMega 8535" der mit 16MHz läuft.
Da dieser leider nur 3 Hardware PWM's besitzt bin ich gezwungen auf software umzusteigen.
(unter allgemein => Software PWM kann man sich das mal anguggn ;P)

Ich wollte nun fragen ob mir jemand einen Microprozessor empfehlen kann der soviele Hardware PWM ausgänge besitzt.
Oder vielleicht eine art erweiterung für meinen aktuellen Chip mit dem ich diese auch ansteuern kann.
Zur not nehm ich einfach 2 von denen ^^
Wenn jemand eine bessere Idee hat wie man Servos optimal ansteuert nur raus damit ^^


Danke schonmal im vorraus

mfg
Feratu

gummi_ente
05.11.2007, 17:03
Hallo Feratu,

Du könntest einen Timer-IRQ laufen lassen mit der notwendigen Auflösung der PWM, in der eine Varible hochgezählt wird.

Dann kannst Du im Hauptprogramm am Anfang alle Ausgänge setzen und dann bei jedem neuen Wert der Variablen die einzelnen Kanäle prüfen ob diese wieder abgeschaltet werden müßen.

Servos werden normalerweise alle 20ms mit einem Puls von 1..2ms angesteuert. Um eine Auflösung von 100 Schritten zu erreichen muß dein Timer-IRQ mit 1ms/100 = 10µs laufen, in der Zeit kann der µC ca. 150 Befehle verarbeiten.

Da nach 2ms alle Ausgänge wieder null sind hätte der µC die restlichen 18ms nichts zu tun, diese kann man nutzen um wieder so ein 2ms Paket einzuschieben.

So kann man schon eine ganze Reihe von Servos steuern. Aber die Soll-Daten müßen ja auch irgendwie in den Controller, daher sollte man dazu noch was Luft lassen.

Grüße


Grüße

robocat
05.11.2007, 17:27
ich arbeite gerade an etwas ähnlichem und gehe folgendermassen vor:
alle 20ms (timer-interrupt) werden alle servo ports eingeschalten. nach einer weiteren ms wird in eine blockierende funktion gesprungen, die die servo-pins wieder abschaltet, in etwa so (opcode):

for(i=0;i<255;i++) // schleife dauert max. 1ms
{
if(i>servoposition1)SERVOPORTn=0;
else warte_solang_wie_wenn_bedingung_erfüllt();
if(i>servoposition2)..
...
}
je nach servo-anzahl wird die auflösung natürlich geringer, bei mehr als 12 servos sollte man evtl. auf 2 funktionen aufsplitten, die abwechselnd alle 10ms aufgerufen werden.

da die funktion zeitkritisch ist, schreibt man sie am besten in assembler. den rest der zeit (18-19ms) hat man für andere berechnungen frei.

gruesse von der katz

Feratu
05.11.2007, 17:50
Moin
https://www.roboternetz.de/phpBB2/viewtopic.php?t=35211
Das steht meine Aktelle ansteuerung von 6 Servos über die selbe Methode, wie in deinem Vorschlag.
Allderdings sind 6 Servos zuwenig und wenn ich mehr hinzufüge sinkt die Genauigkeit der Servos da ich die Frequenz des Timers verringern müsste.
Wenn die frequenz zu hoch ist dann eiert der controller nurnoch im ISR des Timers rum und die normale Hauptschleife Funktioniert garnicht mehr.
Das selbe Problem tritt auf wenn ich zuviele IF schleifen in den Timer schreibe . Leider habe ich keine Bessere Idee wie ich um die schleifen herum komme.

Wäre großartig wenn du deine Idee hast was ich an meiner PWM verbessern könnte bzw wie ich das Problem lösen könnte.

Ist es eigentlich möglich 2 Microcontroller so zu vernetzen das sie funktionieren wie ein großer?
Oder gibt es einen Chip der eine PWm weobei man die Pulsweite über ein Bus System steuert ?

Noch meine Frage an euch was ihr davon haltet:
Ich dachte mir ich baue eine Art AT ST aus starwars nach

Hier ein Bild davon:
http://www.chaoszone.de/blog/media/blogs/webnews/starwars-at-st-walker.jpg

Klar das ich das so niemals hinbekommen werde ohne en haufen Geld und wirklich viel Geduld ^^
Aber eine stark vereinfachte Version bestimmt O:)

Meine Idee ist es das Bein einfach so beweglich wie möglich zu machen indem ich ein haufen Servos benutze wobei die aktuellen 10 ausreichen sollten.
Zur stabilisierung benutze ich ein kleines Gewicht das den Oberkörper simulieren soll.
Im endeffekt soll es dann so funktionieren als ob man beim laufen das Gleichgewicht nur mit dem Oberkörper halten würde.

Wenn der Robi einfach nur da steht befindet sich das gewicht in der mitte.
Bevor der robbi ein Bein anhebt bewegt sich das Gewicht auf das noch stehende Bein.
Das Gewicht muss halt so schwer sein das der Roboter auf ein Bein stehen kann ohne umzufallen.
Wenn er los läuft bewegt sich das Gewicht in Richtung des anderen Beines
und dann halt hin und her ....


Umsetzung:
1. Ich habe einen kleinen Schrittmotor und ein Zahnriehmen mitdem ich das Gewicht hin und her bewegen könnte.
2. Die 2. Idee besteht aus 2 zusätzlichen servo motoren die sich bewegen können wie ein Moving Head allerdings ist daran keine Lampe sonder eiene Stange mit Bleigewicht, die je nach Kipprichtung das Gleichgewicht halten soll. Man könnte sagen sie schwingt hin und her.


Ich habe einiges über Laufroboter hier gelesen aber da war nur rellativ wenig über 2 Beiner drin. Es wäre also super wenn mir jemand tipps bzw erfahrungen sagen könnte in diesem Bereich.

mfg
Feratu

Manf
05.11.2007, 18:00
wenig über 2 Beiner drin. Es wäre also super wenn mir jemand tipps bzw erfahrungen sagen könnte in diesem Bereich.
Eine der elementarsten Formen eines zweibeinigen Laufroboters ist wohl der Yeti (oder Toddler) der auch im RN beschrieben ist.

https://www.roboternetz.de/phpBB2/viewtopic.php?t=20369

http://web.mit.edu/newsoffice/2005/robotoddler.html
Robotic Toddler
Control programs in the Cornell and Delft robots are extremely simple, because a large portion of the control problem is solved in the mechanical design. The MIT robot uses customized learning software that exploits this design, allowing the robot to teach itself to walk in less than 20 minutes, or about 600 steps.

Feratu
05.11.2007, 18:24
Hi Robocar
Ich habe mir das mal ähnlich zusammengebastelt allerdings klappt das nicht
Ich vertseh zwar den Grund nicht aber ok ^^

Ich hatte meine PWm auf 50Hz ausgelegt (die 20mS)
Darin enthalten die 1 - 2mS Impuls

Seltsamerweise lief das ding aber nicht.???
Vielleicht habe ich mich ja verrechnet und die Frequenz stimmte nicht.
Wie auch immer,...

Als ich die Frequenz auf knappe 2KHz hochschraube funktionierte das ding beinahe einwandfrei
nur bei einem Wert nah am rechtsausschlag fängt der Servo an zu vibrieren
Du weist nicht zufällig woran das liegt ?

Feratu
05.11.2007, 18:33
hi manf
Die kenn ich garnich sau lustig XD besonders der Toddler ^^

Ich will halt vermeiden das der Robi hin und her Wackelt
also er soll rellativ gerade laufen und nicht so schwanken als wäre er besoffen ^^

robocat
05.11.2007, 18:38
ich würde die servos mit 50Hz ansteuern. dafür sind sie gedacht, und selbst wenn sie bei exotischen frequenzen funktionieren sollten, tun das wahrscheinlich 1. nicht alle und 2. geht dann noch mehr rechenzeit für die dinger drauf.

bist du sicher, dass dein µC mit 16MHz läuft und nicht etwa noch mit 1MHz? einfach mal ne led blinken lassen testweise.

ca. 100Hz erhältst du bei 16MHz mit prescaler 1024, wenn du den timer im overflow-interrupt auf 100 setzt (im normal timer mode).

gruesse

Feratu
05.11.2007, 18:54
Hab nochmal nachgeschaut und 16MHz sind angegeben
Mein Programm steht unter dem Link
https://www.roboternetz.de/phpBB2/viewtopic.php?t=35211
Der untere Post ist der aktuelle.

Also ich schreibe mal meine rechnung hin und du schaust ob ihc kein Fehler gemacht habe ;P
Das sind meine Timer einstellungen:

Config Timer0 = Timer , Prescale = 1
Enable Timer0
On Timer0 Isr_von_timer1
Enable Interrupts
Load Timer0 240

Die Rechnung dazu:
Timer0 = 8Bit Timer = 256
Timer Frequenz:
(16000000Hz / 1 = 16MHz)

Gewollt 1 MHz
16000000 / 1000000 = 16

Einzustellender Load:
256 - 16 = 240

Eingestellter Zählwert der Variable A (zählende Variable)
480 (Testweise ermittelt)
Fpwm = 480 * (1/1000000) = 4.8x10^-4
= 1/4.8x10^-4
= 2083,3333... Hz

Damit gehts
werde aber deinen Vorschlag gleich ausprobieren

Manf
05.11.2007, 19:15
Ich will halt vermeiden das der Robi hin und her Wackelt
Nur noch als Ergänzung, hier gibt es eine sehr schöne Zweibeiner-Laufstudie mit QRIO, die (besonders bei 00:35 - 00:43) zeigt, wie bei geringer Schrittfrequenz das Gewicht verlagert wird durch Schwanken oder hier eleganter durch seitliches Verschieben des Körpers über den Standfuß.
Bei hoher Schrittfrequnz bleibt der Körper auch ohne Gewichtsverlagerung im Mittel stabil.
Manfred

http://www.youtube.com/watch?v=oEfJC32BuQQ

Feratu
05.11.2007, 19:20
Also wäre es am sinnvollsten die schritgeschwindigkeit soweit gochzuschrauben das er sich selbst stabilisiert

Manf
05.11.2007, 20:21
Vielleicht, es kommt auf die Zielsetzung an.
In der Umgebung gibt es auf alle Fälle noch ein paar Anregungen O:) :
http://www.youtube.com/watch?v=ZlOBmUb__VM
http://www.youtube.com/watch?v=vcH97Dx8VCk
http://www.youtube.com/watch?v=eoUoyBCB1Kg&NR=1

Feratu
05.11.2007, 20:29
XD sieht ja witzig aus XD
Ma sehn was sich draus machen läst
DU kennst aber nich zufällig ein Chip der PWM besser kann als der MIcro Controller ?
Ein weiteres Problem ist mir gerade aufgefallen
Der verzettelt sich manchmal und weis dnn nich mehr wo er war
also bleibt das Bein stehn und es passiert garnix mehr

mfg Feratu

Manf
05.11.2007, 20:49
Wenn es um die Steuerung von Servos geht, dann gibt es auch einen Servo Controler. Es ist aber auch nur ein entsprechender Controler mit Spezialaufgabe.
http://www.google.de/search?hl=de&q=servo+controller&meta=

Ich wollte in der Diskussion nicht abschweifen, es ist aber nach den angesprochenen Themen ein weites Feld. Schlimmstenfalls kann man ja später noch einen Thread zu den speziellen Themen der Bewegungen aufmachen, das entwickelt sich dann...
Manfred

Feratu
05.11.2007, 22:25
Na der SD20 Controller hört sich dochmal sehr gut an ;P
danke dir ;P
NUr die Frage ist
1. Kann ich den mit meinem Chip verbinden ? (I²C Bus sollte der eigentlich haben)
2. Ich habe den MAX 232 an meinem Chip hängen um damit Texte zum PC zu senden. Aber der Servo Controller benötigt die selben Pins.
Kann ich nun Beide an die Leitung hängen ohne das sie sich im Weg stehn ?

ps: In dem Thread geht es einfach um beides ^^

MeckPommER
06.11.2007, 10:41
Feratu, bist du sicher, das die Fuses in deinem µC nicht zufällig den Takt durch 8 teilen?

Servosteuerung mache ich übrigens per Software, die mit 10 Servos ganz ordentlich und flatterfrei funktioniert und nicht viel Rechenzeit erfordert.
Ich steuere die Servos nacheinander in einer Interrupt-Routine an.
Diese Routine schaltet in einem Rutsch den aktuellen Servo ab, schaltet den nächsten an und belegt einen Timer mit einem passenden Wert, sodaß dessen Überlauf nach 1-2ms diesen Servo abgeschaltet und den folgenden einschaltet usw.
Nach einem Durchgang aller Servos kommt eine Pause, die 20ms - (summe aller servozeiten) lang ist, wozu ich einen n+1. virtuellen Servo setze.

Gruß MeckPommER

Feratu
06.11.2007, 15:36
Also meine Fusebits sind genauso eingestellt wie hier beschrieben

https://www.roboternetz.de/wissen/index.php/Bild:Avrtutorial_bascomfusebitquarz.gif

Ich bin lediglich die Schritte durchgegangen und habe das Programm verändert.

Oder liegt das vielleicht an den Kondensatoren die am Quarz hängen
Bei einem 8MHz quarz sind es 22pF könnte ja sein das andere eingesetzt werden müssen.
Das is mir grade erst aufgefallen ^^

Könntest du mal einen Programm ausschnitt posten?


ps: ich programmier in Bascom unter Basic

phaidros
07.11.2007, 00:15
Also zu Basic kann ich nichts sagen. Ich denke, die Servosteuerung sollte in Assembler geschrieben werden.
Ich mache das bei einem PIC wie folgt:

In der Totzeit (18 ms, wo keine Servos aktiv sind) werden die Abschaltzeiten der einzelnen Servos berechnet, (Z.B. Servo 1 nach 1,9 ms, Servo 2 nach 1.2 ms, Servo 3 nach 1.8 ms, Servo 4 nach 1.8 ms).

Diese Werte werden jetzt nach aufsteigender Zeit sortiert:
(1.2 - Servo 2), (1.8 - Servo 3 und Servo 4), (1.9 Servo 1)

Jetzt berechne ich nur die Differenzen bis zum Ausschalten des jeweils nächsten Servos (Startwert ist 0.0 ms):
(S2 - 1.2) , (S3 & S4 - 06), (S1 - 0.1)

Diese Werte schreibe ich in eine zweispaltige Tabelle. 1. Wert ist ein Bitmap aller auszuschaltenden Servos. 2. Wert ist die Zeit bis zum Ausschalten der nächsten Servos.
0x00 | 1.2 ; Start, noch keine Servos ausschalten, 1.2 ms warten
0x02 | 0.6 ; S2 ausschalten, 0.6 ms warten
0x0c | 0.1 : S3 und S4 abschalten (Bits 3 und 4), 0.1 ms warten
0x01 | 0.0 : S1 abschalten und fertig

Die Interrupt-Routine kriegt einen Pointer auf die erste Zeile der Tabelle als Parameter.
Meine Timer-Interrupt-Routine macht jetzt folgendes (nachdem sie einmal zum Zeitpunkt 0ms angestoßen wurde);
XOR Spalte 1 der Tabelle mit den Ausgabe-Ports der Servos.
Setze nächsten Timer-Interupt auf den Wert der Spalte 2 der Tabelle.
Erhöhe Zeilen-Pointer in die Tabelle um 1.

Vorteile:
- Die Interrupt-Routine ist extrem schnell.
- Es können mehrere Servos gleichzeitig ausgeschaltet werden, da immer 8 Bit am Port gleichzeitig gekippt werden können.
- Die Anzahl der Servos ist hauptsächlich durch die Anzahl der Ports beschränkt.

Nachteile:
Etwas RAM-Verbrauch durch die angelegte Tabelle.

Ist softwaretechnisch ein ziemlicher Aufwand, das Ganze elegant und effizient hinzubekommen, funktioniert aber tadellos.

Feratu
07.11.2007, 12:13
Also das Prinzip habe ich soweit verstanden und muss sagen gute idee ^^
Aber wie bekomst du die genaue Zeit hin ?
ich glaube mit W
Waitms 1.2
is das nicht getan ^^
Oder hast du noch einene 2. Timer laufen der dir das berechnet ?

Ich dachte mir vll wäre es ja möglich eine timer zu machen der alle 20ms ein interupt auslöst.
Gleichzeitig läuft ein wesentlich schnellerer Timer der einfach nur drin hat
also
Dim a as word
Interup_timer2_
load timer2 xxx
a = a + 1
return

Der andere Timer hingegen hat
interupt_timer_der 20ms_hat:
load ....
porta.0 = 1
..
..
porta.7 = 1
a = 0
do
If a >= 100 then porta.0 = 0
...
...
If a >= 180 then porta.7 = 0

loop until a = 500 'das sollen dann halt 2ms sein
Return

In der Hauptschleife steht halt drin was für ein Wert der jeweilige servo hat

Ich probier das ma aus ;P

Feratu
07.11.2007, 13:01
Schade geht nich XD
wer häts gedacht ^^

MeckPommER
07.11.2007, 13:13
Also meine Fusebits sind genauso eingestellt wie hier beschrieben

Auf betreffendem Bild ist aber nicht zu sehen, das einige Atmegas noch eine Fuse "Clock Division by 8" haben, oder so ähnlich. Bei einigen Atmegas ist das aktiviert, was einen 8MHz Atmega nurnoch mit 1MHz betreibt und einem alle zeitrelevanten Dinge durcheinanderwurschtelt.

Die 22pF am Quartz sind immer ok, egal ob 1MHz oder 16MHz.

Gruß MeckPommER

Feratu
08.11.2007, 13:44
So hier sind ma die Fusebits des Chips

http://img65.imageshack.us/img65/6682/fusebitsqa0.png (http://imageshack.us)

Ich denke ma da is kein fehler drin.
Aber wenn jemand einene findet wäre ich sehr glücklich drüber ^^
Das würde zumindest einiges erklären ;P

wegen der Kondensatoren:
Wunderbar muss ich das ding doch net umlöten ^^

Kann es eigentlich sein das die Schnittstelle R232nur richtig mit 8MHz funktioniert ?
Weil abundzu funktioniert die nicht richtig `?

MeckPommER
08.11.2007, 14:27
Ich habe momentan leider keinen 8535 vor der Nase, sonst würde ich mal nachschauen, was sich unter der Fusebit P noch für Optionen verbergen. Wenn der Punkt "Oszillator-Optionen" bedeuten soll, dann klingt das schonmal vielversprechend. Würde mich nicht wundern, wenn "programmed" die Taktdivision / 8 bedeutet.
Mit den von dir errechneten Refresh-Raten würde kein auf Erden gebauter Servo funktionieren, also irgendwo muss der Wurm ja sein :)

Feratu
08.11.2007, 15:11
Oo
Tatsache der rechnet wirklich nur mit 1Mhz
Ich habe meine rechnugn einfach mal mit 1MHz gemacht anstatt 16 und tada
der Servo läuft wesentlich besser Oo
Also irgendwo muss wohl ein fehler sein
Ich kenn ihn nur nicht -_-
need Help ](*,)

Feratu
09.11.2007, 00:39
Ook ich versuch das mal mit der wait methode
Dazu muss ich ja die eingänge vom niedrigsten zum höchsten sortieren lassen
Jetzt hab ich nur das problem das ich den MA/Min befehl nciht ganz verstehe

In der Bascom Hilfe steht zwar drin das man auch den Index des kleinsten Arrays angeben kann aber nicht wie.

Weis einer wie das geht ?
wäre super ^^

Feratu
10.11.2007, 13:18
So ich hab mal etwas mit den Fusebits rumprobiert
Um ehrlich zu sein ich hab keine ahnung wo der fehler liegt.
Das "osc options programmed" habe ich gewechselt da passiert nix
Zum testen habe ich eine einfach loop und ein Print befehl mit Wait 1 versehen.
Der logik nach sollte jede sekunde dann der der Text angezeigt werden.
Aber er kommt nur alle 2 Sekunden.
Wobei es an dem Terminal nicht liegen kann das ews schnell genug ist.
Mit wait 3 kommt der Text nur alle 7 Sekunden.
---> Also kann da was vorne und hinten nich stimmen.

Schließlich habe ich versucht den Chip wieder auf den internen OSC umzuschalten aber das will der irgentwie nicht mehr ???
-- >Könnte es daran liegen das der Externe noch anliegt ?
Obwohl es in den Fusebits abgeschaltet ist ??

Könnte das an meinem Programmer liegen ?
Ich benutze das "MCS Universal Programmer Interface"

Ich hatte es schonmal mit diesen einstellungen hier versucht aber das geht nicht.
https://www.roboternetz.de/wissen/index.php/Bascom_-_Erstes_Programm_in_den_AVR_Controller_%C3%BCbertr agen


???

Feratu
15.11.2007, 22:57
XD Fehler gefunden
Der Microcontroller war futsch -_- weil der Spannungsregler nicht mehr so funktionierte wie ich es wollte XD
Außerdem war ein Fusebit falsch gesetzt. Was ich aber eben erst herausgefunden habe.

Ich habe mir jezt ein neuen uC besorgt und getestet ob er mit 16mhz rechnet
Wieder mit der Led die mit einer Sec. blinkt.
Zusätzlich wird jede sekunde ein Text auf das Hyper Terminal gesendet.
Die sekunde stimmt ziemlich genau wobei ich dem Wait 1 befehl eh nicht ganz vertraue.

Die PWM funktioniert auch ganz gut wobei ich nocheinmal mit einem Oszi nachmessen werde, da der Servo nicht ganz so schnell verfährt wie er es sollte.
Errechnet sind 50Hz bin mal gespannt was es wirklich ist ^^.

Nur dei dem Min/Max Befehl habe ich immernoch nicht herausgefunden wie ich den Index ausgeben kann
Kennt sich da jemand aus ?