Hey Leute, im Rahmen eines Schulprojekts übertragen wir das Bewegungskonzept von Sechsfüßer auf ein technisches Modell. Wahrscheinlich sind andere ähnliche Projekte als "Hexapod" unter euch bekannt ;) Die Entwicklungsumgebung: WinAVR, PonyProg. Die Hardware: Pollin Evaluationsboard, ATMega32. Benutzt werden 18 Servos, die einzeln ansteuerbar sind. D.H es werden 18 PWM's benötigt. Die Ansteuerung der Servos und die erstellung der Soft PWM's klappt soweit. PROBLEM: Da außer den PWM's auch noch die bewegungsmodis über den µC gesteuert werden soll, suchen wir nun verzweifelt nach einer Möglichkeit, die PWM's praktisch "parallel" neben dem Hauptprogramm ablaufen zu lassen. Mir ist durchaus bewusst, dass der µC natürlich keine befehle wirklich parallel ausführen kann, Ich hoffe unser problem ist trotzdem deutlich geworden und ihr wisst, worauf ich hinaus will. Es gab erste ansätze mit der DWORD WINAPI Thread Funktion. Jedoch funktionierte diese nur unter windows und ließ sich unter WinAVR (auch nach dem kopieren der entsprechenden libraries) nicht compillieren. Ist es möglich diese Funktion auf einem µC auszuführen?? Auch andere Lösungsvorschläge sind herzlich wilkommen ! Danke schonmal im Vorraus!
Wenn aus dem PWM-Signal eh eine Gleichspannung erzeut wird könnte man vielleicht auch Digital/Analogwandler mit SPI oder anderen Schnittstellen verwenden. Also Bausteine bis 16 Kanälen habe ich schon gesehen. Vielleicht gibt es noch größere oder man nimmt 2.
Danke für die schnellen Antworten ! Der Multitasking Thread hört sich schonmal verdammt gut an ;9
ado schrieb: > Wenn aus dem PWM-Signal eh eine Gleichspannung erzeut wird könnte man > vielleicht auch Digital/Analogwandler mit SPI oder anderen > Schnittstellen verwenden. Es geht nicht um wirkliches PWM, Marv will Servos ansteuern, er nennt das nur PWM. MfG Klaus
Hi Marv, ich habe gerade ein Projekt mit AVR und Servo fertiggestellt. In welcher Auflösung (Stufen) willst Du denn die Servobewegung steuern ? Dirk
Gibt es nicht auch Portexpander (glaub für LEDs) die jeden Kanal einzeln mit einer PWM ansteuern können? Soweit ich weis ist bei denen die Frequenz (hier dann 50Hz) und das Tastverhältnis für jeden Kanal einzeln einstellbar. Bei 10 Bit wär dass immerhin eine Auflösung von 20ms/1024= 19,5us. Müssten dann so um die 50-60 Positionen sein die man einstellen kann. Vorteil: Einfach über SPI/I2C anzusteuern und der uC hatt außer die neuen Werte über SPI zu senden nichts zu tun. Grüße N.Müller
Vielleicht hift Dir dieses Programmbeispiel, viele PWM-Kanäle zu realisieren. Falls nicht alle 64 Kanäle gebraucht werden, bleibt mehr Zeit für die Verarbeitung anderer Programmteile. http://www.mino-elektronik.de/AVR_PWM_64/AVR_PWM_64.htm
Marv schrieb: > Danke für die schnellen Antworten ! Der Multitasking Thread hört sich > schonmal verdammt gut an ;9 Multitasking halt ich für übertrieben, schau dir mal den Link zur Ansteuerung an. Mit einem Timer lassen sich bequem 8 Servos ansteuern. Mit z.B. 3 Timern lassen sich dann alle 18 (eigentlich schon 24) Servos ansteuern. Der Trick dabei ist, dass die 8 benötigten Pulse über die Periodendauer verteilt sind, um die Prozessorzeit zu minimieren.
Floh schrieb: > Multitasking halt ich für übertrieben, schau dir mal den Link zur > Ansteuerung an. Mit einem Timer lassen sich bequem 8 Servos ansteuern. > Mit z.B. 3 Timern lassen sich dann alle 18 (eigentlich schon 24) Servos > ansteuern. Es reicht ein einzigster Timer und eine intelligente Programmierung um die benötigten 18 Pulsweiten zu erzeugen, welche auch stabil sein sollten. Eine Servo Ansteuerung lässt sich nicht ohne weiteres mit einer normalen PWM Steuerung verleichen. Man benötigt eine minimale Pulslänge von ca. 1 ms um den Servo in seiner 0 Referenzposition zu halten. Die nächste ms (zur Erweiterung der 1.) muss in Stufen geteilt werden um den Servo um ca. 90° zu bewegen. Dir Wiederholung dieses Vorganges beträgt 20ms. Mit einer entsprechend intelligenten Ansteuerung (Software) kommt ein relativ geringer Softwareaufwand zustande.
Dirk schrieb: > Es reicht ein einzigster Timer und eine intelligente Programmierung um > die benötigten 18 Pulsweiten zu erzeugen, welche auch stabil sein > sollten. Geile Idee. Also in etwa so (für gedachte 8ms Periodendauer ,da mir hier die Breite fehlt :-) 0 1 2 3 4 5 6 7 8 Zeit | | | | | | | | | | (je 1 ms) S1 PPPPPP--------------------------PPPPPPP-- S2 ----PPPPP------------------------------PP S3 --------PPPPPPP-------------------------- S4 ------------PPPPPPP---------------------- ... Dann skaliert man z.B. einen Timeroverflow auf 1ms. Zusätzlich hat man nen Output Compare-Interrupt. Bei Timeroverflow wird immer Serv0(n) angeschaltet und gleichzeitig der Output-Compare-Wert von Servo(n-1) genommen. Bei Output-Compare-Interrupt wird dann Servo(n-1) ausgeschaltet. Ja so kriegt man elegant 18 Servos in eine 20ms Periode. :-)
Floh schrieb: > Der Trick dabei ist, dass die 8 benötigten Pulse über die Periodendauer > verteilt sind, um die Prozessorzeit zu minimieren. Üblicherweise wird das auch als Zeitmultiplex bezeichnet, d.h. innerhalb der Periodendauer gibt es für jeden Servo ein 2ms Zeitfenster, in dem sein Puls erzeugt wird Dirk schrieb: > Dir Wiederholung dieses Vorganges beträgt 20ms. Als Wiederholung (Periode) werden zwar oft 20ms verwendet, aber den Servos ist der genaue Wert ziemlich wurscht. Irgendwas zwischen 10 ms und mindestens 100 ms funktioniert eigentilich immer. Einziger Effekt einer langen Periodendauer ist, dass die Servos etwas langsamer umsteuern. Es kommt auf einen Versuch drauf an, ob es für den Hexapod ok ist, alle 18 Servopulse auf eine als Zeitmultiplex erzeugte Serie zu packen. Die Chancen sind gut.
Matthias schrieb: > Als Wiederholung (Periode) werden zwar oft 20ms verwendet, aber den > Servos ist der genaue Wert ziemlich wurscht. Irgendwas zwischen 10 ms > und mindestens 100 ms funktioniert eigentilich immer. Einziger Effekt > einer langen Periodendauer ist, dass die Servos etwas langsamer > umsteuern. Genau in der Reaktionsgeschwindigkeit liegt denke ich hier die Anforderung. 100ms wären da wohl eindeutig zu langsam. Nicht zu vergessen ist, dass preiswerte Servos per PWM offset und aktiver Pulslänge evtl. kalibriert werden müssen, um zu verhinder, dass der HEXAPOD in Schräglage durch die Welt läuft.
Dirk schrieb: > Genau in der Reaktionsgeschwindigkeit liegt denke ich hier die > Anforderung. > 100ms wären da wohl eindeutig zu langsam. Die 100ms sind ein Wert, bei dem sich bei mir noch kein Servo beschwert hat. Mit 18 Servos á 2 ms wäre man bei 36 ms mit der Option, auch noch Pausen aus dem Signal rauszukürzen, falls nicht gerade alle in der 2 ms-Stellung stehen. Reaktionsgeschindigkeit ist nicht das Problem. Und fast 28 Positionskommandos pro Sekunde an jeden Servo sollte wohl noch kein Engpaß sein. Dirk schrieb: > Nicht zu vergessen ist, dass preiswerte Servos per PWM offset und > aktiver Pulslänge evtl. kalibriert werden müssen, um zu verhinder, dass > der HEXAPOD in Schräglage durch die Welt läuft. Ja und? Warum soll man das nicht wie gewohnt machen können? Die Signale werden einzig und alleine zeitlich verschachtelt, wie beim Summensignal einer Funkfernsteuerung.
Das mit der periodendauer seh ich wie von euch beschrieben nicht so eng. test haben ergeben dass die servos noch bei einer pause von 5-50ms zwischen den pulsen sauber fahren. Auch unterschiedliche pausen machen nichts aus. Zum test haben wir mal alle servos nacheinander angesteuert, so ergaben sich pausenzeiten von min.: 17*0,8 = 13,6ms und max.: 17*2,2 = 37,4ms. Die Servos liefen problemlos. Außer der herangehensweise vom multitasking sind mir die funktionsprinzipe der anderen beschriebenen herangehensweisen noch unklar. Zum testen wurden bisher nur delays eingesetzt. Wir sind aber gerade daran alles mit Timern umzusetzen. mfG Marv
> die PWM's praktisch "parallel" neben dem Hauptprogramm > ablaufen zu lassen. Ach was. Das sind Servos. Deren Ansteuersignal nennt man übrigens PCM pulse code modulation. Es werden nicht alle Impulse gleichzeitig gesendet, weil man nicht will, daß alle Servos gleichzeitig Strom ziehen, sondern nacheinander. Das geht problemlos, weil ein Servo auch erst in ca. 25msec seinen nächsten Impuls sehen will. Servo1 --XXX-----------------XXX---- Servo2 -----XX------------------XX-- Servo3 -------XXXX----------------XX... Servo4 -----------XXX--------------- Wenn man das in Form einer Interrupt-Routine machen will, kann diese einfach jedesmal den "nächsten" Zeitwert setzen. Also pseudocodemässig in der Art: int servoduration[19]; interrupt timer(void) { static int servo=0; PORT[servo]=0; // letzten Puls zurücknehmen TIMER=servoduration[servo]; // neue Zeit bis zum nächsten Interrupt setzen servo++; if(servo>=19) servo=0; PORT[servo]=1; // Puls auslösen } Es spielt dabei keine so grosse Rolle, daß die Pausenzeiten von den Pulslängen der anderen Servos abhängen.
Ist jemandem aufgefallen, dass Servos unter Last Schnattern ? Die Schnatterfrequenz ist die Updaterate, bei 20ms also 50Hz.
Danke erstmal für die vielen Antworten! Es sind allerdings neue Probleme aufgetaucht. Aus uns unerklärlichen gründen ist es nicht möglich Timer0 im CTC Modus zu betreiben. Normaler Timerbetrieb funktioniert soweit. Nachdem unser programm nicht kompillierbar war, haben wir alle fremdfaktoren entfernt, den fehler allerding nicht gefunden. Also: dieser fertige Code versucht zu kompillieren:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | int main(void) |
5 | {
|
6 | // Timer 0 konfigurieren
|
7 | TCCR0A = (1<<WGM01); // CTC Modus |
8 | TCCR0B |= (1<<CS01); // Prescaler 8 |
9 | // ((1000000/8)/1000) = 125
|
10 | OCR0A = 125-1; |
11 | |
12 | // Compare Interrupt erlauben
|
13 | TIMSK |= (1<<OCIE0A); |
14 | |
15 | // Global Interrupts aktivieren
|
16 | sei(); |
17 | |
18 | while(1) |
19 | {
|
20 | /*Hier kann die aktuelle Zeit
|
21 | ausgeben werden*/
|
22 | }
|
23 | }
|
24 | |
25 | |
26 | |
27 | ISR (TIMER0_COMPA_vect) |
28 | {
|
29 | |
30 | }
|
ABER: Wir bekommen nur ein Fehlercode. Hat jemand einen Tipp für uns, was wir übersehen haben ?
1 | Compiling C: main.c |
2 | avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -MMD -MP -MF .dep/main.o.d main.c -o main.o |
3 | main.c: In function 'main': |
4 | main.c:7: error: 'TCCR0A' undeclared (first use in this function) |
5 | main.c:7: error: (Each undeclared identifier is reported only once |
6 | main.c:7: error: for each function it appears in.) |
7 | main.c:8: error: 'TCCR0B' undeclared (first use in this function) |
8 | main.c:10: error: 'OCR0A' undeclared (first use in this function) |
9 | main.c:13: error: 'OCIE0A' undeclared (first use in this function) |
10 | main.c: At top level: |
11 | main.c:27: warning: 'TIMER0_COMPA_vect' appears to be a misspelled signal handler |
12 | make.exe: *** [main.o] Error 1 |
13 | |
14 | > Process Exit Code: 2 |
15 | > Time Taken: 00:01 |
>Deren Ansteuersignal nennt man übrigens PCM pulse code modulation.
nein. PPM PCM ist nur bei moderneren funken zwischen sender und
empfänger.
Wenn euch irgenwann bei eurem hexapod die Portpins zuneige gehen, könnt
ihr mit einem 4017 mit 2 portpins 8 servos ansteuern. alles was der
braucht ist das summensignal und sein sync signal. So in der ausführung
millionenfach in modellbauempfängern bewährt
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.