Hi,
ich verzweifle gerade, ich finde den Tipp- oder Denkfehler nicht.
ATMega32 klappert auf 16MHz, angeschlossen ist ein RC-Empfänger dessen
Signale korrekt eingelesen werden. Das sind 5 Eingänge am AT-Mega, die
alle 20ms nacheinander 1-2ms high sind.
Also 5-10ms kann das dauern. Das funzt soweit perfekt.
Die Werte des ersten Kanals liegen in den Variablen Esc, Servo1, Servo2
usw.
(Integer mit Vorzeichen) mit 0,5µs/Lsb, also im Bereich von 2000-3000.
Das funktioniert wie gesagt.
Ich bin nun an das 20ms-Raster gebunden und will wieder 5 solche Signale
ausgeben, nur daß die dann später wild mit Sensoren verrechnet und
gemischt werden sollen.
Das gesamte Programm ist schon recht umfangreich (die Sensoren auslesen,
je 3 Achsen Gyro, Beschleunigung und Magnetfeld), was auch alles
funktioniert aber erstmal wieder deaktiviert ist.
Jetzt will ich die Ausgabe der 5 Kanäle (auf Escout, Servo1out usw.)
quasi parallel machen aber das will nicht. Die Ausgänge gehen auf high
und das war's.
Hier die Gosub die nicht will:
1
Rc_out:
2
3
Escout = 1
4
Servo1out = 1
5
Servo2out = 1
6
Servo3out = 1
7
Servo4out = 1
8
9
Start Timer1
10
Timer1 = 0
11
Rc_out_counter = 0
12
Do
13
If Timer1 >= Esc Then Escout = 0 : Rc_out_counter.0 = 1
14
If Timer1 >= Servo1 Then Servo1out = 0 : Rc_out_counter.1 = 1
15
If Timer1 >= Servo2 Then Servo2out = 0 : Rc_out_counter.2 = 1
16
If Timer1 >= Servo3 Then Servo3out = 0 : Rc_out_counter.3 = 1
17
If Timer1 >= Servo4 Then Servo4out = 0 : Rc_out_counter.4 = 1
18
Loop Until Rc_out_counter = &B00011111
19
20
'(
21
Timer1 = 0
22
Escout = 1
23
Do
24
Loop Until Timer1 >= Esc
25
Escout = 0
26
27
Timer1 = 0
28
Servo1out = 1
29
Do
30
Loop Until Timer1 >= Servo1
31
Servo1out = 0
32
33
Timer1 = 0
34
Servo2out = 1
35
Do
36
Loop Until Timer1 >= Servo2
37
Servo2out = 0
38
39
Timer1 = 0
40
Servo3out = 1
41
Do
42
Loop Until Timer1 >= Servo3
43
Servo3out = 0
44
45
Timer1 = 0
46
Servo4out = 1
47
Do
48
Loop Until Timer1 >= Servo4
49
Servo4out = 0
50
')
51
Return
Der auskommentierte zweite Teil (nach dem "Loop Until Rc_out_counter =
&B00011111" ) funktioniert bestens!
Der erste Teil sollte das gleiche machen aber eben schneller.
Wo ist da der Fehler?
Rc_out_counter ist ein Byte und wird nirgendwo anders im Programm
angefasst.
Es sind auch ansonsten keine Interrupts aktiv und Timer1 klappert so
einfach mit 2MHz vor sich hin. Funktioniert ja auch mit dem 2. Teil.
Verdammte Axt, das ist so banal, daß es mir fast peinlich ist aber ich
sehe den Fehler einfach nicht
Daher möchte jetzt gerne den Publikumsjoker einsetzen.
Gruß,
Norbert
Norbert S. schrieb:> Do> If Timer1 >= Esc Then Escout = 0 : Rc_out_counter.0 = 1> If Timer1 >= Servo1 Then Servo1out = 0 : Rc_out_counter.1 = 1> If Timer1 >= Servo2 Then Servo2out = 0 : Rc_out_counter.2 = 1> If Timer1 >= Servo3 Then Servo3out = 0 : Rc_out_counter.3 = 1> If Timer1 >= Servo4 Then Servo4out = 0 : Rc_out_counter.4 = 1> Loop Until Rc_out_counter = &B00011111
der Fehler ist ganz einfach:
dir fehlern ca. 10 Klammern....das RC_out_counter.x wird immer beim
ersten durchlauf ausgeführt....es ist nicht an die If-Abfragen
gekoppelt.
Gruß ich
Es ist keine gute Idee, den Zählerstand eines relativ schnell laufenden
Timers per Software zu vergleichen. Dafür hat der Timer programmierbare
Compare-Einheiten in Hardware, die im Hintergrund arbeiten und bei
Erreichen des Vergleichswertes einen Interrupt auslösen. Also (durch
Addition) Timerstand berechnen, bei dem der nächste Impulswechsel
stattfinden soll, den in OCR1A schreiben und Servo1-Pin setzen. In der
Compare1A-ISR dann den nächsten Interrupt-Termin berechnen und setzen,
das neue Bitmuster an die Servopins ausgeben und zur Mainloop
zurückkehren, wo es sicher Wertvoleres zu tun gibt, als auf das
Erreichen des nächsten Zählerstandes zu warten.
Auch das Einlesen der Impulse geht mittels Interrupt bedeutend einfacher
(für den Controller) und präziser (jitterärmer). Hierzu kann man die
Kanäle 1, 3 und 5 mit Dioden zusammenfassen (wired OR) und über den
ICP-Pin (oder Analog-Comparator, falls der Pegel nicht mehr für ICP
reicht) einlesen, der einen Input-Capture-Interrupt auslöst und dabei
den Zählerstand des Timers bereitstellt, der bei Auftreten der Flanke
galt und nicht erst den, wenn der Programmcode den Timer abfragen würde.
Denn der Timer läuft bei Dir so schnell, dass er bereits bei wenigen
einfachen Anweisungen weitergezählt hat.
Du wirst ohne Interrupts nichts Gescheites erreichen, schon alleine,
weil Dir durch das Warten und Pollen zuviel Rechenzeit der Mainloop
verloren geht, die Du aber für die restlichen Aufgaben des Programms
brauchst. Selbst mit Interrupts wird es in Bascom recht eng, da Bascom
recht viel Zeit zum Sichern und Wiederherstellen der Register braucht.
Falls Deine Intension war, mal schnell in Bascom "das ultimative
Heli-Stabilisierungsprogramm" zu schreiben, dann hast Du Dich vermutlich
übernommen, um das mit Bascom zu realisieren, muss man Bascom schon
verdammt gut kennen und beherrschen.
...
@ich:
Tja, das wars. Sowas Dämliches.
Ist aber nix mit Klammern sondern so:
1
If Timer1 >= Esc Then
2
Escout = 0
3
Rc_out_counter.0 = 1
4
End If
@Hannes:
Natürlich sieht das so etwas unelegant aus aber ich müsste dann ja immer
die Servosignale sortieren um den den nächsten Termin zu berechnen und
dann auch wissen welcher Ausgang dran ist. Das wird auch nicht weniger
Jitter erzeugen und so wie es jetzt ist, merken die Servos nix von den
paar µs.
Mal simpel ausgedrückt: Was ich auf dem Oszi nicht sehe interessiert die
Servos auch nicht. Eigentlich ist der Timer auch zu schnell. Mit
Prescaler 64 hätte ich ne Auflösung von 4µs, das reicht eigentlich auch.
Mit Ints wäre das immer noch eng, der simple Code kommt da noch eher
mit.
Das wären dann für den gesamten Servoweg immer noch etwa 8bit. Kein
Servo und kein Fernsteuerknüppel sind so genau, daß sie besser auflösen
würden.
So wie oben dauert das max 2ms für die Ausgabe, das ist schön
kalkulierbar und passt.
Das Einlesen ist in der Tat eklig mit der diskreten Abfrage der Pins.
Allerdings: Genau genug ist es und nach spätetestens 10ms ist es vorbei.
Das Auslesen der Sensoren dauert etwa 1,2ms und damit habe ich noch über
6ms zum Rechnen in jedem Zyklus. Das sollte bei 16MHz massig reichen.
Wenn nicht, kann ich immer noch an der Stelle optimieren wobei das ja
auch nicht ohne Fußangeln ist, wenn die Ints während der Berechnung
zuschlagen.
Später werde ich ohnehin noch einen weiteren Käfer brauchen, wenn ich
noch GPS auslesen will. Das ellenlange NMEA mit 9600baud passt nun gar
nicht zu den Servosignalen aber per veroderten Kanälen mit Int (jeder
Kanal per C entkoppelt auf die steigende Flanke triggernd) müsste das
gehen, dafür sind die 9600baud langsam genug. Das ist aber noch
Zukunftsmusik.
Es soll nicht das ultimative Heli-Stabilisierungsprogramm werden sondern
sowas wie der fliegende Ball von den Japanern:
http://www.youtube.com/watch?v=pF0uLnMoQZAhttp://www.youtube.com/watch?v=mvC1kXxM01A
Das Ding hat den Vorteil, daß ein großer Propeller nen besseren Eta hat
als 4 kleine, wobei der Drehmomentausgleich natürlich auch wieder etwas
frisst. Einfacher beherrschbar als z.B. ein Quadrocopter sollte es auch
sein denn bei hoovernden RC-Fliegern ist es das selbe Prinzip.
Und keine Angst, ich bin seit 10 Jahren ganz gut mit Bascom unterwegs,
auch wenn das nach dem obigen Fehler vielleicht nicht so aussieht ;-)
Gruß,
Norbert
Norbert S. schrieb:> Und keine Angst
Ich habe da keine Angst, ich werkele in Assembler also fast in der
Sprache, in der auch der AVR arbeitet...
Aber mach' ist 'n cooles Projekt...
...
Hi,
so, der Testkasten hat abgehoben, alles läuft richtig rum und reagiert
auch korrekt auf die Gyros.
Naja, ich speichere nur die Gyrodaten in einem Array das aufsummiert
wird und tausche jeweils ein Element mit den neuen Daten aus. Das wird
dann etwas skaliert einfach zu den Servosignalen addiert bzw
subtrahiert.
So primitiv hat das natürlich nichts mit Regelung zu tun und
funktioniert auch nicht wirklich aber das ist schon deutlich stabiler
als die ersten Hopser ganz ohne Steuerung.
Sieht auch so aus als wenn die Klappen und die Ausschläge zu klein sind.
Also so vollkommen daneben ist das schonmal nicht aber das wird wohl
noch etwas dauern bis das stabil fliegt.
Ich könnte einen Pseudocode für sowas gebrauchen, momentan fällt mir
nichts Schlaues ein.
Gruß,
Norbert