Sehr geehrtes Forum,
ich habe mal wieder ein Problem :|.
(Newbie Problem, einfaches Programm, nicht sinnvoll)
Ich möchte gerne einen Servo ansteuern.
Diesen versorge ich extern mit 5 V, und habe dessen GND
auch mit dem GND des Chips verbunden, welcher übrigstens auch mit 5V
versorgt wird.
Mein Servo hat die Kabelfarben Rot, Gelb und Braun, d.h. Rot = 5V, Braun
= GND und Geld = Signal?
Nun habe ich folgendes Programm, welches ich schon mehrmals mit dem
Debugger auf richtige Wartezeit der Wartemethoden geprüft habe, ebenso
wie auch durch Testen der WAIT_1_SEC Methode mit einer LED in echt.
1
.include "m88def.inc"
2
3
/*
4
5
Servosteuerung, durch Pulse zwischen 1ms und 2ms, alle 20ms
6
7
Taktfrequenz des MC: 1 MHz
8
*/
9
10
.CSEG
11
// Definitionen
12
.def POSITION = R20
13
14
// Richtung der IO Ports definieren
15
LDI R16, 0b11111111 // 1=Output, 0=Input
16
OUT DDRD, R16
17
18
// Stackpointer initialisieren
19
LDI R16, low(RAMEND)
20
OUT SPL, R16
21
LDI R16, high(RAMEND)
22
OUT SPH, R16
23
24
// Main Methode
25
26
MAIN:
27
LDI POSITION, 20 // Servo nach links stellen = 2,0 ms
28
RCALL SERVO_COMMAND
29
RCALL WAIT_1_SEC
30
31
LDI POSITION, 15 // Servo nach mitte stellen = 1,5 ms
32
RCALL SERVO_COMMAND
33
RCALL WAIT_1_SEC
34
35
LDI POSITION, 10 // Servo nach rechts stellen = 1,0 ms
36
RCALL SERVO_COMMAND
37
RCALL WAIT_1_SEC
38
39
RJMP MAIN
40
41
// Servo Motor Positionieren
42
SERVO_COMMAND:
43
LDI R25, 10
44
45
SERVO_COMMAND_2:
46
47
MOV R21,R20
48
SBI PORTD,PD0
49
SERVO_COMMAND_1:
50
RCALL WAIT_100_MIC_SECS
51
DEC R20
52
BRNE SERVO_COMMAND_1
53
54
MOV R20,R21
55
CBI PORTD, PD0
56
RCALL WAIT_10_MIL_SECS
57
RCALL WAIT_10_MIL_SECS
58
59
DEC R25
60
BRNE SERVO_COMMAND_2
61
RET
62
63
64
// WAIT 100_MIC_SECS
65
WAIT_100_MIC_SECS:
66
LDI R17, 3
67
WAIT_100_MIC_SECS_2:
68
LDI R16,9
69
WAIT_100_MIC_SECS_1:
70
DEC R16
71
BRNE WAIT_100_MIC_SECS_1
72
DEC R17
73
BRNE WAIT_100_MIC_SECS_2
74
NOP
75
NOP
76
NOP
77
RET
78
79
// WAIT 10_MIL_SECS
80
WAIT_10_MIL_SECS:
81
LDI R18, 100
82
WAIT_10_MIL_SECS_1:
83
RCALL WAIT_100_MIC_SECS
84
DEC R18
85
BRNE WAIT_10_MIL_SECS_1
86
RET
87
88
// WAIT 1_SEC
89
WAIT_1_SEC:
90
LDI R19, 100
91
WAIT_1_SEC_1:
92
RCALL WAIT_10_MIL_SECS
93
DEC R19
94
BRNE WAIT_1_SEC_1
95
RET
Das Programm sendet also 10 mal einen Impuls, welcher 2ms dauert, und im
Abstand von 20ms. Der Servo sollte also nach links.
Dann wartet das Programm 1 Sekunde.
Dann 10 mal einen Impuls, welcher 1,5ms dauert, und ebenfalls im Abstand
von 20ms. Der Servo sollte also in die mitte.
Dann wartet das Programm 1 Sekunde.
Dann 10 mal einen Impuls, welcher 1,0ms dauert, und ebenfalls im Abstand
von 20ms. Der Servo sollte also rechts.
Dann wartet das Programm 1 Sekunde.
Ich hab das Signal meines MCs auch schon an ne LED gelegt, es kommt
definitiv beim Servo an.
Nun passiert folgendes: Der Servo dreht sich bis zum Anschlag nach
rechts, egal ob ich 1,0ms, 1,5ms oder 2,0ms Pulse sende.
Kann mir jemand sagen was ich falsch mache?
Ich habe den Anschluss mehrfach überprüft, und denke, dass ich laut
diesem Tutorial
https://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung auch
richtig mit meinen Annahmen in Bezug auf die Belegung gehe.
Danke sehr für eure Hilfe,
m.f.G.: Developer_X
A. B. schrieb:> Mein Servo hat die Kabelfarben Rot, Gelb und Braun, d.h. Rot = 5V, Braun> = GND und Geld = Signal?
Du hast doch den Servo vor dir liegen und kennst als einziger den Typ.
Wie soll dir hier jemand erzählen, wie der Hersteller sich das mit den
Anschlüssen gedacht hat.
Hier ein bisschen Auswahl:
http://wiki.rc-network.de/Servo
Seltsam ist auch, dass manchmal, wenn ich allein schon die Spannung an
den Servo anschließe, der sich dreht, und zwar auch in dieselbe Richtung
zum Anschlag.
Hat jemand eine Idee?
Ich weiss ja nicht ob sich da was geändert hat, aber früher (TM) musste
das Signal kontinuierlich gesendet werden und
1ms / 2ms waren vollausschlag li/re und 1,5ms Neutral. Alles dazwischen
irgendwas anderes. Pausen mochte das System garnicht =Ausfall, ggf.
Notstellung.
Wie schon geschrieben, das Datenblatt ist Dein Freund.
//hufnala
A. B. schrieb:> Dann wartet das Programm 1 Sekunde.
Du kannst nicht 1 Sekunde lang nichts tun.
Ein Servo will ständig Pulse!
Die Pulse sagen ihm, welche Position es anfahren (und halten) soll.
Kommen keine Pulse mehr, dann macht es irgendwas (je nach Typ).
D.h. wenn du das Servo 1 Sekunde lang an einer Position halten willst,
dann musst du ihm auch 1 Sekunde lang genau die Pulslänge dafür
schicken.
Und spätestens jetzt rächt sich dein Delay-Ansatz. Denn wenn man das
geschickt macht, dann erzeugt der Timer ganz von alleine ständig die
richtigen Pulse.
Ich hab deine Code-Zeiten jetzt nicht kontrolliert und nachgerechnet.
Aber wenn du erst mal von einem ständigen Wechsel des Servos Abstand
nimmst, dann schickst du ihm erst mal einfach nur eine immer gleiche
Pulslänge. Zb 1.7ms. Das Servo muss dann genau diese Position anfahren.
Als Gegentest schickst du ihn eine andere Pulslänge (natürlich ständig).
Zum Bleistift 1.2ms. Das Servo muss dann diese andere Position anfahren.
Und natürlich halten.
Wenn es das nicht tut, dann stimmen deine Pulslängen nicht.
(Deine Kabelbelegung dürfte stimmen. Rot ist Spannung, Braun ist Masse,
Gelb ist Signal)
So, ich habe mir das lange nochmal durch den Kopf gehen lassen.
Ich habe hier, ein ganz primitives C-Programm, viel schneller lesbar als
ein Assembler Programm
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main (void)
5
{
6
DDRD = 0xFF;
7
PORTD = 0b00000000;
8
9
while(1)
10
{
11
PORTD = 0b00000001;
12
_delay_us(1500);
13
14
PORTD = 0b00000000;
15
_delay_ms(20);
16
}
17
18
return 0;
19
}
Ich mein hier sieht man doch, dass die Signale dauerhaft gesendet
werden, und zwar dauerhaft, im Abstand von 20ms, für eine Pulsdauer von
1,5ms.
Was konkret passiert: Jedes mal wenn der MC solch einen Puls sendet,
reagiert der Servo, und dreht sich rechts an den Anschlag, egal wie lang
ich die Pulslänge mache.
Denkt ihr, es könnte ein Fehler am Servo sein?
Er dreht sich nur in die eine Richtung.
Danke für eine Antwort,
m.f.G.: Developer_X
A. B. schrieb:> Denkt ihr, es könnte ein Fehler am Servo sein?
Wenn ich mal davon ausgehe, dass die Verkabelung stimmt, dann kommt auch
noch die Stromversorgung in Frage.
Servos können richtige Dreckschweine sein und dir massenhaft Störungen
auf die Versorungsspannung einkoppeln. Die muss gut gesiebt werden,
sonst schmiert dir der µC dauernd ab.
Ich hab da eine 5V Spannung die mit großen als auch kleinen
Kondensatoren schön geglättet wird.
Der Punkt ist: Früher hatte ich das einmal hinbekommen, leider
funktioniert das jetzt nicht mehr. Aber er kann nicht kaputt sein, da
dieser reagiert, oder?
Ich weiß woran es noch liegen könnte:
Wie stellt man bei der Delay.h ein, welche Taktgeschwindigkeit
am MC eingestellt ist? (Ich nutze C nicht, deswegen weiß ich das nicht
:( )
Ich habe nämlich eine Geschwindigkeit von 1MHz, könnte diese auf 8 MHz
hochsetzen, hat beides aber auch nichts gebracht.
A. B. schrieb:> Aber er kann nicht kaputt sein, da dieser reagiert, oder?
'türlich kann er trotzdem defekt sein. Das Servo bestimmt seine Position
anhand eines Potentiometers auf der Achse. Hat bspw. der Schleifer
keinen richtigen Kontakt mehr, spinnt das Servo. Da hilft nur Gegenprobe
mit einem (funktionierenden) RC-Empfänger oder Servotester.
A. B. schrieb:> Wie stellt man bei der Delay.h ein, welche Taktgeschwindigkeit> am MC eingestellt ist?
Falscher Ansatz. Zeit, sich mit den PWM-Funktionen der Timer zu
beschäftigen. Die sind für sowas nämlich um Größenordnungen besser
geeignet als Delay-Schleifen. Keine Angst, so kompliziert ist das nicht.
Ok. Aber ich glaube der Servo ist trotzdem nicht funktionsfähig, da er
immerhin auch schon nach Anschluss, sogar wenn Signal ganz auf VCC oder
ganz auf GND gleich zum Anschlag dreht.
Tschuldig das ich störe...
aber warum nutzt nicht nen Timer der dir die 1-2ms generiert und mit den
selben Timer kannst du, nach jeweils 20ms, den neuen Impuls anlegen...
Warum so kompliziert... Auch wenns nur ein nicht Sinnvolles Program ist
??
Gerade weils hier auf nix ankommt mal alle Möglichkeiten
durchspielen....
Also ich habe jetzt, in Assembler, und mit dem Debugger auf genaue
Taktzahlen geprüft, ein paar Funktionen geschrieben, die einmal 1ms,
einmal 1.5ms, und einmal 20ms warten.
1
.include "m88def.inc"
2
3
4
/*
5
6
Taktfrequenz des MC: 1 MHz
7
*/
8
9
.CSEG
10
11
// Richtung der IO Ports definieren
12
LDI R16, 0b11111111 // 1=Output, 0=Input
13
OUT DDRB, R16
14
OUT DDRC, R16
15
OUT DDRD, R16
16
17
// Stackpointer initialisieren
18
LDI R16, low(RAMEND)
19
OUT SPL, R16
20
LDI R16, high(RAMEND)
21
OUT SPH, R16
22
23
// Timer Einstellung initialisieren
24
IN R16, TCCR0B
25
SBR R16, (1<<CS00) | (1<<CS01) // Prescaler von 64 einstellen
26
OUT TCCR0B, R16
27
28
// Main Methode
29
LDI R17, 0x00
30
31
MAIN:
32
SBI PORTD, PD0 // LED einschalten
33
// Warten bis 20ms vergangen
34
RCALL WAIT_1_5_MS // Braucht 1000 Takte, also 1,000 ms
35
36
CBI PORTD, PD0 // LED ausschalten
37
// Warten bis 20ms vergangen
38
RCALL WAIT_20_MS
39
RJMP MAIN
40
41
WAIT_1_MS:
42
OUT TCNT0, R17 // Counter resetten
43
LOOP_1: // Warten bis Counter abgelaufen
44
IN R16, TCNT0
45
CPI R16, 15
46
BRLO LOOP_1
47
48
LDI R18, 9
49
LOOP_2:
50
DEC R18
51
CPI R18, 0
52
BRNE LOOP_2
53
54
NOP
55
RET
56
57
WAIT_1_5_MS:
58
OUT TCNT0, R17 // Counter resetten
59
LOOP_4: // Warten bis Counter abgelaufen
60
IN R16, TCNT0
61
CPI R16, 23
62
BRLO LOOP_4
63
64
LDI R18, 6
65
LOOP_44:
66
DEC R18
67
CPI R18, 0
68
BRNE LOOP_44
69
70
NOP
71
RET
72
73
WAIT_20_MS:
74
LDI R19, 20
75
LOOP_3:
76
RCALL WAIT_1_MS
77
DEC R19
78
CPI R19, 0
79
BRNE LOOP_3
80
RET
Es funktioniert weiterhin nicht, der Servo dreht nach rechts.
Jetzt muss es definitiv am Servo liegen, denke ich zumindest.
Was meint ihr?
m.f.G.: Developer_X
A. B. schrieb:> Was meint ihr?
Nicht so schnell.
Du klingst nicht besonders sicher, was die Taktfrequenz deines µC
angeht.
Die würde ich mal überprüfen.
Das kannst du ganz einfach machen.
Häng mal eine LED an den Ausgang.
(das F_CPU muss am sinnvollsten VOR die Includes. Du weisst nicht, in
welcher Form der Wert von dem includierten Teil benutzt wird!)
1
#define F_CPU 1000000UL
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
7
intmain(void)
8
{
9
DDRD=0xFF;
10
11
12
while(1)
13
{
14
PORTD=0b00000001;
15
_delay_ms(1000);
16
17
PORTD=0b00000000;
18
_delay_ms(1000);
19
}
20
}
LED beobachten.
leuchtet sie 1 Sekunde und ist 1 Sekunde aus?
Die Zeiten brauchst du jetzt nicht mit der Stoppuhr kontrollieren. Denn
die Alternativen sind nicht so gross. Wenn der µC mit 8Mhz läuft, dann
leuchtet die LED nur 1/8 Sekunde (und ist 1/8 Sekunden aus). Den
Unterschied sieht man mit freiem Auge.
Karl H. schrieb:> (das F_CPU muss am sinnvollsten VOR die Includes.
d.h. am sinnvollsten kommt sie ins makefile bzw. in die
Projekteinstellungen. Aber lass uns die Dinge jetzt nicht
verkomplizieren, wenn du normalerweise kein C benutzt)
Ja, ich habs kontrolliert, die Zeit beträgt eine Sekunde.
Ich denke wirklich, dass es am Servo liegt.
Weil es wirklich richtig scheint mit der Zeit und der Impulsdauer.
Felix A. schrieb:> Es gibt auch Servos, die einen invertierten Puls haben wollen. Also eine> Lowphase von 1 bis 2 ms brauchen.
Die gab es vor 30 Jahren zu kaufen.
Robin schrieb:> Schraub mal den Servo auf und kontrolliere die Kabel zum Poti. Würde> fast wetten, das da entweder eine kalte Lötstelle ist oder das Kabel> gebrochen.
Jetzt wärs natürlich gut, wenn man das Servo nur zur Kontrolle an einen
normalen RC-Empfänger anstecken könnte.
Hi,
>Ok. Aber ich glaube der Servo ist trotzdem nicht funktionsfähig, da er>immerhin auch schon nach Anschluss, sogar wenn Signal ganz auf VCC oder>ganz auf GND gleich zum Anschlag dreht.
Ist def. weil ein Servo ohne Signal stehen bleibt(sollte).
Viel Erfolg, Uwe