Hallo Leute!
Ich würde gerne einen/mehrere Servo(s) ansteuern. Also habe ich mir
einen kleinen Code zusammengebastelt:
1
#define F_CPU 16000000L
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
unsignedchari;
7
8
intmain()
9
{
10
DDRA=0xFF;
11
PORTA=0x00;
12
while(1)
13
{
14
for(i=0;i<150;i++)
15
{
16
PORTA=0xFF;
17
_delay_us(2000);
18
PORTA=0x00;
19
_delay_ms(18);
20
}
21
for(i=0;i<150;i++)
22
{
23
PORTA=0xFF;
24
_delay_us(1000);
25
PORTA=0x00;
26
_delay_ms(19);
27
}
28
}
29
30
while(1);
31
return0;
32
}
Dazu habe ich den Servo dann angeschlossen, also das schwarze Kabel an
Minus, das Rote an Plus und das letzte an irgendeinen Pin von Port A.
Eigentlich sollte das Servovieh immer schön hin und her drehen, oder?
Und wie ihr euch schon denken könnt: Es funktioniert nicht. Ein Servo
dreht sturr nach links und ein anderes Modell tut garnichts. Ich habe
absolut keine Ahnung, wo der Fehler liegt? Ist was in meinem Code
falsch?
Also mit der Frequenz sollte eigentlich alles stimmen...
Habt ihr eine Antwort?
Vielen Dank schonmal, PowerProgrammer
Aus der avr-libc Doku:
_delay_ms:
The maximal possible delay is 262.14 ms / F_CPU in MHz.
_delay_us:
The maximal possible delay is 768 us / F_CPU in MHz.
da musste mal deinen code anpassen
Oh, vielen Dank!
Vorher hatte ich das aber auch mit _delay_ms(1); und _delay_ms(2);
gemacht, es hatte trotzdem nicht geklappt. Naja, das wäre hier jetzt ein
zusätzlicher Bug, danke für den Hinweis!
Weiß denn jemand, was noch falsch sein könnte?
Hi PowerProgrammer,
die Servos erwarten folgendes "Protokoll":
[Stellimpuls][Warteimpuls]
Von Impuls zu Impuls 22,5ms
Stellimpuls + Warteimpuls = 22,5ms
Für die Position 0 ist der Stellimpuls 0,7ms
für die Position voll Ausschlag 2ms
1
while(1)
2
{
3
PORTA=0xFF;
4
_delay_us(2000);
5
PORTA=0x00;
6
_delay_ms(20);
7
PORTA=0xFF;
8
_delay_us(700);
9
PORTA=0x00;
10
_delay_ms(21);
11
12
}
Der Code hat zumindest bei mir funktioniert.
Habs nacher mit einem Timer gelöst. Das ist nicht ganz so CPU lastig
Gruß Marcus
Hmm, ich hatte gelesen, dass die Summe aus Stellimpuls und Wartezeit
nicht exakt sein muss und zwischen 10 und 20 ms liegen soll.
Jedenfalls kann dein Code nach der Anmerkung thorstens nicht
funktinieren, wenn er das bei dir dennoch tat, dann ist das höchst
seltsam. Nach deinem Code wechselt das Teil ja alle 22,5 ms die
Stellung, das schafft kein Servo, also, ich werde den Code bei
gelegenheit mal ausprobieren, wenn er klappt, fresse ich nen Besen.
Danke.
Hallo PowerProgrammer,
ups, da ist mir wirklich ein kleiner Fehler unterlaufen. Hab aus meinem
Code das ein oder andere rausgeschnippelt und leider auch eine falsche
Zeile!
1
while(1)
2
{
3
inti=0;
4
while(i<200){
5
PORTA=0xFF;
6
_delay_us(2000);
7
PORTA=0x00;
8
_delay_ms(20);
9
i++;
10
}
11
while(i<200){
12
PORTA=0xFF;
13
_delay_us(700);
14
PORTA=0x00;
15
_delay_ms(21);
16
}
17
18
}
Das Servo sollte so alle 4 Sekunden einal von ganz rechts nach ganz
links wandern. Die Standartservos brauchen da so ihre Zeit.
Gruß Marcus
Hallo PowerProgrammer,
ups, da ist mir wirklich ein kleiner Fehler unterlaufen. Hab aus meinem
Code das ein oder andere rausgeschnippelt und leider auch eine falsche
Zeile!
while(1)
{
int i = 0;
while (i < 200) {
PORTA = 0xFF;
_delay_us(2000);
PORTA = 0x00;
_delay_ms(20);
i++;
}
i = 0;
while (i < 200) {
PORTA = 0xFF;
_delay_us(700);
PORTA = 0x00;
_delay_ms(21);
i++
}
i = 0;
}
Das Servo sollte so alle 4 Sekunden einal von ganz rechts nach ganz
links wandern. Die Standartservos brauchen da so ihre Zeit.
Gruß Marcus
Trotzdem werden weder _delay_us(2000) noch _delay_us(700) das tun, was
Du von ihnen erwartest. Wenn das funktioniert, dann zufällig! Thorstens
Beitrag entspricht Tatsachen...
Danke, es geht mir halt drum, erstmal einen verfluchten Servo irgendwie
zu bewegen, egal wie dreckig der Code ist;) Ich bin halt neu in der
Branche und habe so Sachen wie Timer und Interrupts und alles beim AVR
noch nie genutzt, ich kenne bis jetzt halt nur die Intel-x86-Prozessoren
genauer...
Ich verzweifel an diesen Teilen sowieso, ich weiß nicht, wieso die Teile
mich nicht mögen. Wüsste nur zu gerne, wie ich am besten mal die Signale
meines AVRs unter die Lupe nehmen könnte...
PowerProgrammer
>wie ich am besten mal die Signale meines AVRs unter die Lupe nehmen >könnte...
Für sowas benutzt man in der Regel ein Oszilloskop.
Würdestr du die Suche des Forums bemühen, würdest du auch diverse
Lösungen mit Timern finden.
Fluchen bringt übrigens bei Servos (und anderen Dingen) überhaupt
nichts, sowas hilft höchstens bei anderen Menschen...
Hai PowerP,
guck' Dir doch mal meinen Code an. Eine brauchbaren Servopuls kriegst Du
mit einer Handvoll Codezeilen hin.
Beitrag "Sequenzer für Einziehfahrwerke"
Gruß,
Peter
Ein wirklich gut gemeinter Ratschlag, allerdings doch etwas
unverständlich für einen Anfänger, der schon bei 2 Delay-Anweisungen
verzweifelt;) Ich dachte mir halt wirklich, Timer erst einzubauen, wenn
der Servo überhaupt erstmal irgendiwie funktioniert!
Trotzdem nochmal vielen Dank an all die Leute, die mir geholfen haben!
PowerProgrammer
ok Jungs, jetzt sag ich euch mal wie das geht! mit folgender methode
kannst du ganz elegeant 2 servos ansteuern!
du benutzt fast PWM und setzt ICR als TOP! das machst du so WGM1n=1110,
siehe dazu datenblatt S.112! den timer musst du noch ein wenig
prescalen, damit du genau nach 22.5ms den wert in ICR erreichst! nun
stellst du noch OCR1n so ein dass bei einem compare match das pwm signal
gelöscht wird! jetzt gibt es ja aber ein minimum und maximum deines pwm
signals, d.h das minimum ist ja glaub ich bei 1ms und das maximum bei
2ms oder so! dazu berechnest du einfach den zählerstand des timers der
bei diesen werten! um OCR1n zu setzen nimmst du dann
OCR1n=Minimum+(Maximum-Minimum)/Auflösung*Wert
alles klar?
Hi,
ich werd den alten Thread ma vorkramen, da ich ein ähnliches bzw. das
gleiche problem hab. Ich hab hier zwei Servos, der eine ohne
Potirückmeldung und der andere mit Rückmeldung.
Dazu hab ich den folgenden Quellcode, denn ich aus dem Tutorial von hier
habe. Allerdings laufen beide servos immer nur nach links, auch wenn ich
die Delay-Zeit ändere!
Kann mir jemand helfen!!
Danke!