Irgendwie erinnert mich das an meine eigenen Schandtaten:
http://www.youtube.com/watch?v=F45RU9yRXtI
Bei dir sieht das aber deutlich besser aus.
Interesse besteht immer ;)
Irgendwie erinnert mich das an meine eigenen Schandtaten:
http://www.youtube.com/watch?v=F45RU9yRXtI
Bei dir sieht das aber deutlich besser aus.
Interesse besteht immer ;)
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Hier noch einmal den Code zum Linienfolgenprogramm:
Nun möchte ich meine Servofunktion so gestalten, das sie den PWM wie bei der MotorSpeed) Funktion funktioniert. Mit anderen Worten: Ich möchte der servo()Funktion einen Wert übergeben, der so lange ausgeführt wird, bis er geändert wird, damit der Servo einen Hebel gegen einen Federdruck halten kann.Code:#include "asuro.h" int main(void) { Init(); unsigned char l; int data[2]; FrontLED(ON); l=108; Sleep(255); Sleep(255); MotorDir(FWD,FWD); MotorSpeed(130,130); int servo(unsigned char l) { BackLED(ON,OFF); Sleep(l); BackLED(OFF,OFF); Sleep(144);Sleep(72);Sleep(144);Sleep(144);Sleep(144);Sleep(144);Sleep(144);Sleep(144);Sleep(144); return 0;} while(1) { LineData(data); if(data [0] < data[1]) {l=l+4; MotorSpeed(100,140);} else if(data[0] == data[1]) {l=l;} else {l=l-4; MotorSpeed(140,100);} servo(l); if(l > 120) {l=120;} else if(l < 80) {l=80;} else {l=l;} } return 0; }
Bisher ist das ja so, das der Servo zwar in der richtigen Stellung bleibt, wenn servo() nicht mehr while schleife andauernd ausgeführt wird, aber inaktiv ist und damit verdrahbar.
Lässt sich das mit dem Atmel umsetzen oder braucht man dafür multitaskting?
Hallo
Multitasking können die AVRs natürlich nicht. Für Aufgaben, die quasi im Hintergrund ablaufen sollen, verwendet man deshalb die Timerfunktionen der AVRs. Hier wird die "klassische" Servoansteuerung beschrieben:
http://www.rn-wissen.de/index.php/Servo
Wie funktioniert das? Der Timer wird so programmiert, dass er alle 10µs die Interruptserviceroutine (ISR) aufruft. Die Aufrufe werden in der ISR mitgezählt (count), der Zählerstand wird zwischen den Aufrufen gespeichert (static). Zusätzlich wird in der ISR der Zählerwert mit dem Wert für die Servoposition (servopos) verglichen und dem Ergebniss entsprechend der Servoausgang gesetzt oder gelöscht. Bei 10µs oder 0,01ms pro Aufruf ist nach 100 Aufrufen eine Millisekunde vergangen, nach 2000 sind es 20ms.PHP-Code:
#define SERVOPIN 7
#define SERVOPORT PORTD
#define DDRSERVO DDRD
volatile unsigned char servopos;
void servo_init()
{
TIMSK|=(1<<OCIE2);
TCCR2 |= (1<<WGM21) | (1<<CS20); //Prescale=1, CTC mode
OCR2 = F_CPU/100000; //alle 10µS ein IRQ
DDRSERVO|=(1<<SERVOPIN);
};
ISR(TIMER2_COMP_vect)
{
static int count;
if(count>servopos)SERVOPORT&=~(1<<SERVOPIN);
else SERVOPORT|=(1<<SERVOPIN);
if(count<2000)count++;
else count=0;
};
Alles klar soweit? Wie verwendet man das nun beim asuro? Man könnte Timer0 verwenden, denn der wird von der Library des asuro nicht verwendet. Oder man klinkt sich in den Timer1 ein der ja schon für die PWM-Ansteuerung der Antriebe genutzt wird:
ungetestetPHP-Code:
#include "asuro.h"
volatile unsigned char servopos=40; // 40 ist ca. 1 ms
SIGNAL (SIG_OVERFLOW1)
{
static int count = 1;
if(count > servopos) BackLED(OFF,OFF); else BackLED(ON,OFF);
if(count < 780) count++; else count=1;
}
int main(void)
{
Init();
TIMSK |= (1 << TOIE1); // Timer1 Overflow-ISR einklinken für Servo
unsigned char l;
int data[2];
FrontLED(ON);
l=108;
Sleep(255);
Sleep(255);
MotorDir(FWD,FWD);
MotorSpeed(130,130);
while(1) {
LineData(data);
if(data [0] < data[1])
{l=l+4;
MotorSpeed(100,140);}
else if(data[0] == data[1])
{l=l;}
else
{l=l-4;
MotorSpeed(140,100);}
//servo(l);
servopos = l; // Servoposition setzen
if(l > 120)
{l=120;}
else if(l < 80)
{l=80;}
else
{l=l;}
}
return 0;
}
Gruß
mic
Geändert von radbruch (21.08.2011 um 11:00 Uhr) Grund: servopos > count war falsch
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Das Programm funktioniert so leider nicht und mein Verständnis für die Elektronik und C reicht nicht aus um da nach nem Fehler zu suchen.
Der Servo zuckt hin und wieder, ich erkenne aber keine regelmäßigkeit.
Oje, das war auch Schwachsinn. Der Timer1 "läuft" beim asuro mit 3,9kHz. Das ist viel zu wenig für eine brauchbare Servoansteuerung.
Besser sieht es mit Timer2 aus. Der läuft mit 36kHz, (wie immer der Hinweis: Bei der orginalen CD-Library sind es 72kHz) und läßt sich ähnlich einfach missbrauchen:
getestet ;)PHP-Code:
#include "asuro.h"
volatile unsigned char servopos=0, p=0; // p dauert ca. 20ms oder 1/50 Sekunde
SIGNAL (SIG_OUTPUT_COMPARE2)
{
static int count = 1;
if(count > servopos) BackLED(OFF,OFF); else BackLED(ON,OFF);
//if(count > servopos) PORTC &= ~(1<<PC4); else PORTC |= (1<<PC4);
if(count < (20*72)) count++; else {count=1; if(p) p--;} // 20ms bei 72kHz-Lib!
}
int main (void)
{
Init();
//DDRC |= (1<<PC4); // Tasteneingang auf Ausgabe setzen
TIMSK |= (1 << OCIE2); // Timer2 CompareMatch-ISR einklinken für Servo
OCR2 = 0x91; // duty cycle for 36kHz vorsichthalber OCR2 belegen
while(1)
{
StatusLED(RED);
servopos=70;
p=50; // eine Sekunde warten
while(p);
StatusLED(GREEN);
servopos=190;
p=50;
while(p);
}
return 0;
}
Dabei sollten die Werte wie bei der Sleep()-Ansteuerung sein. servopos=0 sendet keinen Impuls zum Servo.
Gruß
mic
[Edit]
Sehr knuffig:
PHP-Code:
#include "asuro.h"
volatile unsigned char servopos=0, p=0; // p dauert ca. 20ms oder 1/50 Sekunde
SIGNAL (SIG_OUTPUT_COMPARE2)
{
static int count = 1;
if(count > servopos) BackLED(OFF,OFF); else BackLED(ON,OFF);
//if(count > servopos) PORTC &= ~(1<<PC4); else PORTC |= (1<<PC4);
if(count < (20*36)) count++; else {count=1; if(p) p--;} // 20ms bei 36kHz-Lib!
}
int main (void)
{
unsigned char l[3];
Init();
//DDRC |= (1<<PC4); // Tasteneingang auf Ausgabe setzen
TIMSK |= (1 << OCIE2); // Timer2 CompareMatch-ISR einklinken für Servo
OCR2 = 0x91; // duty cycle for 36kHz vorsichthalber OCR2 belegen
while(1)
{
SerRead(l,3,0); // drei Ziffern einlesen (blockierend!)
servopos = (l[0] - '0') * 100 + (l[1] - '0') * 10 + (l[2] - '0');
}
return 0;
}
Geändert von radbruch (21.08.2011 um 13:39 Uhr)
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
wenn ich die programme compilen will kommt folgender fehler:
asuro.o: In function `__vector_3':
C:\Users\Erik\Desktop\asuro_src\ASURO_src\FirstTry/asuro.c:35: multiple definition of `__vector_3'
test.o:C:\Users\Erik\Desktop\asuro_src\ASURO_src\F irstTry/test.c:6: first defined here
make.exe: *** [test.elf] Error 1
grrr
Welche Library verwendest du?
Mach mal ein Update auf 2.3 oder höher:
http://sourceforge.net/projects/asur...%20lib%20V2.3/
(asuro.c und asuro.h austauschen)
Die aktuelle Lib:
http://sourceforge.net/projects/asur...1.zip/download
Geändert von radbruch (21.08.2011 um 15:56 Uhr)
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Lesezeichen