Hallo zusammen, dieses Projekt entstand aus dem Spruch "Hey, wir haben noch Platz auf einem Nutzen, ca. in der Größe einer Zigarettenschachtel! Muss die Gerberdaten wohl morgen früh haben." Also schnell eine Platine für einen Hexabot zusammengetüddelt (Anhang) und weg damit. Seit das Teil aus dem Haus ist hab ich dann mal ein bisschen Mechanik gefräst. Auf den Fotos im Anhang kann man eine Lochrasterkarte mit einem mega8 sehen der nur mal schnell da war um das ganze Teil mal auf "eigene Beine" zu stellen (alle Pins für 18,ms low dann 1,5ms high... sagt jetzt nichts dazu...). Auf dem Bild sind alle Servos in Mittelstellung. So "schwebt" der Körper ca. 1,5 - 2cm über dem Boden. Hier mal ein paar Daten zusammengefasst: - Gewischt (Alu, 18 Servos, ca. 230 Schrauben mit Unterlegscheibe, Spannring, Mutter, Platine, Akkus): ca. 2kg - Pollin Funkkamera ;) - 2 LiIon Akkus aus einem Notebook Platine: - ATmega2560 (1280/640) - 16MHz - serielle Bluetoothverbindung - RFM12 - ISP - Uartanschluss - 8 LEDs frei programmierbar - Resettaster - 1 Taster frei programmierbar - 24 Ausgänge für Servos - I2C / TWI - Power LED - Spannungsregler für 3,3V Ich glaub das wars im Großen und Ganzen. Ich weiß, die Pins sind garantiert total grottig gewählt. Wie gesagt die Zeit war zu knapp ;) So jetzt mein Problem: WIE erzeuge ich auf einem ATmega (erstmal für den mega8, da die andere Platine erstmal ankommen muss und bestückt werden muss) 18 Software PWMs? Die Müssen ja nicht wirklich genau sein... Ein "paar" Schritte pro Gelenk die ich anfahren kann reichen ja. Habe hier irgendwo eine Routine gefunden mit der ich 8 Servos per Timer ansteuern kann aber das bringt mich nicht so richtig weiter. Vllt sollte man dazu sagen dass ich bei dem Atmega8 momentan mit dem internen 8MHz Quarz arbeite. Kennst jemand eine schnelle Möglichkeit um die Servos einzeln anzusteuern? Am liebsten wäre mir irgendeine Routine bei der ich einfach nur 18 verschiedene Variablen irgendeinen Wert geben muss der dann vom jeweiligen Servo angefahren wird. PS: Wenn jemand an den CAD Datenoder Gerberfiles interessiert ist einfach laut schreien. Die CAD Daten besitze ich im dxf und cam Format soviel ich weiß... muss ich auf meinem anderen Rechner nachgucken ;) Wäre super wenn mir jemand bei der Programmierung hilft :) Chriss
chriss schrieb: > So jetzt mein Problem: WIE erzeuge ich auf einem ATmega (erstmal für den > mega8, da die andere Platine erstmal ankommen muss und bestückt werden > muss) 18 Software PWMs? So: Modellbauservo Ansteuerung letzter Abschnitt Das Prinzip lässt sich problemlos auch auf 18 Servos erweitern.
Okay vielen Dank erstmal da werde ich mich dann morgen mal durchwühlen :)
Also die Ansteuerung hier aus dem Forum funktioniert schonmal ganz gut. Solang sich alle Servos in Mittelstellung befinden. Wenn ich eins der 18 Servos jetzt in Endposition fahren will dann fangen ein paar andere (nicht alle) wie wild an zu zucken... vllt könnt ihr mir ja helfen ;) Programm steck ich mal in den Anhang.
So
1 | ISR (TIMER2_COMP_vect) |
2 | {
|
3 | ....
|
4 | |
5 | //
|
6 | // den Puls des aktuellen Servos beenden
|
7 | //
|
8 | GELENK1_PORT &= ~ServoPuls[ServoId]; |
9 | GELENK2_PORT &= ~ServoPuls[ServoId]; |
10 | GELENK3_PORT &= ~ServoPuls[ServoId]; |
11 | |
12 | ....
|
13 | |
14 | //
|
15 | // die Ausgangsleitung fuer dieses Servo auf 1; den Puls beginnen
|
16 | //
|
17 | GELENK1_PORT |= ServoPuls[ServoId]; |
18 | GELENK2_PORT |= ServoPuls[ServoId]; |
19 | GELENK3_PORT |= ServoPuls[ServoId]; |
20 | |
21 | ....
|
geht das nicht. Du musst die 18 Servos hintereinander ansteuern, nicht in 3 Gruppen parallel. Schliesslich läuft der Timer ja immer nur für die Zeit des jeweils nächsten Servos.
1 | ISR (TIMER2_COMP_vect) |
2 | {
|
3 | ...
|
4 | |
5 | //
|
6 | // den Puls des aktuellen Servos beenden
|
7 | //
|
8 | if (ServoId < 6) |
9 | GELENK1_PORT &= ~ServoPuls[ServoId]; |
10 | else if (ServoId < 12) |
11 | GELENK2_PORT &= ~ServoPuls[ServoId]; |
12 | else
|
13 | GELENK3_PORT &= ~ServoPuls[ServoId]; |
14 | |
15 | ....
|
16 | //
|
17 | // die Ausgangsleitung fuer dieses Servo auf 1; den Puls beginnen
|
18 | //
|
19 | if (ServoId < 6) |
20 | GELENK1_PORT |= ServoPuls[ServoId]; |
21 | else if (ServoId < 12) |
22 | GELENK2_PORT |= ServoPuls[ServoId]; |
23 | else
|
24 | GELENK3_PORT |= ServoPuls[ServoId]; |
25 | |
26 | ....
|
uh doofer Fehler danke dunktiniert :) dann lassen wir das Teil mal laufen...
Ich werde aus diesem Teil hier noch nicht ganz schlau:
1 | ServoValue[0] += 2; |
2 | if( ServoValue[0] > 2*CENTER ) |
3 | ServoValue[0] -= 2*CENTER; |
Hier soll ein Servo mit einer bestimmten Geschwindigkeit angesteuert werden. Aber wie wird das gemacht? Ich werde aus dem Code noch nicht so ganz schlau... Und wie kann ich das Servo jetzt in eine bestimmte Position außer Links/Mitte/Rechts fahren? Chriss
chriss schrieb: > Ich werde aus diesem Teil hier noch nicht ganz schlau: >
1 | > ServoValue[0] += 2; |
2 | > if( ServoValue[0] > 2*CENTER ) |
3 | > ServoValue[0] -= 2*CENTER; |
4 | >
|
> Hier soll ein Servo mit einer bestimmten Geschwindigkeit angesteuert > werden. Aber wie wird das gemacht? Ich werde aus dem Code noch nicht so > ganz schlau... Der Code soll einfach nur IRGENDEINE Ansteuerung der Servos machen. Irgendeine, so dass die Servos unabhängig voneinander irgendetwas tun. Mehr steckt da nicht dahinter. Für dich ist dieser Code uninteressant, weil er nicht zur eigentlichen Servoansteuerung gehört, sondern demonstrieren soll, dass die Servoansteuerung funktioniert. Der Code stellt bei jedem Durchlauf das Servo ein kleines Stückchen weiter und wenn es am Ende angelangt ist, dann fährt es in einem Rutsch wieder an die Anfangsposition zurück. > Und wie kann ich das Servo jetzt in eine bestimmte Position außer > Links/Mitte/Rechts fahren? Indem du den einzelnen Variablen ServoValue[x] Werte zuweist. Fertig. Einfach nur einen Wert zuweisen und das Servo fährt an die entsprechende Position.
1 | ServoValue[0] = 0; // Servo 0 fährt ganz nach links |
2 | _delay_ms( 1000 ); |
3 | ServoValue[0] = 2*CENTER; // Servo 0 fährt ganz nach rechts |
4 | _delay_ms( 1000 ); |
5 | ServoValue[0] = CENTER; // und Servo 0 fährt wieder in die Mitte |
6 | _dleay_ms( 1000 ); |
7 | |
8 | ServoValue[1] = 0; |
9 | ServoValue[2] = 0; // jetzt fahren Servo 1 und 2 ganz nach links |
10 | _delay_ms( 1000 ); |
11 | ServoValue[1] = CENTER; |
12 | ServoValue[2] = CENTER; // und wieder zurück zur Mitte |
13 | |
14 | ....
|
Soo da bin ich nochmal... Ich habe es jetzt endlich mal geschafft meine Platine mit dem mega2560 zu bestücken. Erstmal eine LED blinken lassen -> Platine funktioniert. Jetzt habe ich das Servoprogramm in versucht in den µC zu laden. Bekomme aber schon beim Compilieren bekomme ich folgende Fehlermeldungen:
1 | Build started 11.4.2011 at 16:21:28 |
2 | avr-gcc -mmcu=atmega2560 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d -c ../main.c |
3 | ../main.c:39: warning: 'TIMER2_COMP_vect' appears to be a misspelled signal handler |
4 | ../main.c: In function 'TIMER2_COMP_vect': |
5 | ../main.c:62: error: 'OCR2' undeclared (first use in this function) |
6 | ../main.c:62: error: (Each undeclared identifier is reported only once |
7 | ../main.c:62: error: for each function it appears in.) |
8 | ../main.c: In function 'InitServo': |
9 | ../main.c:84: error: 'OCR2' undeclared (first use in this function) |
10 | ../main.c:85: error: 'TIMSK' undeclared (first use in this function) |
11 | ../main.c:85: error: 'OCIE2' undeclared (first use in this function) |
12 | ../main.c:86: error: 'TCCR2' undeclared (first use in this function) |
13 | make: *** [main.o] Error 1 |
14 | Build failed with 7 errors and 1 warnings... |
Kann mir jemand helfen? Hat ja scheinbar alles was mit dem Timer für die Servos zu tun... Danke schonmal chriss
Hi
>../main.c:85: error: 'TIMSK' undeclared (first use in this function)
Der ATMega2560 hat z.B. kein TIMSK-Register. Jeder Timer hat ein eigenes
TIMSK0, TIMSK1...
Nimm dir das Datenblatt und sieh nach wie deine Register richtig heißen.
MfG Spess
Vielen Dank :) Werde ich dann gleich mal ausprobieren wenn ich zuhause bin :) chriss
Wo die Register sind, steht im Datenblatt Wie die Register heißen, steht im Header-File
Mahlzeit, ich komme mit den Servos einfach nicht weiter. Ich weiß absolut nicht wie ich das mit dem Timer machen muss... Habe bis jetzt fast ausschließlich auf dem ATmega8 programmiert. Da gabs so viele Beisiele die man sich einfach zusammenbasteln konnte :) Jetzt bin ich mit dem mega2560 Datenblatt total überfordert. Kann mir mal jemand einen anschubs geben was ich alles ändern muss? Lade den Code aus dem Tutorial nochmal mit hoch. Danke chriss
Hallo Chriss, auch wenn es etwas hart klingt, aber programmieren besteht nicht daraus, aus dem Internet Codeschnipsel zusammenzukopieren und bei Problemen diese vom Forum lösen zu lassen. Du leidest am Guttenbergsyndrom. Hier wurde dir doch ein Haufen Ansätze gezeigt, jetzt bist du dran. Beginne mit einem Servo, wenn das zu viel ist fange mit einer LED an, aber nicht Code kopieren, sondern selber schreiben, ohne zu spicken. Trau dich, du kannst mehr als du denkst. Viel Erfolg, Udo
also ne LED bekomm ich schon hin das ist wohl kein problem ;) Der Roboter läuft auch schon (so halbwegs, stolpert mehr). Allerdings auf der Basis eines ATmega8. Das Problem was ich jetzt habe ist halt den Code auf einen mega2560 zu bekommen da blicke ich einfach nicht durch die ganzen Timer-Register durch...
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.