Ok, ich versuch es mal verständlich zu erläutern, schonmal ein Danke
fürs lesen.....
Aufbau :
Eine bewegliche Platte kann auf zwei Achsen (X,Y) über Servos gekippt
werden. Auf der Platte ist ein IR Touchpad geschraubt, das Seriell
(UART0 ,9600Baud) die Position einer rollenden Kugel an den ATmega644P
übermittelt.
Das soll/wird über einen Software PID Regler geregelt. Ziel ist das
halten der Kugel auf eine festgelegte Sollposition auf der Platte
(Positionsregelung).
Zur Darstellung wurde eine VB.net Oberfläche entwickelt, die alle Werte
der beiden Regler (x- & y-achse) darstellen kann, sowie die vom
Controller Empfangenen Daten des Touchpads (Kugelposition etc.)
Die Daten werden vom Controller über den zweiten Serielle Port (UART1)
an den PC gesendet.
Problem :
Wird die Hauptprogrammschleife des Controllers ausgeführt, ohne die
Daten an den PC zu senden, reagiert die Regelung ( Das verstellen der
Motoren in abhängigkeit zur Kugelposition ) annähernd Verzögerungsfrei.
Werden jedoch während der Hauptschleife zusätzlich noch die Daten an den
PC versendet, merkt man einen deutliches "Motorstottern" , da der
Controller wesentlich länger braucht, bis er wieder an den punkt
gelangt, an dem er die aktuelle Kugelposition abfragen kann.Somit
"verpennt" er Zwischenschritte die er eigentlich einstellen sollte, was
das ganze sehr stotternd und unsauber macht.
Frage :
Wie kann dem ganzen abhilfe geschaffen werden. unsere überlegungen sind
folgende :
- Den Prozessortakt erhöhen ( momentan auf 14,7456MHz )
- Die Baudrate erhöhen, damit die Daten schneller übertragen werden,
brachte jedoch keine Besserung.
- Die Daten nicht alle auf einmal in der Schleife zu übertragen, sondern
maximal 4 pro Schleife ( Das ist nicht Sinn des Programms, Datenansicht
sollte möglichst Synchron laufen)
- Unwichtige Daten nur alle 10 Durchläufe senden ( Macht dann jeden
10ten durchlauf Ruckend, is auch nicht gewünscht)
- Einen zweiten Controller verwenden, der sich um die PC-Kommunikation
kümmert ( Das klingt doch schicker )
Und hier an diesem Punkt stellen sich jetzt diese Fragen :
Wie am besten die Kommunikation realisieren, so das der
Regler-Controller in seiner Arbeit möglichst wenig gestört wird. SPI
wird scheinbar ja auch durch den UART realisiert, fällt damit Flach.
Wie würde es mit einer parallelen Datenübertragung an zwei PORTS
aussehen, die über Interrupts gesteuert werden würde ?
Pro zu übertragenden Signal wären das 5 bytes , Eins für die
Funktionsnummer und 4 für einen FLOAT Wert.
Das wäre mit meinem jetzigen Wissenstand wohl die schnellste und
unterbrechungsfreiste Methode. Was meint ihr dazu ?
Danke für eure Hilfe
gruss Maggus ;)
Da wir ja nicht wissen wie es bis jetzt gelöst ist (eventuell
Quelltext?) kann man nur raten. Der µC ist bestimmt schnell genug für
die aufgabe. Das senden Verbraucht keine nennenswerte rechenzeit. Das
Problem wird vermutlich sein, das eine Zeichenkette auf einmal gesenden
wird - in der Zeit regelt er vermutlich nicht.
Man könnte die Zeichen die zu senden sind, in einen art Ringbuffer
stecken und über den Interrupt versenden lassen.
> Wie kann dem ganzen abhilfe geschaffen werden.
Die seriellen Daten gar nicht in einer Schleife verschicken, sondern in
einen Ringpuffer schreiben und Interrupt gesteuert verschicken.
Markus wrote:
> Wie am besten die Kommunikation realisieren, so das der> Regler-Controller in seiner Arbeit möglichst wenig gestört wird.
Nicht darauf warten, dass die UART Kommunikation abgeschlossen wird.
Sprich die UART Übertragung findet im Hintergrund interrupt gesteuert
statt.
Einen 2-ten Prozessor einzusetzen klingt zwar schick, öffnet aber einen
neuen Sack voll Problemen.
Wie schnell ist denn der Regelungsalgorithmus ? Zykluszeit in ms ? Ist
der in Float oder in Integer ? Die Kommunikation sollte nicht ausmachen,
den die kann im hintergrund laufen. 9600 baud, und auch 38400 ist nicht
alle welt. Da sollte noch einiges an Leistung uebrig sein.
Eben hat es klickt gemacht !
Damit der Empfangspuffer auf der PC Seite nicht volläuft, hab ich eine
kleine Pausenzeit an das Ende der Sendefunktion angehängt. Die wartet
knapp 40ms bis die nächste gesendet wird....
Wenn ich die rausmache dann funktioniert es ohne stottern (PATSCH!!X°)
Hier mal die SendeFunktion damit ihr versteht wovon ich rede
// Kleine Pause, damit Windows zeit für die Datenauswertung hat, bevor
30
// die Nächsten Daten geschickt werden. Ansonsten droht ein Empfangspuffer
31
// Überlauf im Windows bei zu kleiner Wartezeit!
32
33
//zeit(WAITFORWINDOWS); // <------------ DER ÜBELTÄTER
34
35
36
}
Zum senden wird die Uart Bibliothek von Peter Fleury benutzt, die aus
dem Internet bezogen werden kann
http://homepage.hispeed.ch/peterfleury/uartlibrary.zip
Wenn ich die Daten ungehindert an den PC senden lasse, läuft mir dessen
Empfangspuffer voll.
Aber die Zwangspause in die Interruptroutine von Peter Fleury schreiben
, wird wahrscheinlich das selbe problem hervorrufen wie am Anfang
beschrieben.
Das abarbeiten der Hauptschleife wird jedesmal durch die pause
unterbrochen werden, da Interruptroutinen ja nicht parallel zur
Hauptschleife ablaufen.....
Ich denke ich sollte das Problem auf der Windows Seite versuchen zu
lösen, durch z.b. effektiveren Quellcode.
Da sieht man mal wieder, das man manchmal andere braucht um seinen
eigenen Kram zu verstehen :D
> Ich denke ich sollte das Problem auf der Windows Seite versuchen zu> lösen, durch z.b. effektiveren Quellcode.
ja das denke auch auch, bei 9600baud sollte auch ein 286 sich noch
langweile, vermutlich ist die Gui und das auslesen der RS232 in dem
gleichen Thread.
Du hast aber immer noch ein kleines Problem mit
sendInfo
in der Zeit wo die 9Byte gesendet werden, kannt du nichts anders machen
(die meisten zeit wartet der µC nur damit der puffer leer wird!) das
könnte man zwar mit einer höhere baud rate etwas verbessern aber der
Tipp von oben mit dem Ringpuffer ist die bessere lösung.
Gibt es dafür ein Beispiel ? ich kann mir nicht wirklich etwas
vorstellen, ausswer das die Daten über die Hauptschleife gesammelt
werden und am Ende verschickt werden.
ich glaube das Peter Fleury das genau so wie ihr meint auch gelöst
hat...
ich verstehe das jetz so :
1.In der "uart_putc" schiebe ich das zu sendende zeichen in den
Ringpuffer sobald Platz vorhanden ist, und gibt durch das Aktivieren des
interrupts das "SendeSignal" für den Controller.
2.Der Controller Sendet..
3.Wurde das zeichen gesendet wird "SIGNAL(UART0_TRANSMIT_INTERRUPT)"
ausgelöst. hier wird geprüft ob noch zeichen zum sendenvorhanden sind.
Falls ja, wird das nächste in das Senderegister geschrieben.
Meiner Meinung nach könntet ihr doch genau das gemeint haben, oder ?
Der Code von Fleury ist schon sehr gut.
Mach den Ringbuffer doch größer (von 32byte auf 128) und erhöhe die
Übertragungsrate.
An dem PC liegt es jedenfalls nicht.
@Mike J.
> Mach den Ringbuffer doch größer (von 32byte auf 128)
Das pauschal zu sagen macht überhaupt keinen sinn, es werden im Block
9Byte gesendet diese Passen 3mal in den Puffer. Da wir nicht wissen wie
oft diese Daten pro sekunden gesendet werden sollen kann man auch keine
abschätzung der Puffer größe machen. Wenn mehr daten in den Puffer
geschrieben werden als gesendet werden können, dann kann man in auch
gleich auf 100Mbyte erhöhen und hat immer noch nichts gekonnt.
> Wenn mehr daten in den Puffer> geschrieben werden als gesendet werden können, dann kann man in auch> gleich auf 100Mbyte erhöhen und hat immer noch nichts gekonnt.
das ist klar, deshalb sagte ich auch:
>> und erhöhe die Übertragungsrate
Er soll das aber erst mal probieren, dann sieht er dass es daran lag und
ist glücklich.
Wenn er weiß woran es liegt kann er an der Stelle ansetzen und seinen
Code weiter optimieren. Also Puffer verkleinern, Übertragungsrate so
weit senken wie möglich.
Mike J. wrote:
>> Wenn mehr daten in den Puffer>> geschrieben werden als gesendet werden können, dann kann man in auch>> gleich auf 100Mbyte erhöhen und hat immer noch nichts gekonnt.> das ist klar, deshalb sagte ich auch:>>> und erhöhe die Übertragungsrate>> Er soll das aber erst mal probieren, dann sieht er dass es daran lag und> ist glücklich.> Wenn er weiß woran es liegt kann er an der Stelle ansetzen und seinen> Code weiter optimieren. Also Puffer verkleinern, Übertragungsrate so> weit senken wie möglich.
Und vor allen Dingen: überlegen in wie weit ein hohes Volumen sinnvoll
ist.
Wenn die Daten letztendlich nur dazu dienen, einen menschlichen
Beobachter zu informieren, reicht es völlig aus, wenn sich die Daten nur
alle halbe Sekunde aktualisieren. Kein Mensch kann die Daten schneller
mental verarbeiten.
Wenn an der anderen Seite natürlich ein weiterverarbeitendes Programm
sitzt, kann das anderes aussehen.