Hallo,
ich habe hier eine Include-Datei für das universelle steuern von Servos geschrieben. Die Lib ermöglicht das Steuern von einer beliebigen Anzahl von Servos an verschiedenen Ports. Jedoch sinkt die Geschwindigkeit der Positionsänderung mit steigender Servoanzah. An Resourcen verbraucht die Lib neben 16 Bit pro Servo im Ram und 8 im Heap einen 8-Bit Timer im CTC-Mode. Die Die verwendung der Lib, bzw die initalisierung sieht wie folgt aus am Beispiel eines ATmega32 mit Timer0
Code:
#define VEKTOR TIMER0_COMP_vect // Der Interruptvektor für die ISR von Timer0 im CTC-Modus
#define VERGLEICHSREGISTER OCR0 // Das Register, in das der Wert geschrieben wird, wann eine ISR aus gelöst werden soll
#define NUMBER_OF_SERVOS 3 // Die Anzahl der verwendeten Servos.
//In main() oder in einer anderen Funktion muss dann das Array Servolist zuerst initalisiert werden und dann mit Werten bestückt werden.
//Die Initalisierung erfolgt über die Funktion init_ServoArray() danach werden die Belegungen der einzelnen Servos wie folgt eingetragen:
servolist [0].pin = PORTxy ; //Servo1, der an PORTx an Pin y angeschlossen ist
servolist [0].port =& PORTx; // Da für den Zugriff auf die PORTs Zeiger verwendet werden, muss hier umbedingt der Adressoperator verwendet werden
//In die nächte Variable wird der Drehwinkel geschrieben, dabei bedeutet der Wert 0 Mittelposition, -127 linker Anschlag und 127 rechter Anschlag. Die Variable ist //vom Typ int8_t
servolist[0].angle = 0;
Die Lib geht davon aus, das die maximale Pulslänge 2ms beträgt, die minimale 1ms. Aus diesem Grund muss der verwendete Timer so eingestellt sein, das der längst mögliche Durchlauf möglichst genau 1ms beträgt.
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
/*
Wichtig für die korrekte Funktionsweise der Lib ist das richte Einstellen des Taktes vom 8-Bit Timer auf 1KHz Wichtig dabei CTC-Mode
logischerweise müssen die entsprechenden Ports in das Array Servolist eingetragen werden
Dazu muss in der Funktion init_ServoArray() nach initialisierung der Servos, dieses mit Pins,Port und evtl Winkeln gefüllt werden
Diese drei Konstanten müssen vor dem Einbinden der include definiert werden:
#define VEKTOR -> Der passenden Interruptvektor aus dem Datenblatt. BSP TIMER0_COMP_vect
#define NUMBER_OF_SERVOS
#define VERGLEICHSREGISTER BSP: ORC0
*/
typedef struct
{
uint8_t PIN;
volatile uint8_t *PORT;
int8_t angle;
} servo;
volatile struct
{
unsigned modus :1 ;
unsigned index: 7;
} Servo;
volatile servo servolist[NUMBER_OF_SERVOS];
ISR (VEKTOR)
{
VERGLEICHSREGISTER = 255;
if (Servo.modus)
{
*(servolist[Servo.index].PORT) &= ~(1 << servolist[Servo.index].PIN ); //Alten Servo löschen
if (++Servo.index >=NUMBER_OF_SERVOS) //Wenn inkrementierter Index größer als Servoanzahl, reset
{
Servo.index= 0;
}
*(servolist[Servo.index].PORT) |= (1 << servolist[Servo.index].PIN ); //Neuen Servo setzen und...
VERGLEICHSREGISTER = 255; //...1ms warten
Servo.modus =0; //Servo als aus makieren
}
else
{
VERGLEICHSREGISTER = 127+servolist[Servo.index].angle; //Drehwinkel, "Restzeit" warten , Wertebereich [-127...127]
Servo.modus = 1; //Servo als ein makieren
}
}
void init_ServoArray() //lädt in alle Stellen des Arrays eine Null
{
servo empty;
empty.PIN = 0;
empty.PORT = 0;
empty.angle = 0;
for(uint8_t i = 0; i >= NUMBER_OF_SERVOS;i++)
{
servolist[i] = empty;
}
}
Getestet worden ist die Lib bis jetzt nur mit den Conrad Topline Servos mit einem ATmega32. Es würde mich freuen, wenn ihr die Lib auch an anderen Servos testen würdet.
Gruß Jannis
Lesezeichen