Hallo zusammen, ich habe einen µC, der über einen halfduplex RS485-Bus mit dem PC kommuniziert. Das Ende eines Telegrams wird über eine Pause von mind. 5ms angezeigt. Der µC sendet zyklisch alle 100ms eine kurze Nachrichte. Nun muß ich den PC irgendwie darauf synchronisieren, denn der PC darf seine Nachrichten an den µC nur in den Pausen zwischen zwei µC-Telegrammen senden, sonst kommt es zu Buskollisionen. Ich wüßte nun ganz genau, wie ich das auf einem µC programmieren würde, da ich dort direkten Zugriff auf UART-Interrupts, Timer etc. habe. Aber wie mache ich das unter C#? Ich bräuchte ein Event, das zügig kommt, wenn der PC ein Telegram vom µC empfangen hat und dann mind. 5ms Ruhe war. Im Augenblick hab ich einen Thread laufen, der quasi den SerialPort "pollt" und über eine StopWatch das Timing mißt. Das Ganze läuft aber nicht sehr präzise, z.B. kann ich keine Sync-Pause von 5ms realisieren, sondern muß dem PC mind. 20ms geben, damit er nicht durcheinander kommt. Hat jemand einen Tip?
Was du "brauchst" geht schon in richtung echtzeit...da kannst du erstmal mit eigenen windows treibern etc anfangen. Generell ist dein ansatz hier ein wenig falsch... Für sowas nimmt man entweder ein vernünftiges protokoll/bus wie zB CAN oder baut sich einen gateway zwischen bus und pc, der sich um den echtzeit teil kümmert. Alternativ kannst du zB auch die funktionsweise von pc und uc tauschen
>ann ich keine Sync-Pause von 5ms realisieren, warum nicht? also 5ms sind ja EWIG.. schon mal nach high-resolution timer gesucht http://msdn.microsoft.com/en-us/library/aa964692%28v=vs.85%29.aspx usw. (ICH würde, wenn du schon gut µC Programmieren kannst, aber auch ein gateway basteln, rs485<>UDP)
Ich hab mal was ähnliches versucht, mit einem USB/RS485 Adapter auf FTDI-Basis, und zwar unter direkter Zuhilfenahme der Windows-API und Overlapped-IO und WaitForSingleObject() mit eine Timeout von nur 1ms, ich hab der ganzem Low-Level Mimik sogar ihren eigenen Thread spendiert der nur auf neue Daten von der seriellen Schnittstelle wartet, nichts anderes macht und sofort reagiert. Dennoch ist es mir nicht gelungen das zeitliche Eintreffen der empfangenen Bytes in der Windows-API (also das Auslösen von WaitForSingleObject) genauer als ungefähr 25ms (eher schlechter) mit dem tatsächlichen physikalischen Eintreffen auf der Leitung zu korrelieren. Ich hab mir das dann irgendwann mit der Natur des USB-Treibers (dessen Pufferung von Daten, etc) erklärt, als prinzipielle Unmöglichkeit angesehen und meinen Timeout auf 50ms erhöht. Vielleicht hast Du mehr Erfolg wenn Du eine "echte" serielle Schnittstellenkarte (als PCI-Karte) reinsteckst. Womöglich hast Du dann ein wesentlich straffer an die physikalische Schicht gebundenes Timing.
:
Bearbeitet durch User
Bernd K. schrieb: > Ich hab mal was ähnliches versucht Hast Du dabei auch die Granularität des Windows-Schedulers umgestellt? Ohne das zu tun, bekommst Du nur Auflösungen im 10msec-Bereich. Die Multimedia-API-Funktion timeBeginPeriod (http://msdn.microsoft.com/de-de/library/windows/desktop/dd757624%28v=vs.85%29.aspx) ermöglicht es, diese Granularität auf 1msec zu setzen.
Rufus Τ. Firefly schrieb: > Hast Du dabei auch die Granularität des Windows-Schedulers umgestellt? > Ohne das zu tun, bekommst Du nur Auflösungen im 10msec-Bereich. > > Die Multimedia-API-Funktion timeBeginPeriod > (http://msdn.microsoft.com/de-de/library/windows/desktop/dd757624%28v=vs.85%29.aspx) > ermöglicht es, diese Granularität auf 1msec zu setzen. Das muss ich noch mal ausprobieren, danke für den Tipp! Die Software wurde größtenteils unter Linux entwickelt (wo sie besser funktionierte) und erst nachträglich nach Windows portiert, d.H. mit der Windows-API hab ich weniger Erfahrung, also kannte ich diesen Trick noch nicht. Es ist mir noch nichtmal überhaupt in den Sinn gekommen überhaupt nur in Erwägung zu ziehen ob es dort Mechanismen geben könnte mit denen ein unberechtigtes Userspace-Programm eventuell einfach so an irgendwelchen Kernel-Timings rumschrauben darf. Muß ich mal ausprobieren ;-)
Das Ganze ist vom Protokol her schon suboptimal. Sowas sollte man Master-Slave implementieren. Also der Master, dh der PC, verlang was vom slave, dh dem controller, mit einem timeout. Der Slave muss nun antworten. Ohne Aufforderung sendet der slave gar nichts. Und sonst sollte man's bidirektional zB mit RS422 implementieren. Dort gibt's nichts umzuschalten.
Siebzehn Für Fuenfzehn schrieb: > Das Ganze ist vom Protokol her schon suboptimal. Sowas sollte man > Master-Slave implementieren. Naja, bei genau 2 Geräten ist das doch reine Definitionssache: In dem Fall wie oben geschildert definierst du halt kurzerhand den µC als Master und den PC als Slave der sich dem Timing des Masters unterzuordnen hat und schon passts wieder: Der Master (der µC) erwartet eine "Antwort" vom Slave (dem PC) entweder unmittelbar nach seinem Telegramm oder keine Antwort (keine Antwort ist auch eine Antwort).
:
Bearbeitet durch User
Bernd K. schrieb: > In dem Fall wie oben geschildert definierst du halt kurzerhand den µC > als Master und den PC als Slave der sich dem Timing des Masters > unterzuordnen hat und schon passts wiede Passt halt nicht wirklich, wenn man sich dessen bewusst wird, wie schwierig es ist, mit einem PC ein genaues Timing einzuhalten. Hier sind bereits auf Millisekunden spezifizierte Timeoutwerte extrem problematisch. Beim Systemdesign (also der Entscheidung, wer hier Master und wer Slave ist) muss man das berücksichtigen; der, der eher Schwierigkeiten hat, ein vorgegebenes Timing einzuhalten, sollte es definieren. Ist beim Zu-Fuß-Gehen in einer Gruppe auch so: Der langsamste gibt das Tempo vor. Zwar ist ein PC nicht per se langsam, aber beim Reagieren auf externe Ereignisse ist er das, und zwar so deftig, daß auch ein popliger 8-Bit-Controller, der mit nur ein paar MHz getaktet wird, hier problemlos das Oberwasser gewinnen kann.
Bronco schrieb: > Der µC sendet zyklisch alle 100ms eine kurze Nachrichte. Nun muß ich den > PC irgendwie darauf synchronisieren, denn der PC darf seine Nachrichten > an den µC nur in den Pausen zwischen zwei µC-Telegrammen senden Könntest du das noch etwas klarifizieren? Ist das was der PC sendet eine Antwort auf die Nachricht, oder ist das Timing nur nötig, um Kollisionen zu vermeiden? Falls letzteres, würde ich bei deinem Kenntnisstand die Sache sanieren mit einem Prozessorchen, das die Daten vom PC zwischenspeichert und immer 10 ms nach einer µC-Meldung an diesen weitergibt, das kriegst du viel schneller hin als echtzeitfähige Windows-Software. Verkorkst ist die Sache schon vorher, man sollte nicht nur den PC zum Master machen, weil ein µC viel geeigneter als Slave ist, es ist auch ungünstig, Protokolle durch Pausen zu definieren. Vielmehr sollte das Messageende durch ein spezielles Zeichen definiert sein wie CR oder EOT. Daraus lässt sich ein sofortiges Windows-Event ableiten, das wahrscheinlich schnell genug ist, um in weniger als 100 ms zu reagieren, allerdings nicht immer, aber meistens. Georg
Georg schrieb: > es ist auch > ungünstig, Protokolle durch Pausen zu definieren. Bei Modbus ist das beispielsweise so definiert, dreieinhalb Bytelängen trennen die Telegramme voneinander. Wenn man einen guten und ziemlich direkten Draht zur UART-Hardware hat ist das eigentlich kein Problem. Das Problem ist hier dass das wohl unter Windows (oder generell durch dicke Schichten von Treibern und übereinandergelegten RS485-over-irgendwas-over-USB Stacks hindurch) alles andere als trivial ist.
Hi, > Bernd K. schrieb: >> Ich hab mal was ähnliches versucht > > Hast Du dabei auch die Granularität des Windows-Schedulers umgestellt? > Ohne das zu tun, bekommst Du nur Auflösungen im 10msec-Bereich. > > Die Multimedia-API-Funktion timeBeginPeriod > (http://msdn.microsoft.com/de-de/library/windows/desktop/dd757624%28v=vs.85%29.aspx) > ermöglicht es, diese Granularität auf 1msec zu setzen. das hat unter reinem C++ auch immer ganz gut funktioniert. Aber bei .NET hatte ich in meinen Versuchen kein Glück mehr, mit diesen Funktionen den Scheduler zu verändern. Es hat einfach gar nichts bewirkt :-( Ganz ehrlich: Mit dieser Art des Protokolls und C# sehe ich keine Möglichkeit, dies zuverlässig in den Griff zu bekommen. Falls aber die Gegenstelle in Stein gemeißelt ist, dann würde ich mir eine kleine Schaltung mit MC und USB/Seriell-Wandler bauen, die als weiteres Interface für das "murksige" Protokoll dient. Auf der PC-Seite kann man dann mit dem "neuen" MC ein zuverlässiges und Timing unabhängiges Protokoll definieren. Z.B. kann dieser MC Befehle an die Gegenstelle erst einmal zwischenpuffern und dann im richtigen Moment weiterleiten. Gruß Oliver
schon mal die Einstellungen des USB<>serial Adapters kontrolliert (ist es überhaupt USB???) ähnlich hier, ganz unter: (buffer noch auf ein Minimum.. usw.) http://www.digi.com/support/kbase/kbaseresultdetl?id=3418
Eine pragmatischere Möglichkeit wäre das Auftreten von Kollisionen einfach als gegeben hinzunehmen und einzuplanen (wie groß ist rechnerisch die Wahrscheinlichkeit einer Kollision?) und stattdessen einfach das Telegramm (nach kurzen zufällig langen Pausen) wiederholen, so oft bis ein korrektes ACK empfangen wurde. Das geht aber nur vernünftig wenn die Idle-Zeiten weitaus länger sind als die Telegrammlängen, also größtenteils Schweigen herrscht auf dem Bus.
Hallo zusammen, erstmal danke für die vielen Antworten und sorry, daß ich mich erst jetzt zurückmelde (war im Urlaub). Kurz zum Verständnis meiner Anwendung: Auf dem RS485-Bus kommunizieren normalerweise zwei µCs miteinander. Die haben überhaupt kein Problem mit dem Protokol. Nun soll man zu Service-Zwecken das PC-Tool anstecken können. Ich hab nun zwei mögliche Lösungen probiert: 1. Langsames Timing (20ms) auf PC-Seite -> geht, aber eben langsam, wenn man größere Datenmengen übertragen muß 2. Bus-Kollisionen einplanen -> geht auch, wenn man die Daten mehrfach sendet, kam mir aber etwas unschön vor Ich denke, der Hinweis, den PC das nächste mal zum Master zu machen, ist am hilfreichsten. Kann ich im aktuellen System nicht mehr realisieren, aber bei zukünftigen Projekten berücksichtigen. Danke!
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.