Hardware ist ein 5€-Miniservo von Conrad, aufgeklebt auf den RP6 mit einem Power-Strip. Aus dem Stecker(JBL) habe ich den Taktpin (orange) ausgebaut. Nun kann ich den Servo-Stecker mit +(rot) und -(braun) in den XBUS-stecken (Pin1=GND, Pin3=5V-Vcc) und das Signal z.b. in Pin8 (INT1) oder Pin10 (SCL).
Für die Ansteuerung zapfe ich den 72kHz-Interrupt an, der Timerinterrupt hat mit nur 10 kHz eine zu geringe Auflösung (=weniger mögliche Servopositionen). Das ergibt zwar "krumme" Werte für die Positionen, funktioniert aber wunderbar:
Code:
#include "RP6RobotBaseLib.h"
#define servo_min 26
#define servo_mitte 85
#define servo_max 155
volatile unsigned char servo_winkel;
uint8_t servo_pos=servo_mitte;
void servo(uint8_t winkel)
{
uint16_t servo_stellzeit;
if (servo_winkel != winkel)
{
TIMSK |= (1 << OCIE2);
servo_stellzeit=200*abs(servo_winkel-winkel);
servo_winkel=winkel;
while (servo_stellzeit--);
TIMSK &= ~(1 << OCIE2);
}
}
int main(void) {
uint8_t i;
initRobotBase();
DDRC |= 1; // SCL auf Ausgang stellen
while (1)
{
servo(servo_mitte);
mSleep(500);
servo(servo_min);
mSleep(200);
for (i=servo_max; i>servo_min; i-=2)
{
servo(i);
setLEDs(16);
}
for (i=servo_min; i<servo_max; i+=2)
{
servo(i);
setLEDs(32);
}
}
while(1);
return 0;
}
/*
ISR (TIMER2_COMP_vect)
{
#define Servo on
#ifdef Servo
extern unsigned char servo_winkel;
static unsigned int servo_zyklus=0;
if (servo_winkel)
{
if (servo_zyklus>servo_winkel) extIntOFF(); else extIntON();
//if (servo_zyklus>servo_winkel) PORTC &= ~1; else PORTC |= 1;
if (servo_zyklus<1440) servo_zyklus++; else servo_zyklus=0;
}
//else
if (0)
{
#endif
...
#ifdef Servo
}
#endif
}
/**
*/
Der einfache Democode definiert die Lageendpunkte und die Mitte, und steuert das Servo endlos auf diese Punkte. In der Funktion servo() wird die Stellzeit berechnet und der Winkel in servo_winkel eingetragen. Dann wird der Interrupt freigegeben und die Erweiterung des Interrupts steuert dann das Servo automatisch. Nach Ablauf der Stellzeit wird der Interrupt wieder gesperrt.
Lesezeichen