PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 2 Servos mit PWM ansteuern



privatestatic
14.10.2006, 15:42
Hallo Leute,

ich möchte 2 Servos mittels PWM im "Phase and Frequency Correct"-Modus ansteuern. Mit dem untenstehenden Programm funktioniert allerdings immer nur jeweils ein Servo. Wenn ich beide gleichzeitig aktiviere dann zuckeln sie nur sinnlos herum. Wie kann ich beide Servos gleichzeitig zum Laufen bringen?

MfG
Nico



#ifndef F_CPU
#define F_CPU 16000000
#endif

#include <avr/io.h>
#include <util/delay.h>

// Servoansteuerung
#define U_LIMIT 2000
#define L_LIMIT 1000
#define TOP 20000

#define SPEED(x) (L_LIMIT + ((( U_LIMIT - L_LIMIT ) / 255.0 )*x))
#define SETBIT(x,n) ((x)|=1L<<(n))
#define WAITMS(x) _delay_loop_2(((F_CPU * 0.001) / 4)*x) /**< 1 ms delay */

void init(void)
{

ICR1 = TOP; // ICR1 as TOP

SETBIT(DDRD,PIND4); // Port PD4 (OC1B) als Ausgang
SETBIT(DDRD,PIND5); // Port PD5 (OC1A) als Ausgang

SETBIT(TCCR1A,COM1A1); // OCR1A on
SETBIT(TCCR1A,COM1B1); // OCR1B on
SETBIT(TCCR1B,CS11); // Prescaler 8
SETBIT(TCCR1B,WGM13); // Phase and Frequency Correct PWM

//OCR1A = L_LIMIT + ((U_LIMIT-L_LIMIT)/2); // <-- Problem
OCR1B = L_LIMIT + ((U_LIMIT-L_LIMIT)/2);
}

int main(void)
{
unsigned char c;

init();

while(1)
{
for(c=0;c<=255;c++)
{
//OCR1A = SPEED(c); // <-- Problem
OCR1B = SPEED(c);
WAITMS(10);
}
}
}

Hubert.G
15.10.2006, 08:22
Ich kann deinen Code so auf die Schnelle nicht nachvollziehen aber mich stören in zeitkritischen Anwendungen Warteschleifen unheimlich. Ich habe mir mit diesen Schleifen schon die unmöglichsten Fehler eingehandelt die nur sehr schwer nachzuvollziehen sind. Vieleicht überdenkst du mal das.

privatestatic
15.10.2006, 14:13
Hallo,

danke für die Antwort. An dem WAITMS(10) liegt es leider nicht. Auch wenn ich das WAITMS weglasse und einmalig beide Servos in feste Positionen bringen möchte funktioniert dies nicht.

Ich habe das Programm nochmals etwas modifiziert und diesmal FastPWM genutzt. An dem Problem hat sich jedoch nichts verändert. Es läuft immer nur ein Servo. Der andere muss kommentiert bleiben.


#ifndef F_CPU
#define F_CPU 16000000
#endif

#include <avr/io.h>
#include <util/delay.h>

// Werte für OCR1A/OCR1B
#define U_LIMIT 4000 // oberes Limit
#define L_LIMIT 2000 // unteres Limit

// Obergrenze Zähler
#define TOP 40000

// Makro für Normierung auf Werte zwischen 0 und 255
#define SPEED(x) (L_LIMIT + ((( U_LIMIT - L_LIMIT ) / 255.0 )*x))
#define WAITMS(x) _delay_loop_2(((F_CPU * 0.001) / 4)*x)

void init(void)
{
ICR1 = TOP; // ICR1 as TOP

DDRD |= (1 << PIND4); // Port PD4 (OC1B) als Ausgang
DDRD |= (1 << PIND5); // Port PD5 (OC1A) als Ausgang

// Aktiviere OCR1A und OCR1B und setze Waveform Generation Mode 14
TCCR1A = 0x00 | (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); // OCR1A und OCR1B an
TCCR1B = 0x00 | (1 << CS11) | (1 << WGM12) | (1 << WGM13); // Prescaler 8, 16 Bit Fast PWM, TOP ist ICR1

// Servos in Mittelstellung
OCR1A = SPEED(127);
//OCR1B = SPEED(127); // <- Problem
}

int main(void)
{
unsigned char c;
init();
while(1) // Hauptschleife
{
for(c=0;c<=255;c++) // Servos von Minimalstellung zu Maximalstellung fahren
{
// setze Servopositionen
OCR1A = SPEED(c);
//OCR1B = SPEED(c); // <- Problem

// Zeit schinden
WAITMS(10);
}
}
}


MfG
Nico

SprinterSB
16.10.2006, 08:50
Bist du sicher, daß deine Schaltung ok ist? Wenn zB zwei Servos zusammen zu viel Strom saugen und der µC resettet oder spinnt, dann kannst du so nen Effekt bekommen. Geht es, wenn zu die 2 Servos simultan an einem PWM-Kanal betreibst? Also die Soaftware genauso lässt wie sie mit einem Servo geht, aber nur die 2 Dinger an einen Pin anklemmen.

privatestatic
16.10.2006, 12:43
Arghh,

stimmt, das Problem lag in der Schaltung. Die beiden Programme funktionieren wunderbar! Mein fehler war, dass ich Servos und Atmel mit verschiedenen Stromquellen verbunden hatte und vergessen habe die Massen untereinander zu verbinden.

Grüße,
Nico