PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Servo an ADC0 gesteuert von Timer0



Mc Delta
02.10.2010, 12:15
Hallo,
Ich möchte, dass mein RP6 einen Servo steuert. Den Servo habe ich an ADC0 angeschlossen und dieses Programm ausprobiert:


#include "RP6RobotBaseLib.h"

int main(void)
{
initRobotBase();
DDRA |= 1; // ADC0 auf Ausgang
while(1) // immer weiter Impuls für rechts geben
{
PORTA |= 1;
sleep(10);
PORTA &= ~1;
sleep(200-10);

}


return(0);
}
Das funktioniert auch gut aber jetzt wollte ich nicht mehr die RP6lib verwenden sondern selbst die sleep-Funktion schreiben. Das sieht dann so aus:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>

uint8_t timer=0;

void timer_init(void) // Timer einstellen
{

TCCR0 = (0 << WGM00) | (1 << WGM01)
| (0 << COM00) | (0 << COM01)
| (0 << CS02) | (1 << CS01) | (0 << CS00);
OCR0 = 99;

}

ISR(TIMER0_COMP_vect)
{
timer++;
}



void sleep(uint8_t time)
{
for (timer = 0; timer < time;);
}



int main(void)
{
DDRA |= 1;
timer_init();

while(1) // Servomitte
{
PORTA |= 1; // Ausgang auf high
sleep(15); // schlafe 1,5ms
PORTA &= ~1; // Ausgang auf low
sleep(200-15); // 20ms-1,5ms warten bis nächster Impuls gesendet wird
}
return(0);
}

Aber leider klappt das nicht. Der Servo dreht sich garnicht.
Kann mir jemand sagen was ich falsch gemacht habe? Bei der Initialisierung des Timers bin ich mir nicht sicher ob das richtig ist, weil ich die aus der RP6Lib habe aber selber nicht so ganz verstehe was die Befehle bedeuten.

radbruch
02.10.2010, 14:32
Hallo

Ich bin grad zu faul um dein Timersetup nachzuprüfen. Es lohnt sich allerdings auch nicht wirklich in diese stümperhafte Sleep()-Ansteuerung unnötig Zeit zu investieren. Viel besser ist eine Ansteuerung direkt in der ISR. http://www.rn-wissen.de/index.php/Servo zeigt das Prinzip mit einem Servo. Die ISR wird mit 100000kHz aufgerufen und daraus werden die Impulslängen berechnet. Ich verwende das dann auch gleichzeitig als Zeitgeber für eine Pause()-Funktion:


uint8_t p=0;

void Pause(uint8_t wert) // Pause in 1/50 Sek
{
p=wert;
while(p);
}

und am Ende der ISR:

if(count<2000-servopos)count++;
else {count=0; if(p) p--;}


Gruß

mic

[Edit]
Drei Servos an SDA, SCL und E_INT mit Timer0 ohne RP6-Library:

https://www.roboternetz.de/phpBB2/viewtopic.php?p=322293#322293

Mc Delta
03.10.2010, 11:32
Danke für die Tipps,
Ich habe das Problem jetzt so gelöst:


#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "lib.h"


unsigned char x, count;


ISR (TIMER0_COMP_vect)
{
if (count>x) PORTA &= ~1; else PORTA |= 1;
if (count < 200) count++; else count=0;
}

void long_delay(uint16_t ms)
{
for(; ms>0; ms--) _delay_ms(1);
}

void demo(uint8_t a) // Demo: ein Durchgang besteht aus linker Anschlag bis rechter Anschlag
{ // Anzahl der Durchgänge kan festgelegt werden
uint8_t q;
uint8_t i=14;
for(q=0; q<a; q++)
{
for(i=14; i<67; i++)
{

long_delay(1000);

x=i;
}
for(i=67; i>14; i--)
{

long_delay(1000);

x=i;
}
}
}
int main(void)
{
delta_init();
timer0_init();
usart_init();
DDRA |= 1;
demo(5); // Demo 5-Mal Ausführen

while(1)
{
if(usart_byte_avail()) // Dann auf Befehle über UART warten
{ // links:67 , mitte:39 , rechts:14
x = readInteger();

}
}
return(0);

}

Jetzt funktioniert alles, wie es soll.