Hallo

Der Drehwinkel eines Servos ist von der Impulslänge des Ansteuersignals abhängig. Der Bereich geht von ca. 0,5ms (ms=Millisekunde) bis 1,5ms (je nach Servo und Doku auch1-2ms) für ca. 180 Grad. Der Impuls sollte ca. alle 20ms wiederholt werden (nicht nach 20ms!).

Das Problem ist nun die Zeitmessung für solche doch recht kurze Impulse. Neben Zählschleifen (dazu komme ich später noch) bietet sich hierfür ein Sleep() an. Die kürzeste Zeit dabei ist abhängig von der Version der Library. Bei der orginalen CD-Lib dauert ein Sleep(1) 1/72000Sek, bei den erweiterten Libs 1/36000Sek. Eine Millisekunde (=Servomitte) dauert dann Sleep(72) bzw. Sleep(36). Die Werte für 1/2ms sind jeweils die Hälfte, für 1,5ms entsprechend 150% ;)

Für 20ms der Pause wären es Sleep(20*36) (oder 72, das erspare ich mir jetzt aber, im Folgenden nur noch Daten für neue Libs) oder Sleep(720). Das ist mehr als in ein Byte geht, deshalb verteilen wir das auf mehrere Aufrufe: Sleep(255); Sleep(255); Sleep(210); Weil wir den Impuls ja alle 20ms wiederholen wollen, müssen wir noch die schon verstrichene Zeit für die Impulslänge abziehen. Ein kompletter Impuls mit folgender Pause würde dann so aussehen:

BackLED (ON,ON);
Sleep(winkel); // Winkel ca. 18-54
BackLED (OFF,OFF);
Sleep(255);
Sleep(255);
Sleep(210-winkel);

Da das Servo aber auch Zeit benötigt um die geforderte Position anzufahren, muss man den Impuls mehrmals senden. Wie lange das Servo genau braucht weiß man dabei allerdings nicht. Die Zeit für 50 gesendete Impulse beträgt genau 1 Sekunde (0,02s*50) Ein Programm das im Sekundenwechsel Impulse für zwei Servopositionen erzeugt könnte so aussehen:
Code:
#include "asuro.h"
int main (void)
{
   unsigned char c;
   Init();
   StatusLED(GREEN); // ist nach Init() immer grün!
   while(1)
	{
      StatusLED(RED);
		for (c = 0; c < 50; c++)
		{
			BackLED (ON,ON);
			Sleep(20); // Impuls Wert ca. 18-54
			BackLED (OFF,OFF);
			Sleep(255); // Pause
			Sleep(255);
			Sleep(210-20);
		}
      StatusLED(GREEN);
		for (c = 0; c < 50; c++)
		{
			BackLED (ON,ON);
			Sleep(50);
			BackLED (OFF,OFF);
			Sleep(255);
			Sleep(255);
			Sleep(210-50);
		}
   }
   return 0;
}
(nicht getestet)

Anstelle von Sleep(winkel); kann man auch eine Zählschleife verwenden. Dadurch wird die Auflösung des Servos besser. Meine Variante sieht meist so aus:

unsigned int i, dummy;

BackLED (ON,ON);
i=winkel; // irgendwas bei ca. 1000-5000?
while(i--) dummy^=i;
BackLED (OFF,OFF);

Gruß

mic

[Edit]
zwei Servos gleichzeitig:

BackLED (ON,OFF);
Sleep(20); // Impuls Servo1 Wert ca. 18-54
BackLED (OFF,ON);
Sleep(50); // Impuls Servo2
BackLED (OFF,OFF);
Sleep(255); // Pause
Sleep(255);
Sleep(210-20-50);
;)