Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM-IC / parallel in oder SPI
trickTronic
22.03.2004, 08:41
Hallo!
Ich bin auf der Suche nach einem PWM-IC um Servos anzusteuern.
Ich würde den gerne parallel oder mit SPI über meinen Microcontroller beschreiben. Mein Controller hat nur 3 PWM-Ausgänge, ich brauche aber 8, deshalb ist eine andere Lösung nötig.
Danke,
Alex
Was benutzt du denn für einen Mikroprozessor ?? Bei den schnelleren ( zum Beispiel AVR ) kann man an jedem Pin ein Servo anschließen.
MfG Kjion
trickTronic
22.03.2004, 18:27
Ich hab den AtMega8, aber ich hab nur noch 2 Timer und 13 Pins frei.
Mit 2 Timern wird das ganze aber ein bisschen ungenau und viel Rechenaufwand, oder?
MFG Alex
Naja, welche Timer sind es denn ?? Wenn du noch den 16-Bit Timer frei hast, dann hast du ne Auflösung von über 20 000 Schritten ;) auch wenn Servos das nicht umsetzten können.
Also nix mit ungenau ! Viel Rechenaufwand ist das auch nicht. Ich kann dir eine fertige Routine dafür geben die ich auf meinem Laufroboter einsetzte ( ist in C geschrieben ). Sie läuft über Interrupt und ist nur relativ kurz, sodass die Rechenzeit zu vernachlässigen ist...
13 Pins -> 13 Servos ;) mit dem entsprechenden Programm kein Problem
MfG Kjion
trickTronic
23.03.2004, 08:14
Ja, den 16-Bit-Timer hab ich noch frei.
Kannst du mich mal in den code einsehen lassen? Danke,
Alex
/* Variablen für die Servoansteuerung */
volatile unsigned char
servo_zaehler;
volatile unsigned int
servo_werte[3];
/*
* Timer1 52736 -> 0.8 ms
* 41535 -> 1.5 ms
* 30336 -> 2.2 ms
*
* Auflösung : 52736 - 30336 = 22400 Schritte
*/
void servo_init(void)
{
/* Timer1 */
TCCR1A = 0x00; // normaler Timermodus ( kein PWM )
TCCR1B = 0x00; // Timer1 deaktivieren
TIMSK = (1<<TOIE1) | (1<<TOIE0); // Timerüberlaufinterrupts aktivieren
/* Timer0 */
TCCR0 = (1<<CS02) | (1<<CS00);
TCNT0 = 0x98;
}
/****************************[ Interruptroutinen ]******************************/
/* Interrupt wird bei einem Überlauf von Timer0 ausgelöst ( alle 6,656... ms )
Es werden nacheinander die drei Servos des Beins ausgewählt und angesteuert */
INTERRUPT(SIG_OVERFLOW0)
{
unsigned int temp;
servo_zaehler++;
if (servo_zaehler > 2)
servo_zaehler = 0;
switch(servo_zaehler) // Signal für die Servos auswählen
{
case 0:
PORTD |= (1<<PD5);
break;
case 1:
PORTD |= (1<<PD6);
break;
case 2:
PORTD |= (1<<PD7);
break;
default:
servo_zaehler = 0;
}
temp = servo_werte[servo_zaehler];
TCNT1 = temp;
TCCR1B = (1<<CS10); // Timer1 aktivieren, Prescaler = 1
TCNT0 = 0x98; // Timer0 neu laden
}
/* Interrupt wird bei einem Überlauf von Timer1 ausgelöst
Setzt das Signal für die Servoansteuerung wieder zurück */
INTERRUPT(SIG_OVERFLOW1)
{
PORTD &= ~((1<<PD5)|(1<<PD6)|(1<<PD7)); // Servosignal wieder löschen
TCCR1B = 0x00; // Timer1 deaktivieren
}
Du müsstest dann nur noch die entsprechenden Werte in das Array laden. Das Beispiel hier ist jetzt für 3 Servos, sollte sich aber auf mindestens 10 erweitern lassen ( Man müsste nur die ganzen anderen Servos in die "case" Anweisung einfügen und den Wert für TCNT0 anpassen, sag wieviele du brauchts, dann kann ich dir den entsprechenden Wert geben ). Es ist jetzt einfach aus meinem Quelltext zusammenkopiert ... ich hoffe man kann trotzdem erkennen worum es geht ;)
MfG Kjion
Hi Kjion,
was macht Dein 2313 Servo-Code? Gehts gut voran?
Gruß frank
Jaja, kommt ;)
I2C will noch nicht ganz, ansonsten ist er aber größenteils fertig...
trickTronic
24.03.2004, 08:22
Danke Kjion!
Ich werds heute abend mal analysieren...
Schöne Grüße
@trickTronic
Ich sehe du kannst die "temp" Variable aus der INTERRUPT(SIG_OVERFLOW0) - Routine rausschmeißen. Wird von mir in einem weiteren Teil der Routine benötigt, im dem Fall ist sie aber sinnlos...
also gleich:
TCNT1 = servo_werte[servo_zaehler];
MfG Kjion
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.