Hallo Leute,
Ich weiß, dass das hier wahrscheinlich der 500 beitrag zu servos ist,
aber ich muss da jetzt einfach fragen weil ich ziemlich verzweifelt bin!
Ich bekomm es einfach nicht hin, meinen servo(futaba S3003
Modellbauservo)
so laufen zu lassen wie ich es möchte.
Also ich weiß wie servos angesteuert werden müssen. also impulse der
länge zwischen 1ms und 2ms verändern meine position des servos usw.
Also funktionsprinzip vom servo ist mir prinzipell klar!
So ich verwende einen PIC 16F877a mit jetzt mittlerweile der
Taktfrequenz 20Mhz (vor ein paar wochen habe ich noch 4 MHz verwendet ->
hat aber leider auch nicht hingehaun). Diesen PIC programmiere ich in C
mit MPLAB Version 8.10.
folgender pseudocode funktioniert einwand frei:
1
while(true)
2
{
3
output_high(PIN_C2);
4
delay_ms(2);
5
output_low(PIN_c2);
6
delay_ms(18);
7
}
also ich erzeuge mir quasi selbst ein pwm signal, indem ich den ausgang
C2 auf HIGH setze, dann 2 ms warte , und dann wieder auf LOW setze und
dann 18 ms warte!
wenn ich diesen code in meinem pic laufen lasse, stellt sich die
gewünschte servo position ein. (funktioniert auch für diverse andere
positionen also zum BSP für delay_ms(1.5) stellt sich mein servo in
mittelstellung!
so jetzt zu meinen eigentlichen problem:
ich möchte per rs232 aber die servo position variieren können!
dazu hab ich folgenden pseudocode:
1
while(true)
2
{
3
empfangen=getc();
4
switch(empfangen)
5
{
6
case'a':pos=1;
7
break;
8
case's':pos=1.5;
9
break;
10
case'd':pos=2;
11
break;
12
}
13
output_high(PIN_C2);
14
delay_ms(pos);
15
output_low(PIN_c2);
16
delay_ms(18);
17
}
also ich empfange über die rs232 ein zeichen, je nachdem ob dieses
empfangene zeichen a, b oda c ist sollte dann der sevo sich auf die
mittelstellung oda ganz rechts oda ganz links einstellen.
leider macht er das nicht. der servo zuckt dann nur!
was mach ich falsch? ich hoffe es kann mir jemand helfen! bin für viele
ratschläge, anmerkungen und eventuell anderen vorschlägen sehr dankbar!!
mfg dewey
> empfangen = getc();
Wenn getc() auf ein Zeichen wartet kann das
auch nicht funktionieren. Du bräuchtest eine
Funktion die mal nachsieht ob ein Zeichen empfangen wurde.
Falls nicht wird einfach im Programm weitergemacht.
hallo,
hab leider kein ossi!
nein eigentlich nicht! weil das kbhit() ist zwar dazu da das nur ein
zeichen gelesen wird, wenn eines empfangen wird! aba sobald das erste
zeichen gelesen wird. also ich sende das zeichen a zu meinem pic das
zeichen a wird dann in die variable empfangen gespeichert und dann
sollte durch die switch funktion die gewünschte pos eingestellt werden!
wenn jetzt kein zeichen empfangen wird, wird die getc() funktion
übersprungen und das zeichen das der variable empfanegen steht wird
wieder an meine switch funktion übergeben!
naja wie würdest du das mit den timer machen! welchen timer muss ich da
verwenden?? timer1??
also müsste ich folgendermaßen vorgehen:
ich setze mein ausgangspin auf high, in dem moment beginnt mein timer
hinauf zu zählen und nach 20ms wird mein timer wieder auf null gesetzt.
wenn ich jetz mein timer signal mit dem compare modul mit einem 2ten
signal vergleiche und die haben den selben wert also sind ident wird
mein ausgangspin wieder auf low gesetzt!
bin ich auf den richtigen weg oder??
wie würdest du das machen??
>> empfangen = getc();>wenn jetzt kein zeichen empfangen wird, wird die getc() funktion>übersprungen und das zeichen das der variable empfanegen steht wird>wieder an meine switch funktion übergeben!
Und woher soll getc() wissen was vorher in empfangen war?
empfangen wird einfach überschrieben mit dem Rückgabewert von getc().
nein sonst hab ich nix vergessen!*gg*
also if(kbhit()) wird nur TRUE wenn etwas über die rs232 empfangen wird!
das heißt ich sende ein zeichen vom pc zum pic -> kbhit() liefert 1
zurück -> empfangen = getc() wird ausgeführt (also das zeichen wird in
die variable empfangen gespeichert) -> switch anweisung ...
wenn ich jetzt kein zeichen sende -> kbhit() lifert rückgabewert 0 ->
empfangen = getc() wird nicht ausgeführt (weil ja die if anweisung FALSE
ist) -> somit wird das zeichen das vorher in der variable empfangen
gespeichert wurde wieder an die switch anweisung übergeben!
hallo leute!
ich habe jetzt mal einen programm code geschrieben der den servo in eine
bestimmte position bringt und dort die position hält!
das ganze habe ich jetzt mit den timer1 realisiert!
1
2
#include<16F877a.h>
3
#include<stdlib.h>
4
#use delay (clock=20000000)
5
#fuses HS, NOWDT, NOPROTECT, NOLVP
6
#use RS232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
7
8
voidmain(void)
9
{
10
int16pos=1875;// Servo mittelstellung (1,5ms)
11
12
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
13
14
set_timer1(0);//timer wird auf 0 gesetzt
15
output_high(PIN_C2);//ausgang wird auf high gesetzt
16
while(true)
17
{
18
if(get_timer1()>=pos)//wenn pos >= timer wert
19
output_low(PIN_C2);// ausgang auf low setzen
20
21
if(get_timer1()>=22500)//22500 entspricht 18ms
22
{
23
set_timer1(0);
24
output_high(PIN_C2);
25
}
26
}
27
}
so dieser code funktioniert einwandfrei! ich habe es mit verschiedenen
pos werten ausprobiert und es funktioniert!
nun möchte ich aber per rs232 ein zeichen senden das mir eine bestimmte
pos bestimmt.
das heißt wenn ich zb ein 'a' sende, soll mein servo ganz nach links
oder rechts drehen!
also ich habe folgenden code ausprobiert, aber so funktioniert es leider
nicht und ich weiß nicht warum!
1
#include<16F877a.h>
2
#include<stdlib.h>
3
#use delay (clock=20000000)
4
#fuses HS, NOWDT, NOPROTECT, NOLVP
5
#use RS232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
6
7
voidmain(void)
8
{
9
int16pos=1875;// Servo mittelstellung (1,5ms)
10
charempfangen;
11
12
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
13
14
set_timer1(0);//timer wird auf 0 gesetzt
15
output_high(PIN_C2);//ausgang wird auf high gesetzt
16
while(true)
17
{
18
if(get_timer1()>=pos)//wenn pos >= timer wert
19
output_low(PIN_C2);// ausgang auf low setzen
20
21
if(get_timer1()>=22500)//22500 entspricht 18ms
22
{
23
set_timer1(0);
24
output_high(PIN_C2);
25
}
26
if(kbhit())empfangen=getc();//zeichen wird gelesen, in empfangen gespeichert
mein timer zählt bis 22500 dann wird er auf null gesetzt (22500
entsrechen 20 ms)
könnte mir bitte jemand helfen! was hab ich falsch gemacht?
wie würdet ihr das machen?
mfg dewey
Du mußt das schalten der Ausgänge in eine ISR packen...
Ich hab das dann so gemacht das dien zweiter timer die ausgabe immer
wieder neu startet (damit man fein genung auflösen kann)
Aber man kann auf folgendes machen...
ISR wird alle 0,1ms ausgeführt...
In der ISR zählst du einen weiter variabele hoch, wenn diese gleich dem
Wert für den Servo ausgang wird der Ausgang low geschaltet..
High wird der Ausgang wenn deine Zählvar. 0 wird..
Die wird 0 wenn sie das Maxiumum erreicht hat (bei dieser Version 20000)
so zB (so ungefähr)
hallo jan-h. B.!
danke für deine antwort!
das heißt also das mein code folgendermaßen aussieht:
1
#include<16F877a.h>
2
#include<stdlib.h>
3
#use delay (clock=20000000)
4
#fuses HS, NOWDT, NOPROTECT, NOLVP
5
#use RS232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
6
7
int16zaehler=0;
8
int16pos=1875;// Servo mittelstellung (1,5ms)
9
10
#INT_TIMER1 //wodurch soll diese isr ausgelöst werden
11
voidisr()// jetzt würde diese isr() ja auch immer nur ausgeführt
12
{// wenn der timer1 einen überlauf hat
13
14
if(zaehler==0)
15
output_high(PIN_C2);
16
17
if(zaehler==pos)
18
output_low(PIN_C2);
19
20
if(zaehler==20000)
21
zaehler=0;
22
23
zaehler++;
24
}
25
26
voidmain(void)
27
{
28
charempfangen;
29
30
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
31
32
set_timer1(0);//timer wird auf 0 gesetzt
33
output_high(PIN_C2);//ausgang wird auf high gesetzt
34
35
while(true)
36
{
37
if(kbhit())empfangen=getc();//zeichen wird gelesen, in empfangen gespeichert
38
if(empfangen=='a')pos==2500;//2ms
39
if(empfangen=='w')pos==1250;// 1ms
40
}
41
}
das mit der isr() ist mir noch nicht ganz klar! warum man das braucht!
was macht diese interrupt routine wird einfach alle 0,1ms ausgelöst oder
wie? und durch welche aktion wird diese ausgelöst? kann man das auch
einstellen wann diese isr() immer ausgeführt wird?? brauch dann
überhaupt noch meinen timer1??
danke schon im voraus!!
mfg dewey
ahhh jetzt hab ichs glaub ich kapiert!!
ich stelle meinen timer so ein, damit der immer nach 0,1ms einen
interrupt auslöst! und wenn mein interrupt ausglöst wird, in dieser isr
wird ein zähler implementiert der immer um eins hinaufzählt wenn die isr
ausgeführt wird! und weiters wenn der zähler in der isr den wert 20000
erreicht hat wird der zähler auf 0 rückgesetzt , wenn der zähler gleich
der gewünschten servo positionswert ist wird der ausgang auf low gesetzt
und wenn der zähler == 0 ist wird der ausgang auf high gesetzt!
also ist jetzt zwar nicht gerade übersichtlich aufgeschieben aber ich
glaub jetzt weiß ich wie das funktionieren soll!
also ich werds einfachmal so ausprobieren!!
falls ich wieder einen denkfehler habe, bitte melden!
danke schon im voraus
mfg dewey
hallo!
also hab jetzt mal einen code geschrieben der aller 0.1ms einen
interrupt auslöst.
1
#include<16F877a.h>
2
#device ADC=10 //10bit Auflösung
3
#use delay (clock=20000000)
4
#fuses HS, NOWDT, NOPROTECT, NOLVP
5
#use RS232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
6
#include<stdlib.h>
7
8
int16pos=1000;
9
int16zaehler=0;
10
11
#INT_TIMER0
12
voidisr()
13
{
14
zaehler++;
15
if(zaehler==pos)
16
output_low(PIN_C2);
17
if(zaehler==20000)
18
zaehler=0;
19
if(zaehler==0)
20
output_high(PIN_C2);
21
}
22
23
voidmain(void)
24
{
25
charempfangen;
26
27
setup_timer_2(T2_DIV_BY_4,125,1);
28
set_timer2(0);
29
output_high(PIN_C2);
30
31
enable_interrupts(INT_TIMER2);
32
enable_interrupts(GLOBAL);
33
while(true)
34
{
35
if(kbhit())empfangen=getc();
36
if(empfangen=='a')pos==2000;//2ms
37
if(empfangen=='d')pos==1000;// 1ms
38
if(empfangen=='s')pos==1500;// 1.5ms
39
}
40
41
}
aber wenn ich jetzt kompiliere sagt mir der compiler 3 warnings
und zwar in der while(true) schleife bei den if(empfangen...)
anweisungen
der compiler sagt das dieser code keinen effekt hat!!
kann mir jemand erklären warum?? versteh das nicht ganz!
mfg dewey
hallo
ah hoppala da gehört natürlich timer2, ich habs bei mir im MPLAB eh
richtig nur da hab ichs im eifer des gefechts vergessen auszubessern!
ja ich hab jetzt die empfangen variable initialisiert aber der compiler
meckert immer noch!
mfg
Hallo
Ich bin gerade dabei, eine Steuerung mit einem PIC16F877a zu bauen.
Dabei sollen 3 Servos per PC angesteuert werden können. Aber auch 3
Sensordaten sollen zum PC zurückgesendet werden.
Ich habe jetzt schon mal einen Programmcode geschrieben, mit dem ich
einen Servo problemlos per PC steuern kann.
Nun möchte ich aber auch noch Daten zu meinem pc senden. Doch leider
funktioniert das nicht so wie ich es mir vorstelle!
Der Timer2 Interrupt wird alle 0,1ms ausgeführt und in dieser
Interruptroutine erzeuge ich dann den Impuls von 1-2ms. Jetzt habe ich
noch den Timer0 so konfiguriert, dass diese isr alle 0,05ms ausgeführt
wird und mir dann die Messdaten zum PC sendet (Ich habe jetzt nur einen
einfachen Text zum testen genommen). Dieser Text wird mir zwar zu meine
PC gesendet, aber ich kann meinen Servo nicht mehr steuern.
Könnte mir jemand erklären warum das so nicht funktioniert.
Wie würdet ihr das machen??
Hoffe mir kann jemand helfen!
hallo
Habe jetzt eine LED eingeschalten und es funktioniert. LED leutet und
ich kann meinen Servo auch noch steuern.
Hast du eine Idee wie ich Messdaten zu meinem PC senden könnte??
hallo
Erstmal danke!
Ich habe das jetzt ausprobiert, doch leider hängt sich da mein pic auf!
Am Anfang hat es funktioniert und sobald ich einmal ein Zeichen zum PIC
sende hängt er sich auf!
mfg
hallo
ich hab mal ne frage! Warum ist das nicht gut, wenn ich in einer isr
einen printf Befehl verwenden will? Warum funktioniert das nicht??
mfg dewey
printf verbraucht massig Rechenzeit...
ISRs sollten möglichst kurz sein...
Daher kann es dann sein das du Interrupts übersiehst/nicht rechtzeitig
reagierst...