Hallo alle zusammen, ich habe gerade ein kleines Projekt am laufen, und zwar baue ich einen Roboterarm mit Servomotoren. Die Ansteuerung erfolgt über einen Pic 18F4580. Ich bin was Microcontroller betrifft noch ein Anfänger. Die Ansteuerung in prog #1 funktioniert eigentlich, ich bin aber auf ein Problem gestoßen. Das liegt darin, dass der Servo die vorgegebenen Positionen zwar anfährt, aber jedoch keinerlei Halt- und Stellkraft hat. Zu testzwecken habe ich ein programm #2 geschrieben, indem die servos über das Auslesen eines potiwertes angesteuert werden (wie bei der fernbedienung). Bei dieser variante hat der servo eine enorme kraft so wie es sein sollte. Warum hat er diese nicht auch in programm #1 ? und kann ich die stellgeschwindigkeit beeinflussen, und wenn ja wie? ich zeige euch hier mal die 2 programme. Prog #1: Ansteuerung über ziffernblock (jede ziffer hat eine vorgegebene servostellung) void servo_1_links (void) { Output_high (pin_C5); delay_us(2000); Output_low (pin_C5); delay_us(18000); } void servo_1_mitte (void) { Output_high (pin_C5); delay_us(1750); Output_low (pin_C5); delay_us(18000); } void servo_1_rechts (void) { Output_high (pin_C5); delay_us(1500); Output_low (pin_C5); delay_us(18000); } void main(void) { while (true) { taste = keypad(taste); switch(taste) { case 1: servo_1_links(); break; case 2: servo_1_mitte(); break; case 3: servo_1_rechts(); break; } // delay_ms(100); (funktioniert auch mit verweilzeit nicht) } } ___________________________________________ Prog #2: Ansteuern über ausgelesenen potiwert (ad wandlung eines poties welcher auf der platine sitzt ) void ADC (void) { setup_adc_ports(PIN_a0); //ADC-Pin analog input set_adc_channel(0); //Kanalauswahl delay_us(10); //Hier Zeitverzögerung! AD_Wert=read_adc(); //Wandlungsergebnis holen... setup_adc_ports(NO_ANALOGS); //Alle Eingänge digital } void main(void) { lcd_init(); setup_adc(ADC_CLOCK_INTERNAL); while (true) { ADc(); // fkt aufruf adc x=_mul(ad_wert, 6); // eigentliche multifakt. 5,4078 y=x+800; // add 800 Output_high (pin_c5); delay_us(y); // var positionierung Output_low (pin_C5); delay_us(18000); } } Ich hoffe die schilderung meines problems ist verständlich… wäre sehr dankbar wenn mir hierbei jemand weiterhelfen könnte, vielen dank schonmal im voraus
Bei Version2 wird immer pin_C5 getoggelt, bei der ersten Version halt nur wenn du ne Taste drückst. Wenn du da noch einen ansonsten Fall, nämlich falls kein Button gedrückt = tue dass..., dann sollte es funzen. Ob man das generell so machen sollte, wage ich mal zu bezweifeln... Gruß Jonas
taste = keypad(taste); switch(taste) { case 1: servo_1_links(); break; case 2: servo_1_mitte(); break; case 3: servo_1_rechts(); break; } Wenn taste keinem deiner case entspricht wird auch keine deiner Funktionen aufgerufen. Sprich: Der Servo bekommt kein Signal.
@ Jonas erstmal danke für deine antwort, aber wenn wie in prog 2 eine taste gedrückt wird hängt er die ganze zeit in der schleife für die jeweilige position bis etwas anderes gedrückt wird, oder liege ich da falsch ? wie würdest du das generell machen ?
@ holger "Wenn taste keinem deiner case entspricht wird auch keine deiner Funktionen aufgerufen. Sprich: Der Servo bekommt kein Signal." --> der case trift ein wenn ich die entsprechende taste drücke
Holger hat das gleiche gemeint wie ich. Um dir wirklich helfen zu können, müsstest du mal mal näher beschreiben, was du genau vorhast. Meine Glaskugel ist kaputt. Also in etwa so, ich hab ein Tastaturfeld, ich hab x Servos die ich über m/eine Software-delay-Geraffel PWM ansteuern will... Gruß Jonas
>--> der case trift ein wenn ich die entsprechende taste drücke
Sicher, aber hältst du sie dann auch fest?
Bist du sicher das taste beim festhalten auch weiter
einen Wert liefert der für deine case zutrifft?
Was passiert wenn du das machst:
Am Anfang von main diese Variable definieren:
unsigned int position = 1750;
1 | taste = keypad(taste); |
2 | switch(taste) |
3 | {
|
4 | case 1: position = 2000; break; |
5 | case 2: position = 1750; break; |
6 | case 3: position = 1500; break; |
7 | }
|
8 | |
9 | Output_high (pin_C5); |
10 | delay_us(position); |
11 | Output_low (pin_C5); |
12 | delay_us(18000); |
also ich baue einen 5-achsigen roboterarm der vorgegebene positionen anfahren soll. das heißt ich muss 5 sevos gleichzeitigt ansteuern. die positionen werden zwar angefahren ,aber die motoren haben keine kraft. wenn ich die jeweilige taste gedrückt halte ändert das nicht.. @ holger ich werde deine variante gleich mal testen für die anderen motoren benutze ich dann einfach weitere vaiablen- wie position 2, 3 , 4...wenn ich das richtig verstanden habe
> das heißt ich muss 5 sevos gleichzeitigt ansteuern.
Das gibt ein Problem mit deinen delay_us Aufrufen zur PWM Erzeugung.
Wenn du die gleichzeitig generieren willst, klappt das mit deiner
Programmierung nicht. Such mal in deinem Mikrocontroller Handbuch nach
Timer und PWM. Meist kann man mit dem Timer auch eine PWM erzeugen und
das auf mehreren Pins gleichzeitig. Dann musst du die Timertopwerte
(erklärt sich, wenn du das Handbuch liest) nur noch pro Taster mit
passenden Werten neu laden und voila ;)
Gruß Jonas
• One Capture/Compare/PWM (CCP) module • Enhanced Capture/Compare/PWM (ECCP) module (40/44-pin devices only): - One, two or four PWM outputs - Selectable polarity - Programmable dead time - Auto -shutdownandauto-restart Auszug aus dem Datenblatt deines Controllers, da gibt es also definitiv PWM-Hardware. Nun also damit beschäftigen, hoffentlich habt ihr die richtigen Pins geroutet (wahrscheinlich nicht ?! ;) )... Gruß Jonas
>@ holger ich werde deine variante gleich mal testen > für die anderen motoren benutze ich dann einfach weitere vaiablen- wie >position 2, 3 , 4...wenn ich das richtig verstanden habe Die wird nur mit einem Servo funktionieren. Also nimm auch erstmal nur einen Servo. Ansonsten siehe die Antworten von Jonas. Mit den Delays wird das nix bei fünf Servos.
@ holger ich habe deine variante mit einem servo getestet. das verhalten des motors ist leider das selbe wie in meinem programm. ich denke es liegt wohl wirklich daran dass die tasten nicht weiterhin werte liefern nach ein oder mehrmaligem drücken.. @jonas also mit pwm habe ich noch nie etwas gemacht, aber werde mich da reinarbeiten und das mal testen _____ leute ich danke euch dass ihr euch die zeit genommen habt mir zu helfen. ich werde euch auf dem laufenden halten :)
Schonmal in die Codesammlung geschaut? Beitrag "Servo Ansteuerung in C mit Timer0" Sieht ganz vielversprechend aus. Nochne Möglichkeit ist ein Baustein wie der Tlc5940 der kann PWM auf 16 Kanälen und wird ganz einfach über SPI gefüttert.
Hallo Daniel, ich habe eine Spinne mit 12 Servos gebaut. Diese wurden von 2 Pics (je 6 pro pic) auch mit "Delay-Anweisungen" gesteuert und hat gut geklappt, allerdings musst Du das Programm etwas anders aufbauen. meine Lösung: (Sinnfreies Beispiel für 3 servos) position_servo1=150; // diesen positonswert änderst du mit den tasten position_servo2=160; position_servo3=170; start Output_high (pin_C1); //servo1 Output_high (pin_C2); //servo2 Output_high (pin_C3); //servo3 for schleife = 1 to 200 if schleife == position_servo1 Output_low (pin_C1); //servo1 if schleife == position_servo2 Output_low (pin_C1); //servo2 if schleife == position_servo3 Output_low (pin_C1); //servo3 next delay_us(18000); // hier kannst du zB die Tastenabfrage reinpacken goto start; ACHTUNG, die Positonswerte entsprechen nicht mehr einer fixen Zeit sondern sind von der dauer der schleife abhängig. Das heisst entweder berechnen oder try und error, letzteres geht ziemlich gut. Ausserden verlierts du etwas an Auflösung, das war in meinem Fall irrelevant. Ich hoffe das war einigemassen verständlich, sonst bei interesse nachhaken. Viel Erfolg
Das ist mit 5 Servos nicht so einfach. Du brauchst die ganze Zeit über Impulse ohne Jitter. - Ohne Impulse bekommst du dein Problem. - Ungleichmäßige Impulse -> Die Servos summen und die Batterie ist sofort leer. Für 2 Servos gibt es eine trickreiche Routine mit dem Timer im Compere-Mode (PWM Mode hat zu wenig Auflösung). Bei 5 musst du aber die Pins in der ISR setzen. Im Prinzip kannst du die Strategie von Martin Haag mit einem Timer im Compare-Modus umsetzen. Im High-Priority Interrupt. Damit der Jitter klein bleibt, muss aber alles andere Low-Priority laufen.
>also mit pwm habe ich noch nie etwas gemacht, aber werde mich da >reinarbeiten >und das mal testen Das sehe ich anders, immerhin haste du ja schon eine implementiert, dass war dir nur nicht klar :) : >Output_high (pin_C5); >delay_us(2000); >Output_low (pin_C5); >delay_us(18000); Nur das ganze kann auch die Hardware für dich machen, aber da liest du dich ja bestimmt gerade ein... Gruß Jonas
Ich halte eine Ansteuerung von mehr als 2 Servos ohne Timer grundsätzlich für problematisch bzw. einfach inkorrekt. Die Delays sind so und so eine fragwürdige Sache und können sinnvoll eigentlich nur in Initialisierungsroutinen verwendet werden, während weder Benutzer noch Sensorik / Regelungstechnik einen Einfluss auf den Programmablauf hat. Beispiel: Initialisierung eines Displays beim Einschalten eines Gerätes. Ansonsten blockieren die Delays ja entweder Alles oder sie sind (weil Interrupts zugelassen werden) nicht zeitlich konstant. Darum gibt es eine geniale Erfindung und die nennt sich Timer + Interrupt. Auch wenn es einem als Anfänger schwer fällt sich in dem Gewirr zu Recht zu finden, sollte man DRINGENDST diese Thematik beherrschen. Dazu empfehle ich als Einstieg: http://www.sprut.de/electronic/pic/grund/timer/timer.htm Danach kann man einen Blick ins Datenblatt werfen und damit dann auch die Blockschaltbilder der Timer-Module verstehen. Zur Servospezifischen Ansteuerung empfehle ich diesen Artikel (gesamt für Grundlagen), ganz besonders aber diesen Abschnitt: http://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung#Signalerzeugung_f.C3.BCr_mehrere_Servos_mittels_Timer_.28C.29 Die Register heißen ein wenig anderst aber von der Methodik alles gleich ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.