-
Das Problem was Dirk meint wird sein das Dein PWM vielleicht gar keines ist? - Weil die Periode zu lang ist, eben 350 - 400ms. Sie darf aber anfänglich nicht länger als 2ms sein um im Stellbereich des Servos zu bleiben - und auch wenn man die Grenze des Stellbereichs etwas ausweiten möchte bewegt man sich um einen Wert etwa +- 0,6ms um 1,5ms (neutral Stellung). Der digital Servo kann mit einer zu langen Periode (bzw nicht PWM) keine Stellposition berechnen.
Ich habe an eine BabyOranutan (20MHz) einen analogen Servo hängen, ich steuere den mit Bascombefehl Pulsout an. Dort sind die Werte die man eingibt von der Geschwindigkeit des µC abhängig. Bei 20MHz ist ein Wert von ca 8000 eher normal. Sollte hier doch auch so sein?
Nein, man benötigt den Widerstand nicht zwingend.
- - - Aktualisiert - - -
Ich denke wenn Du Dein Programm jetzt so schreiben würdest wie Dirk vorgeschlagen hat, dann wird es wohl eher helfen. Mehr jedenfalls als in der Funktion selbst solche sachen zu machen.
Ändere doch einfach in deinem Ersten Programmpost die Zeiten der Servos bei sleep in 50 oder auch 20 statt 200. Und in der main den mSleep höher wählen. Was ist das für eine Variable (byte; word?) - wie hoch kann man wählen? Nimm mal 500, wenn nichts geht nimm 550 usw usw... oder kleiner werden, in 50er Schritten.
Die LCD Befehlszeilen ALLE (3) auskommentieren.
-
habe es jetzt so:
Code:
void servo1(int pos)//rechter Servo
{
PORTC |= IO_PC4;
sleep(pos);
PORTC &= ~IO_PC4;
sleep(50-pos);
}
void servo2(int pos)//linker Servo
{
PORTC |= IO_PC6;
sleep(pos);
PORTC &= ~IO_PC6;
sleep(50-pos);
}
int main(void)
{
initRP6Control();
initLCD();
I2CTWI_initMaster(100);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedDataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);
mSleep(500);
I2CTWI_transmit3Bytes(Base, 0, CMD_SET_ACS_POWER, ACS_PWR_OFF);
I2CTWI_transmit3Bytes(Base, 0, CMD_SET_WDT, true);
I2CTWI_transmit3Bytes(Base, 0, CMD_SET_WDT_RQ, true);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, 6, BWD);
showScreenLCD("Servo Test","",""," Test");
mSleep(500);
clearLCD();
while(true)
{
for(x=4;x<25;x++)
{
servo1(x);
servo2(x);
//batpower();
//setCursorPosLCD(1,1);
//writeIntegerLCD(x,DEC);
mSleep(500);
}
//clearLCD();
}
}
ok?
aber funktioniert nichts keine bewegung!
- - - Aktualisiert - - -
eins ist aber auch komisch und zwar habt ihr ja gesagt, dass die digitalservos ihre stellung halten in der sie sind. solange diese strom haben. ich kann meine aber drehen wenn ich sie von hand bewege. sie sind aber richtig angeschlossen. habe mir extra die steckerbelegung angeguckt und alles auf richtigkeit geprüft(spannung und durchgang)
-
Bei dieser Version bekommt jedes Servo alle [500ms + eigene Pause + Impuls u. Pause des anderen Servos] einen Impuls von 0,4 bis 2,5ms.
Also noch weiter außerhalb der Spezifikation als in deinem 1. Beispiel.
Frage: Setzt du die beiden Ports eigentlich irgendwo auf AUSGANG?
-
habe es nun so aber so ist auch nichts:
while(true)
{
//for(x=4;x<25;x++)
//{
x=7;
servo1(x);
servo2(x);
//batpower();
//setCursorPosLCD(1,1);
//writeIntegerLCD(x,DEC);
//mSleep(550);
//}
//clearLCD();
}
der rest ist unverändert.
wie setzte ich diese denn auf ausgang mache ich das nicht schon mit den befehlen in den servo funktionen?
-
Mit:
DDRC |= IO_PC4;
DDRC |= IO_PC6;
... im Hauptprogramm (also VOR der while(true)-Schleife)!
-
danke das wars wie konnte ich das vergessen habe es im alten programm auch nun gehts danke an alle!
-
Das ist gut :)
Ich habe die HS 5645mg digital Servos von Hitec. Wenn der sein PWM Puls (einmalig) korrekt errechnet hat, dann bleibt er darauf stehen auch wenn man nichts mehr an ihn sendet.
Solange er anfänglich nichts korrektes erhalten hat, bleibt er kraftlos - auch unter Spannung.
Viel Spaß und Gruß
-
Hallo nochmal
Jetzt reagieren die servos schonmal und nun will ich herausfinden welchen stellbereich ich fahren kann. ich mache es so:
for(x=3;x<25;x++)
{
servo1(x);
mSleep(400);
}
aber er reagiert nicht korrekt nur ca. 5 positionen und die sind nicht immer mit den gleichen zahlen ich weiß auch nicht. es wirkt als wäre die batterie leer aber die sind frisch geladen und wenn wieder x=3 ist dann fährt er schnell und sauber zurück.
-
Woher bekommt der Servo denn seine Positionsangabe her?
-wenn Du mir sagen kannst, welcher Teil vom Programm den Wert produziert. Dann wette ich mit Dir, fällt es Dir auch auf. Kleiner Tipp: Es ist unpraktisch den Positionswert in einer Schleife hochzählen zu lassen, da man dann ja nicht sieht wo der Servo aufhört auf die Werte zu reagieren (Min/Max).
Du solltest wohl erstmal den "neutral-Wert" finden.
Was passiert wenn Du in der Schleife den x-wert bei Servo1 z.B. "fest" auf 11 setzt?
Hinweis: wenn der Servo ständig gegen seine Max- und Min-Position fährt kann er beschädigt werden - denke das gilt auch noch für Digitale. Also achte darauf was der Servo macht wenn Du die Änderungen vornimmst.
Kann es sein das der Schleifenzähler gleichzeitig die Position vom Servo sein soll? - müsste der nicht seperat gehalten werden. Also eine entweder es ist eine Lokale Variable, dann mag das gehen; oder eine Globale - dann müßte sie doch einen eigenen Namen tragen, oder nicht?
-
der code der schleife sieht so aus:
void servo1(int pos)//rechter Servo
{
PORTC |= IO_PC4;
sleep(pos);
PORTC &= ~IO_PC4;
sleep(50-pos);
}
while(true)
{
for(x=4;x<21;x++)
{
servo1(x);
setCursorPosLCD(1,1);
writeIntegerLCD(x,DEC);
mSleep(750);
}
clearLCD();
}
ich lasse mir es ja anzeigen und deswegen weis ich genau welche zahl ich den linken und rechten servoanschlag hat.
ja x wird ja hochgezählt und als stellwert übergeben. somit stellt er sich alle 750ms um und er sollte sich bewegen.