Servo Ansteuerung

OP #340762
Lesenswert?

Hallo!

Ich habe hier eine Servo routine, die nicht funktionieren will...

Es sind schon ein paar unnötige Sachen darin enthalten, die noch nicht
verwendet werden. Diese sollten nicht beachtet werden.

Im Programm solll ein Signal von 1ms erstellt werden um den Servo in
die gewünschte Position zu bringen. Kann mir jemand sagen was daran
falsch ist?

Mfg Xenon
Angehängte Dateien:
#340763
Lesenswert?

http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html

Ist zwar für Mega48 (im Auslieferungszustand, also mit 1MHz),
funktioniert aber. Lässt sich auch leicht umrüsten, indem man die
Positionswerte nicht vom ADC nimmt, sondern aus einem Feld im SRAM, wo
sie von irgendeiner Routine bereitgestellt werden können.

Dein Programm kann ich auf die Schnelle nicht bis ins Detail
nachvollziehen, da ich in der ISR und bei der Variablendeklaration
keine Kommentare finde.

...
Gast #340764
Lesenswert?

Ich habe das noch mal ein bischen gekürzt. Jetzt müsste es sehr einfach
zu verstehen sein. Nur leider funktioniert es einfach nicht. Der Timer
soll alle 100us dein Interrupt aufrufen. Ist alles richtig eingestellt?
Gast #340766
Lesenswert?

100µs sind ja ne richtig grosse Auflösung... ganze 10 Schritte...
Das einfachste ist doch, den Timer im CTC-Mode zu betreiben, beim
OVF-Interrupt den Port-Pin zu setzten und beim OC-Interrupt ihn wieder
zu löschen. Alles andere ist für mich nur noch wirr (oder God-Stuff by
Hannes).
#340767
Lesenswert?

Da haste wohl Recht:-)
Trotzdem ein paar Fehler, die mir auf den 1.Blick auffallen:
ldi temp, 0b00000010         ; Timer0 Interrupt aktivieren
   out TIMSK, temp
//Timer0-OV-Enable liegt beim Mega8 auf Bit0!
   ldi temp, start              ; Startwert des Timers
   out TCNT0, temp

   ldi temp, 0b00000010         ; Prescaler auf 8
   out TCCR1B, temp
//Timer0 wird mit TCCR0 gesteuert

Du mischst wild Timer0 und 1, sieht mir schwer nach Copy und Paste aus,
ohne zu verstehen, was du da machst.
Ausserdem: nimm symbolische Adressen, da sieht man die Fehler besser
:-)
ldi temp, 1<<TOIE0
out TIMSK, temp

Jetzt holt sich der Assembler aus der selbst den richtigen Wert.
Gast #340770
Lesenswert?

Noch was vergessen: In der OVF-ISR wird auch der neue Capture-Wert
gesetzt (falls er sich geändert haben sollte).
Dann hat man bei 1MHz-Taktfreqeunz 1000-2000 Takte Zeit, irgendwas
anderes zu machen.
Diese Methode erfordert zwar jeweils 2Byte pro Capture-Wert, sollte
aber besser funktionieren...

Timerdurcheinandergeschmeisse sollte man natürlich auch vermeiden.
Gast #340771
Lesenswert?

@crazay_horse Also copy und paste war das nur halb. Ich habe eine
aufwändige Servoansteuerung im Internet gesehen, aber da ich immer
alles selber verstehen will hab ich erstma die Hälfte gelöscht und mit
einem Servo angefangen.

Das heißt nich, dass ich es nicht verstehe. Timer0 mit Timer1 zu
vertauschen hat wohl kaum etwas mit Verständnis zu tun. Und wenn man
dann tatsächlich mal Probleme hat, ist ein Forum da. Oder siehst du das
anders??
Gast #340775
Lesenswert?

Im AVR Studio habe ich es gerade laufen lassen, aber wie soll ich denn
dort einen Fehler entdecken(schließlich wird portb,0 im ms Bereich
umgestellt...).

Zwischen Kritik und zu sagen, dass ich nicht wisse was ich mache, weil
ich ein paar dumme Fehler drin habe, ist wohl noch ein Unterschied.

Gegen Kritik und konstruktive Kommentare habe ich selbstverständlich
nichts.

Mfg Xenon
#340776
Lesenswert?

1. Läuft dein Programm im Simulator weeeeesentlich langsamer
   als am realen Prozessor. ms ist da mit Sicherheit nicht.

2. Solltest du dir mal deine Werkzeuge genauer anschauen.
   Im Simulator kann man Breakpoints setzen (die Simulation
   hält an, wenn sie auf einen Breakpoint trifft), man
   kann 'single-steppen' (nur einen, eben den nächsten
   Befehl abarbeiten lassen), und man kann nach so einem
   single-step sich die Register Werte anschauen und überlegen
   (solange wie man möchte) ob der Register Wert so sein soll
   wie er ist, oder nicht.
#340777
Lesenswert?

Die Zeile

 sbi portb,0

im Block "comp1" wird nie erreicht, da cnt1 an dieser Stelle nie den
Wert 0 erreicht. Denn du setzt zwar im Block "comp3" cnt1 auf 0,
erhöhst es dann aber im Block "restart". Somit ist cnt1 beim nächsten
Aufruf der ISR schon wieder 1...

Wenn ich im Block "comp1"

 ldi temp,0

durch

 ldi temp,1

ersetze, dann bekomme ich laut Simulator von AVR-Studio4 eine
Impulsdauer von 0,937ms und eine Impulspause von 20,9ms.

Ja, mit dem Simulator kann man diese Zeiten exakt messen, auch wenn sie
im Millisekunden- oder gar Nanosekunden-Bereich liegen. Dazu setzt man
sich Haltepunkte und löscht nach jedem Halt die "Stop Watch"-Anzeige
durch Doppelklick auf den Wert. Siehe Screenshoot im Anhang...

Dass ich den Servoimpuls nicht auf diese Art generieren würde, hast du
vermutlich bereits gesehen, falls du den Link weiter oben verfolgt hast
und meine Servoimpulserzeugung mit der Compare-Unit des Timer1
analysiert hast. Die läuft übrigens auch mit dem Mega8, ich nahm den
Mega48 wegen Preis und Stromverbrauch im Sleep. Es müssten vermutlich
nur die Int-Vektoren und einige Zugriffe auf Extended-I/O angepasst
werden. Aber du willst ja nicht abkupfern, sondern verstehen...

...
Angehängte Dateien:
Gast #340778
Lesenswert?

Hi!

Also das Programm hat jetzt endlich funktioniert und der Servo bewegt
sich wie gewünscht!

@HanneS Ich wollte nur erstmal, dass mein Code funktioniert. Nun werde
ich mich ausführlich Deinem zuwenden und ihn dann vielleicht auch
verwenden. Danke für die Hilfe! Ich war gerade dabei das ganze Studio
zu entdecken aber mir ist einfach nicht aufgefallen, dass der pin gar
nicht mehr auf High gesetzt wird... Wirklich dumm von mir.

So jetzt weiß ich wie viel man mit dem AVR Studio machen kann und ich
werde es in Zukunft erstmal damit probieren, bevor ich hier einen
Thread eröffne.

Allen vielen Dank für die Hilfe!!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren