PDA

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

Kjion
22.03.2004, 17:32
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

Kjion
22.03.2004, 19:15
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

Kjion
23.03.2004, 20:46
/* 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

Frank
23.03.2004, 20:53
Hi Kjion,

was macht Dein 2313 Servo-Code? Gehts gut voran?

Gruß frank

Kjion
23.03.2004, 21:15
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

Kjion
24.03.2004, 12:39
@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