Hallo zusammen,
folgender Sachverhalt: Ich muss/möchte in Visual Studio (vb.net) eine
Anwendung erstellen, die mit einem Gerät (Unterlagen / Doku gibt es
nicht, ist nichts für den privaten Gebrauch) über den RS232 Anschluss
auf eben diesem Gerät kommuniziert.
Die Original-Software öffnet den Port mit Baudarte 9600, Parity even, 8
Stop Bits etc., und sendet dann "55 d3", quasi als Verbindungsanfrage.
Darauf antwortet das Gerät dann.
Alle Einstellungen (Baudrate, Parity, Stopbits etc.) wurden mittels
Serial Port Monitor ausgelesen und in Visual Studio übernommen.
Das Problem: sendet meine Anwendung nun "55 d3" mit den gleichen
COM-Port Einstellungen wie die originale Software, reagiert das Gerät
nicht.
Sende ich die gleichen Zeichen direkt über die "Send"-Option des Serial
Monitors, funktioniert es aber, und das Gerät reagiert genau wie bei der
Original-Software.
Ich habe zugegeben wenig Erfahrung mit serieller Kommunikation und nur
Grundkenntnisse in vb.net, aber ich weiß wirklich nicht, an was das
liegt.
Schaue ich mir die Logs des Serial Monitors an, sind folgende
Unterschiede zu erkennen, wenn ich zwischen meiner Anwendung und dem
direkten senden der Zeichen über den Monitor unterscheide:
Der Serial Port Monitor (fungiert hier als Anwendung die sendet, nicht
nur überwacht) zeigt im Log als erstes "IOCTL_SERIAL_SET_WAIT_MASK".
Meine VB Anwendung tut dies erst ganz am Ende, nach GET_BAUD_RATE etc,
direkt vor dem senden.
Zudem sind im Log bei meiner Anwendung "IOCTL_SERIAL_CLR_DTR" (scheinbar
als Anfrage vom verbundenen Gerät), und "IOCTL_SERIAL_SET_QUEUE_SIZE"
eingetragen, diese fehlen beim direkten senden mittels Monitor komplett,
aber dennoch antwortet die Hardware beim Monitor, und bei meiner
Anwendung nicht. Anbei noch der Code meiner Anwendung.
Meine Frage ist im Prinzip, ob ich bei Dingen wie "Set Wait Mask" etc.
selbst festlegen kann, wann diese gesendet werden, und ob "Set Queue
Size" zwingend notwendig ist (beim Monitor geht es ja auch ohne...),
obwohl das, wie in meinem Code ersichtlich, nie von mir festgelegt
wurde, und was die Ursache sein könnte, dass das Gerät nicht reagiert.
Johannes S. schrieb:> Probiere mal SerialPort1.DtrEnable = true;> Das DTR wollen einige Devices sehen.
DTR wird tatsächlich benötigt, das stimmt. DTR-Enable habe ich aber in
den Einstellungen von SerialPort1 schon aktiviert. Habe die Zeile
dennoch mal eingefügt, leider ohne Erfolg.
Klaus S. schrieb:> Vielleicht fehlt noch ein CR oder LF als Terminierungszeichen ?
Müsste das nicht im Log des Serial Monitors ersichtlich sein?
Im Serial Port Monitor "Senden"-Dialogfeld "55 d3" eingeben und dann
senden, dürfte ja nichts anders als
Im Eröffnungspost hast Du geschrieben: "55 d3" wird gesendet.
Mir ist jetzt nicht ganz klar ob das als String "55 d3" erfolgt oder
ob die "55" und "d3" binär als Bytes gesendet werden.
Hast Du eventuell mal einen Screenshot des Serial Port Monitor an der
Stelle ?
Klaus S. schrieb:> Mir ist jetzt nicht ganz klar ob das als String "55 d3" erfolgt oder> ob die "55" und "d3" binär als Bytes gesendet werden.
Werden als hexadezimale Bytes gesendet.
Screenshot ist angehängt.
Ich wähle im "Senden"-Dialogfeld des Serial Monitors aus "HEX".
blub schrieb:> dte und dce gibt's auch noch. Stichwort Handshake.
Das müsste ja auch durch den Serial Monitor sichtbar werden, schätze
ich. Parity Baudrate etc. werden jedenfalls automatisch korrekt
eingestellt, wenn ich ihn mitlaufen lasse und die originale Software
verbinde. Handshake bleibt auf "none".
Muss da eine bestimmte Pause zwischen den Zeichen sein? Tippst du die
Zeichen in dem serial Monitor von Hand ein oder wird das als Makro am
Stück gesendet?
Johannes S. schrieb:> Muss da eine bestimmte Pause zwischen den Zeichen sein? Tippst du die> Zeichen in dem serial Monitor von Hand ein oder wird das als Makro am> Stück gesendet?
Ich tippe in eine Linie, nicht nach einander "55 d3". Egal ob direkt
nach dem öffnen des Ports, oder 10 Minuten danach, vermutlich also kein
bestimmtes Timing.
Ist wohl am sinnvollsten...
Log vom Monitor, gekürzt nur bis zur Antwort der Hardware (00) weil ich
so weit mit meiner "Lösung" gar nicht komme - https://docdro.id/yuTwyFy
und Log von meiner Lösung bei der keine Antwort von der Hardware kommt -
https://docdro.id/yuTwyFy
Vielleicht seht ihr mehr als ich...
Die Protokolle zeigen das im Original folgende Dinge passieren:
Set DTR
Set RTS
Set handshake zu DTR Flow oder ähnlich.
Bei deiner Version kommt öfter clear DTR usw vor, evtl ist das aber
automatisch generiert und löst sich mit dem richtigen setzen des
handshake, welcher bei dir auf Off /0 gesetzt wird.
Beispiel in C#, analog in VB.net:
Lenny D. schrieb:> port.RtsEnable = true;
RTSEnable steht bereits in den Properties vom SerialPort in VB auf True.
Werde es später trotzdem nochmal damit versuchen.
cppbert schrieb:> Ich würde mich jetzt erst mal nur darauf konzentrieren die 100% gleichen> Settings zu erreichen
Deshalb war eine meiner Fragen, wie ich einstellen kann, das
Serial-Set-Wait-Mask nicht als letztes, sondern als erstes gesendet
wird, Set-Queue-Size gar nicht (weil das beim Monitor auch fehlt),
etc... aber ob man das überhaupt einstellen kann? Finde jedenfalls
nichts dazu.
Das RTS ist wichtig, aber hast du auch Handshake/Flow control schon
versucht zu ändern?
Wait und die meisten anderen beziehen sich auf Dinge auf der PC Seite,
von denen die Hardware also nichts direkt mitkriegt.
Der Unterschied zw. Deinem und dem original ergibt sich ja schon beim
senden, richtig? Nicht erst beim Empfang der 00 (was mit wait usw
zusammenhängen könnte).
Du siehst aber direkt am Gerät das das senden von den 2 Bytes den
Status/eine anzeigen ändert? Dann würde ich mich im Protokoll auf die
Dinge konzentrieren die tatsächlich an der Hardware Schnittstelle was
anders machen (dts, dtr pins, handshake usw)
Lenny D. schrieb:> Das RTS ist wichtig, aber hast du auch Handshake/Flow control schon> versucht zu ändern?
Im Serial Port Monitor ist Handshake aus, Flow Control XX. Wenn ich hier
etwas verändere, z.B. Flow Control auf Xoff / Xon stelle, reagiert das
Gerät nicht mehr. Diese Einstellungen (Handshake und Flow Control beide
aus) müssten also stimmen.
Ich kann es mir wirklich nicht erklären. Ich dachte, es gibt einen ganz
einfachen Unterschied in den Logs des Serial Monitors und ich bin nur zu
unwissend um diesen zu finden, aber dem scheint wohl nicht so zu sein...
Lenny D. schrieb:> Du siehst aber direkt am Gerät das das senden von den 2 Bytes den> Status/eine anzeigen ändert?
Das Gerät hat kein Display oder ähnliches, der Status etc. wird über die
Software und eben dieser RS232 Schnittstelle mitgeteilt, aber ich sehe
ja, wenn ich mit dem Monitor sende, das ich eine Antwort bekomme ("00"),
und dann je nachdem welche Zeichen ich als nächstes sende z.B. den
aktuellen Gerätezustand etc.
Lenny D. schrieb:> Dann würde ich mich im Protokoll auf die> Dinge konzentrieren die tatsächlich an der Hardware Schnittstelle was> anders machen (dts, dtr pins, handshake usw)
All das ist im Serial Monitor ersichtlich (DTR, RTS, Parity etc.) und
wurde entsprechend übernommen, das ist im Log ja auch zu sehen...
Er sieht schon genug Details über die IOCTLs, mehr Magie kann die
Original Software auch nicht machen
In C/C++ wuerde ich die IOCTLs einfach direkt nachbauen aber auch nur
weil ich nicht weiss ob das so direkt mit VB geht und damit erstmal eine
100% identische Ausgangssituation schaffen
OK, dann bin ich vielleicht verwirrt...
File "monitorfuervb" (Original?):
- Anfangs Control Handshake 0x00
- kurz vor absenden von 55 d3 SET_HANDFLOW auf SERIAL_DTR_CONTROL
- kurz darauf erfolgreicher Empfang von 00
Datei "betalineview" (deine Lösung?):
- kurz vor absenden von 55 d3 SET_HANDFLOW auf 0x00 Handshake (off?)
- scheinbar kein erfolgreicher Empfang von 00 im weiteren Verlauf
Verwechsele ich hier etwas oder wird evtl. der Handshake kurz vor
Absenden wieder umgestellt zu etwas das du nicht erwartest?
Ich glaube du hast Recht!
Funktionsfähig ist: ControlHandShake 0X01
nicht funktionsfähig ist: ControlHandShake 0X00
Die Frage ist jetzt, wie ich in vb.net die Eigenschaft ControlHandShake
festlege... jemand anderes sagt, das tut nichts zur Sache, wenn
DTR-Enable true ist, und das ist es definitiv (in den Properites vom
SerialPort DTREnable auf yes und zusätzlich noch im Code DTREnable =
true), trotzdem scheint es daran ja zu liegen, weil man im Log den
Unterschied sieht.
Lenny D. schrieb:> File "monitorfuervb" (Original?):
Richtig
Lenny D. schrieb:> Datei "betalineview" (deine Lösung?):
Auch richtig
Lenny D. schrieb:> wird evtl. der Handshake kurz vor> Absenden wieder umgestellt zu etwas das du nicht erwartest?
Nochmal richtig, die Frage ist bloß wieso... mein sehr kurzer gesamter
Code ist im ersten Post ersichtlich, und da wird DTR definitiv nicht
wieder deaktiviert.
AAL schrieb:> Nochmal richtig, die Frage ist bloß wieso... mein sehr kurzer gesamter> Code ist im ersten Post ersichtlich, und da wird DTR definitiv nicht> wieder deaktiviert.
Bist du mal schön langsam durch den code gesteppt um zu schauen wo das
deaktivieren ausgelöst wird?
cppbert schrieb:> Bist du mal schön langsam durch den code gesteppt um zu schauen wo das> deaktivieren ausgelöst wird?
1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
2
SerialPort1.BaudRate = 9600
3
SerialPort1.DataBits = 8
4
SerialPort1.StopBits = 1
5
SerialPort1.DtrEnable = True
6
SerialPort1.Open()
7
Dim data() As Byte = {&H55, &HD3}
8
9
'Dim TestData(3) As Byte
10
11
'TestData(0) = &HFE
12
13
'TestData(1) = &H11
14
15
'TestData(2) = &H11
16
17
'TestData(3) = &HFF
18
19
SerialPort1.Write(data, 0, data.Length)
20
21
End Sub
Das ist alles... zusätzlich als Screnshot die Properties des
SerialPorts...
Die neue Frage ist also, was diesen Unterschied auslöst
(ControlHandShake 0x00 statt 0x01)...
ControlHandShake = 0X01 geht nicht, wäre leider zu einfach...
Es gibt bei seriellen Schnittstellen bekanntlich den Hardware-Handshake
(RTS) und den Software-Handshake (XON/XOFF).
Folglich sollte es für die Einstellung einer Seriellen Schnittstelle die
folgenden 4 Möglichkeiten geben:
1. Kein Handshake
2. Hardware-Handshake aktiv
3. Software-Handshake aktiv
4. Hardware-Handshake und Software-Handshake aktiv
In dem Programmausschnitt kann ich nicht erkennen, dass der Handshake
für die Schnittstelle gesetzt wird. Also einfach mal nachschauen, wie
das bei VB geht. Irgendwas mit setHandshake müsste es geben. Default ist
wahrscheinlich „kein Handshake“.
Leider kann ich aus dem Protokoll nicht eindeutig erkennen, ob das Gerät
Software- oder Hardware-Handshake will. Das liegt daran, dass ich nicht
wirklich weiß, was ControlHandShake 0X01 ist. ControlHandShake 0X00
würde ich mal als NONE definieren wollen und ControlHandShake 0X01
vermute ich als XON/XOFF.
Also in der VB Doku nachschauen und XON/XOFF testen. :-)
HandShaker schrieb:> Es gibt bei seriellen Schnittstellen bekanntlich den Hardware-Handshake> (RTS) und den Software-Handshake (XON/XOFF).>> Folglich sollte es für die Einstellung einer Seriellen Schnittstelle die> folgenden 4 Möglichkeiten geben:>> 1. Kein Handshake> 2. Hardware-Handshake aktiv> 3. Software-Handshake aktiv> 4. Hardware-Handshake und Software-Handshake aktiv>> In dem Programmausschnitt kann ich nicht erkennen, dass der Handshake> für die Schnittstelle gesetzt wird. Also einfach mal nachschauen, wie> das bei VB geht. Irgendwas mit setHandshake müsste es geben. Default ist> wahrscheinlich „kein Handshake“.
Es gibt schlicht das Property "Handshake" und das hat genau die vier von
dir als möglich apostrophierten Einstellungen. Tatsächlich deckt es
damit aber nicht alle Möglichkeiten ab, denn Hardware-Handshake gibt es
in zwei Spielarten: 5-Draht und 7-Draht. Im ersteren Fall spielt nur das
Signalspiel auf RTS/CTS eine Rolle, im zweiten Fall zusätzlich auch noch
das auf DTR/DSR.
Der SerialPort von Dotnet unterstützt beim Hardware-Handshake nur die
7-Draht-Variante. Spielt ein Gerät nur mit 5 Drähten, muss man ein
entsprechend geschaltetes Kabel verwenden, nämlich eins, bei dem auf
PC-Seite DTR und DSR direkt verbunden sind und dann das Property
DTREnable auf true setzen. Dann macht sich's der SerialPort sozusagen
selber, was das Signalspiel auf DTR/DSR betrifft, er sieht dann auf DSR
halt immer, dass der Peer "ready" ist.
> Also in der VB Doku nachschauen und XON/XOFF testen. :-)
Auch Software-Handshake gibt es in mehreren Varianten, von denen der
SerialPort von Dotnet nur eine unterstützt. Die Sache ist nämlich, dass
die beiden Zeichen XON und XOFF im Prinzip beliebig sind. Sie dürfen
halt nur niemals in den Nutzdaten vorkommen...
Zusammengefasst kann man sagen, dass der Dotnet-SerialPort ziemlich
kastriert ist. Er unterstützt längst nicht alles, was es real gibt oder
gab, sondern nur die gebräuchlichsten Varianten. Darüber hinaus ist er
auch noch katastrophal lausig programmiert, er ist nämlich z.B.
überhaupt nicht darauf vorbereitet, dass eine COM-Schnittstelle einfach
mal so verschwindet, was bei USB-Schnittstellen aber ziemlich normal
ist, wenn man einfach den Stecker zieht...
Typischer Schrott von unfähigen Microsoft-Indern...
Das darunterliegende Win32-COMM-API kann das übrigens alles noch
richtig...
Danke für die Infos!
Habe nun Handshake mal auf XOn/XOff gesetzt und siehe da:
ControlHandshake-> 0x01!
Habe leider erst Sonntag die Möglichkeit das ganze an der Hardware
auszuprobieren, werde berichten.
Ihr seit spitze ;)
So, hatte heute nochmal Zeit für das ganze.
Geht leider immer noch nicht. Ich kann es mir nicht mehr erklären.
ControlHandshake ist jetzt sowohl beim Monitor, als auch bei meiner
Anwendung 0x01, daran lag es also nicht.
Einziger Unterschied, der mir in den Logs noch aufgefallen ist: XOn und
XOff Limit ist bei meinem Programm 1024, und beim Monitor / der original
Software
XOn - 2048 und XOff - 512.
Dies werde ich noch testen, ansonsten versuche ich probeweise mal ein
anderes serielles Terminal zum testen.
Noch was zur Hardware... das Kabel (Female DB9 PC Seite) hat am anderen
Ende zur Hardware 4 Drähte.
Rx, Tx, DTR, und GND.
Mal sehen was des Rätsels Lösung sein wird...
AAL schrieb:> Noch was zur Hardware... das Kabel (Female DB9 PC Seite) hat am anderen> Ende zur Hardware 4 Drähte.> Rx, Tx, DTR, und GND.
Also mit absoluter Sicherheit:
1) sehr weit weg von allem "Üblichen"
2) kein Hardware Handshake
Ziemlich wahrscheinlich ist zusätzlich:
3) DTR hat eine Bedeutung, aber nicht die übliche.
Um die Bedeutung von DTR zu klären, würde bestenfalls die Beobachtung
der "normalen" Kommunikation mit dem vorgesehenen Host helfen.
Je nachdem, was dabei rauskommt, könnte sich ergeben, dass ein Nachbau
des Protokolls mit dem SerialPort unmöglich ist oder sogar unmöglich mit
dem WinAPI. Es könnte aber auch rauskommen, dass es ein Kinderspiel ist.
Das hängt vom ermittelten Timing des Protokolls ab.
c-hater schrieb:> oder sogar unmöglich mit> dem WinAPI.
Noch ein Nachtrag... "Detect it easy" sagt, die original Software wurde
in C++ 6.0 compiled... gibt mir Hoffnung das hinzubekommen.
Vielleicht hänge ich mal einen Log der original Software an, wenn das
hilft, aber der Serial Monitor schafft es mit senden Dialog ja auch
(auch in neuer VM ohne installierte Software die zur Hardware gehört).
Erstmal XOnnLimit und XOffLimit anpassen und nochmal testen.
Hmmmm,
ich kann mir nicht vorstellen, dass XON- und/oder XOFF-Limit Werte das
Problem sind. Die beiden Werte regeln, bei welcher Puffer Belegung XOFF
bzw. XON gesendet werden soll.
XON-Limit 2048 heißt, dass XOFF gesendet wird, wenn mehr als 2048
empfangene Byte im Puffer stehen (und noch nicht abgeholt wurden).
XOFF-Limit 512 bedeutet, dass XON gesendet wird, wenn weniger als 512
Byte noch im Puffer stehen.
Wenn ich die Logs richtig gelesen habe, werden 2 Byte gesendet und es
soll ja erst mal nur 1 Byte empfangen werden. Damit kann man kein
XON/XOFF-Limit ausreizen. Das sollte, wenn Software Handshake
vorausgesetzt wird, auch funktionieren, wenn auf der anderen Seite „kein
Handshake" eingestellt ist. Denn zum Start der Kommunikation muss kein
XON gesendet werden.
Ich persönlich würde mit einem Terminalprogramm testen. Mit einem bei
dem DTR, RTS etc gesetzt werden kann und angezeigt wird. Eins findet man
z. B. mit Google über „Terminal Version 1.93"
AAL schrieb:> Noch ein Nachtrag... "Detect it easy" sagt, die original Software wurde> in C++ 6.0 compiled... gibt mir Hoffnung das hinzubekommen.
Wirft Fragen auf:
kannst du mit der Original-Software über die Hardware (also PC und
serielles Kabel) normal kommunizieren oder verwendet die alte Software
ganz andere Hardware - vielleicht liegt es daran - billiger USB-Seriell
Adapter?
> Vielleicht hänge ich mal einen Log der original Software an, wenn das> hilft, aber der Serial Monitor schafft es mit senden Dialog ja auch> (auch in neuer VM ohne installierte Software die zur Hardware gehört).
wenn es gar nicht geht würde ich das Original-Log per IOCTLs in C/C++
Nachbauen (falls das mit VB.Net nicht geht) 100% so wie sie im Log
stehen, bisschen Copy&Paste sollte da ja reichen - wenn dann was läuft
kannst du immer noch versuchen zu portieren
cppbert schrieb:> Wirft Fragen auf:>> kannst du mit der Original-Software über die Hardware (also PC und> serielles Kabel) normal kommunizieren oder verwendet die alte Software> ganz andere Hardware - vielleicht liegt es daran - billiger USB-Seriell> Adapter?
Mit der Original-Software (UND mit der "Send"-Funktion des Serial
Monitors), kann ich über den PC normal mit der Hardware kommunizieren.
Einmal ein USB-RS232 Kabel, und das Kabel des Herstellers (DB9 Female
auf 4 Pins).
Es werden die gleichen Kabel verwendet.
cppbert schrieb:> wenn es gar nicht geht würde ich das Original-Log per IOCTLs in C/C++> Nachbauen (falls das mit VB.Net nicht geht) 100% so wie sie im Log> stehen, bisschen Copy&Paste sollte da ja reichen - wenn dann was läuft> kannst du immer noch versuchen zu portieren
Von C++ habe ich keine Ahnung, werde mich mal einlesen, wenn das mit
IOCTL nachbauen tatsächlich reöativ einfach geht.
Were nun noch ein anderes Terminal Programm testen, auch wenn es nicht
so aussieht, als würden die mehr können als der Eltima Serial Monitor.
Nochmal ein Nachtrag...
habe nun die Hercules Terminal Software ausprobiert, mit Erfolg! Hier
antwortet die Hardware. Getestet in einer frischen VM in der die
Original Software nicht installiert ist, es geht also definitiv ohne das
irgendwas mitmischt...
Anbei nochmal die Einstellungen der Terminal Software.
DTR Haken muss ich setzen, und Parity auf even. Dann funktioniert es.
Was ich vergessen habe, zu erwähnen... da die Software leider für
Windows CE 6.0 sein muss, verwende ich Visual Studio 2008 und Framework
ist auf 2.0 eingestellt. Werde das ganze gleich nochmal in VB2019 und
als normale Windows Anwendung testen... vielleicht liegt hier das
Problem, auch wenn laut Serial Monitor ja alles gesendet wird.
Werde weiter berichten.
AAL schrieb:> habe nun die Hercules Terminal Software ausprobiert, mit Erfolg! Hier> antwortet die Hardware. Getestet in einer frischen VM in der die> Original Software nicht installiert ist, es geht also definitiv ohne das> irgendwas mitmischt...
bitte lass dir von dem Testlauf mal ein Serial Log erstellen
AAL schrieb:> habe nun die Hercules Terminal Software ausprobiert, mit Erfolg! Hier> antwortet die Hardware. Getestet in einer frischen VM in der die> Original Software nicht installiert ist, es geht also definitiv ohne das> irgendwas mitmischt...
Handshake ist OFF - sieht also wie eine total triviale serielle
Verbindung ohne Schnickschnack aus, was passiert wenn du den Haken bei
DTR weg machst (geht das?)
cppbert schrieb:> bitte lass dir von dem Testlauf mal ein Serial Log erstellen
Hier nun der Log des Serial Monitors beim kommunizieren mittels Herules
Terminal:
https://docdro.id/YTQGU3T
Bitte vom Datum des Logs nicht beirren lassen, musste einen Snapshot in
der VM wiederherstellen, in der ich das teste...
Hier ist mir, außer mehrere Seiten Get_Modemstatus (zwischen öffnen des
Ports und senden von "55 d3") aufgefallen, dass "Serial_Set_Wait_Mask"
bei meiner VB Anwendung komplett fehlt. Ob das tatsächlich die Ursache
ist, und wie ich das in VB einstellen kann, habe ich noch nicht
herausgefunden, aber viel mehr Möglichkeiten bleiben nicht... das habe
ich nochmal als Screenshot angehängt.
cppbert schrieb:> Handshake ist OFF - sieht also wie eine total triviale serielle> Verbindung ohne Schnickschnack aus, was passiert wenn du den Haken bei> DTR weg machst (geht das?)
Haken entfernen geht. Tatsächlich reagiert die Hardware auch dann... ist
egal, ob DTR gesetzt ist, oder nicht.
Die Anwendung in VB 2019 statt 2008 nachgebaut habe ich auch nochmal,
ebenfalls ohne Erfolg.
Vielleicht gibt dieser Log nun Aufschluss.
Ich habe keine Ahnung was du falsch machst - die serielle Konfiguration
ist sehr einfach - Hardware ist OK und funktioniert, Original und
Terminal-Programme gehen - muss was irgendwas in deinem Code sein
AAL schrieb:> Hier ist mir, außer mehrere Seiten Get_Modemstatus (zwischen öffnen des> Ports und senden von "55 d3") aufgefallen, dass "Serial_Set_Wait_Mask"> bei meiner VB Anwendung komplett fehlt.
Das kann nicht sein. Siehe:
https://referencesource.microsoft.com/#system/sys/system/io/ports/SerialStream.cs,b120632fda7c01ba
Zeile 764
Das passiert das.
Allerdings ist das DotNet4.8, und wie ich sehen konnte, hat Microsoft in
den letzten Jahren deutlich nachgebessert, der Code war früher noch viel
grausiger. Aber, wie auch immer, das SetCommMask an dieser Stelle war
jedenfalls schon immer drin. Muss es auch sein, sonst würde die Events
des SerialPort ja nicht funktionieren können. Das tun sie aber
mindestens seit ca. 2004, da habe ich das Teil das Teil nämlich erste
Mal benutzt. Das muss noch DotNet1.1 oder 2.0 gewesen sein, weiß ich
nicht mehr genau.
Zusammenfassend:
Das Problem ist dein Code. Vermutlich eine krude Mischung der Verwendung
von synchronen und asynchronen Zugriffsmethoden des SerialPort. Das wäre
der übliche Fehler der Laienprogrammierer...
cppbert schrieb:> Ich habe keine Ahnung was du falsch machst - die serielle> Konfiguration ist sehr einfach - Hardware ist OK und funktioniert,> Original und Terminal-Programme gehen - muss was irgendwas in deinem> Code sein
Kannst noch mal ein sauberes Log von deinem Programm machen, damit man
das direkt mit Hercules vergleichen kann
Btw: im ReactOs/Wine Src
(https://doxygen.reactos.org/d2/d06/dll_2win32_2kernel32_2wine_2comm_8c_source.html)
kannst du die WinApi C Implementierungen sehen wie die IOCTLS genutzt
werden, alles simpler WinApi kram, nichts besonderes
cppbert schrieb:> weitere Idee: hier ist ein VS2005/VB.Net Beispiel Serial Terminal mit> Source-Code>> http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm>> sollte es damit gehen dann hast du was zum ausschlachten
Das ist erstens nicht C#, sondern VB.net und zweitens auch nicht völlig
korrekt. Es droht eine race condition beim Schließen des Fensters. Um
diese zu vermeiden, ist die Zeile mit BeginInvoke() durch ein Try..Catch
(keine weitere Fehlerbehandlung nötig) zu sichern.
Aber vom Konzept her ist der Beispielcode schon OK. So ungefähr sollte
die Anwendung des SerialPort in GUI-Programmen aussehen, wobei das
ReadLine natürlich durch eine der anderen Lesemethoden zu ersetzen wäre,
wenn man nicht mit Texten, sondern mit Binärdaten hantiert.
Soooo, danke nochmal an alle... mit dem Beispiel Serial Terminal
inklusive Projektdateien von cppbert, funktioniert es auch... werde das
nun als Grundgerüst nehmen, und entsprechend anpassen.
Heute Abend werde ich trotzdem nochmal meinen gesamten Code hier
reinstellen, der aus wenigen Zeilen besteht. Vielleicht fällt ja
jemandem auf, was ich falsch gemacht habe...
Ich hätte auch selbst auf das testen einer Terminal Software aus einem
vb Beispiel kommen können... ;)
Immerhin ist das Problem nun nach 10 Tagen gelöst.
Danke euch
AAL schrieb:> Soooo, danke nochmal an alle... mit dem Beispiel Serial Terminal> inklusive Projektdateien von cppbert, funktioniert es auch... werde das> nun als Grundgerüst nehmen, und entsprechend anpassen.>> Heute Abend werde ich trotzdem nochmal meinen gesamten Code hier> reinstellen, der aus wenigen Zeilen besteht. Vielleicht fällt ja> jemandem auf, was ich falsch gemacht habe...>> Ich hätte auch selbst auf das testen einer Terminal Software aus einem> vb Beispiel kommen können... ;) Immerhin ist das Problem nun nach 10> Tagen gelöst.>> Danke euch
Wir sind wenn dann nur an deinem Fehler, den du hoffentlich bald findest
interessiert :)
Um dieses Thema nun abzuschließen...
ich verwende nun das Beispiel Terminalprogramm und baue von diesem auf
wie ich es brauche...
ein letzter Screenshot im Anhang, von meinem vollständigen Code, mit dem
es nach wie vor nicht geht.
Reicht "Imports System.IO.Ports" vielleicht nicht? Keine Ahnung.
Vielleicht fällt im Code ja noch jemandem was auf.
Da mit dem Terminalprogramm in VB nun aber alles geht, muss nicht weiter
gerätselt werden ;)
Danke euch.
Wann startet Timer1?
Wenn er seit Beginn der Form läuft, weiß ich nicht wie das Serial Read
reagiert wenn Button1 noch nicht geklickt wurde und der Port nicht offen
ist.
Wenn er bei Beginn aus ist müsstest du ihn in Button1_Click aktivieren?
ReadExisting "Liest alle sofort verfügbaren Bytes auf Grundlage der
Codierung sowohl im Stream als auch im Eingabepuffer des
SerialPort-Objekts." (MSDN)
Du erwartest aber eine binäre Rückgabe "00", keine Ahnung wie die als
String encodiert wird.
Da du nur 1 Byte erwartest (solange du nur die erste Anfrage schickst,
richtig?) ist ReadByte vielleicht besser.
Außerdem interessant:
https://docs.microsoft.com/de-de/dotnet/api/system.io.ports.serialport.readbyte?view=dotnet-plat-ext-3.1
Gehen Sie bei der Verwendung von und mit Bedacht vor ReadByte ReadChar .
Das Wechseln zwischen Lese-und Lesezeichen kann dazu führen, dass
zusätzliche Daten gelesen werden und/oder ein anderes unbeabsichtigtes
Verhalten hat. Wenn zwischen dem Lesen von Text und dem Lesen von
Binärdaten aus dem Stream gewechselt werden muss, wählen Sie ein
Protokoll aus, das die Begrenzung zwischen Text-und Binärdaten
sorgfältig definiert, z. b. das manuelle Lesen von Bytes und das
Decodieren der Daten.
Mit anderen Worten: Da du es hauptsächlich/nur mit Binärdaten zu tun
hast, Vorsicht mit Funktionen die versuchen die gelesenen Daten in Char
oder String umzuwandeln. Auf Dauer würde ich für dein Problem daher
ReadByte oder Read(array_ptr, offset, count) verwenden.
PS: Wenn du Englisch kannst schaue die Hilfeseiten lieber auf Englisch
an, die maschinelle Übersetzung ist Schmarrn wie man sieht.
AAL schrieb:> ein letzter Screenshot im Anhang, von meinem vollständigen Code, mit dem> es nach wie vor nicht geht.
abenteuerlicher Read Timer - ohne das man sieht wo der gestartet wird -
sollte frühestens nach dem Open von dem Port passieren sonst kommt da
bestimmt nur Grütze raus
Ich kann mir nicht wirklich vorstellen, dass es damit etwas zu tun hat.
Denn zum Empfangen kommt es ja gar nicht erst. Dann müsste das senden ja
zumindest so weit gehen, dass man im Serial Monitor eine Reaktion von
der Hardware sieht... eben nochmal nachgebaut ohne Timer. Nur Button und
Serial Port mit "Dim data() As Byte = {&H55, &HD3}
SerialPort1.Write(data, 0, data.Length)", geht auch nicht.
Werde nun wie gesagt das Terminalprogramm von VB nutzen und dieses
entsprechend umbasteln...
Wenn das alles fertig ist, versuch ich nochmal rauszufinden, warum
meines nicht funktioniert.
Lies mal den Link.
Ist ein schöner Code.
https://www.vb-paradise.de/index.php/Thread/124371-Serial-Port/
Da siehst du nämlich das du in deinen Code einiges Vergessen hast. Schau
dir mal den DIM-BEFEHL des PORT an. Schöne viele Parameter. ;)
Das Problem bei Serial ist, das die Bits hintereinander laufen. Tanzt da
eins aus der Reihe fallen alle um, genauer gesagt sie werden
Fehlinterpretiert.
Es kommt also nicht nur darauf an das du die richtigen Bits sendest,
sondern auch die RICHTIGEN Steuerbits. Bei dir fehlt z.b. die PARITY Was
bedeutet :
Grundsätzlich werden immer 10 !!! Bits übertragen. 8 echte, ein Prüfbit,
und ein Stopbit. Das Paritybit entscheidet ob die Anzahl der 1 er Bits
gerade oder Ungerade ist. Bei gerader Parity und ungerader Anzahl der 8
Bits wird das Prüfbit 1 gesetzt (damit wieder alle Gerade sind)
ansonsten 0.
Wie gesagt, stimmt die Reihe nicht, verschluckt sich der Empfänger und
gehst auf Störung.
Timeout und so Spielchen, sagen den System wann es auf "Störung" gehen
soll.
Termial-Programme sind weniger Stress anfällig und handeln was aus,
beziehungsweise akzeptieren die Einstellungen die das Prg. sendet.
Es gibt in VB kein NICHTS. JEDER Parameter hat ein Grundwert(Default).
Und bei dir ist der Grundwert nicht der den deine Hardware will. Ergo
klappt es nicht.
Eine Hardware diskutiert nicht. Sie will das haben was der Programmierer
will und das war's. Diskutieren kostet Speicherplatz. Und der ist ein
einen Meßgerät knapp.
AAL schrieb:> ein letzter Screenshot im Anhang, von meinem vollständigen Code, mit dem> es nach wie vor nicht geht.>> Reicht "Imports System.IO.Ports" vielleicht nicht? Keine Ahnung.> Vielleicht fällt im Code ja noch jemandem was auf.
Ja, darin gibt es nichts, was irgendwas empfangen könnte...
Troll, dammichter!
c-hater schrieb:> Ja, darin gibt es nichts, was irgendwas empfangen könnte...>> Troll, dammichter!
Der Serial Monitor hätte dennoch anzeigen müssen, das die Hardware
reagiert, wenn die Zeichenfolge ans "Anfrage" gesendet wird. Es ging
erstmal nicht drum, Daten anzuzeigen, weil erstmal nur "00" von der
Hardware kommt, quasi als Zeichen das die Anfrage zur Verbindung
akzeptiert wurde.
Nochmal einen Schritt zurück gedacht...
Woran machst du fest, ob die Kommunikation funktioniert hat oder nicht?
Wenn ich dich richtig verstehe:
- Das Senden von 2 Bytes (55 d3), unabhängig vom Lesen der Antwort (00),
triggert kein bestimmtes Verhalten am Gerät -> von außen also keine
Erfolgsbewertung, richtig?
- Das Senden der 2 Byte + Lesen von 00 zeigt dir erfolgreiche
Kommunikation, sowohl im Log der Hersteller-Anwendung als auch im Log
mit dem Serial Monitor
- In deinem Programm funktionieren jetzt alle Schritte inkl. Senden der
2 Byte, aber du siehst im Log kein Read 00 und schließt daraus
Nichterfolg?
Ohne jetzt die Funktion des "Serial Port Monitor" genau zu kennen
(scheint ein nützliches Tool, muss ich mir merken), würde ich nicht
davon ausgehen, dass dort ein Read (00) auftaucht wenn die Anwendung,
die er belauscht, nicht explizit ein Read ausführt.
Außer der mittlerweile als Fehlerquelle ausgeschlossenen
Handschake/DTR/etc-Geschichten ergibt sich aus den oben geposteten Logs
nach dem erfolgreichen Senden der 2 Byte nur noch folgender
Unterschied:
- Die erfolgreiche Anwendung setzt die Wait mask auf RXCHAR, fragt nach
der Waitmask (GET_WAIT_MASK, irrelevant), fragt nach dem Comm-Status,
stellt fest 1 Byte ist in der IncomingQueue und führt schließlich ein
IRP_MJ_READ aus, was erfolgreich 00 zurückgibt
- Deine (scheinbar nicht erfolgreiche) Anwendung setzt die Wait mask
mehrfach auf RXCHAR (warum auch immer, einmal sollte reichen, liegt
evtl. an .net) aber fragt nicht nach der Anzahl verfügbarer Bytes,
geschweigedenn liest sie.
-> Für mich sieht es so aus als würde deine App schon gehen, nur wird
das Read() nie aufgerufen und dann taucht meiner Erwartung nach auch
kein Read im Log auf.
Da die Antwort des Geräts quasi instantan kommt (<1sec nach Senden der 2
Byte) verzichte mal auf den Timer und mach direkt in Button1_Click nach
dem Write ein ReadByte (Timeout des SerialPort auf 1sec setzen).
Lenny D. schrieb:> -> Für mich sieht es so aus als würde deine App schon gehen, nur wird> das Read() nie aufgerufen und dann taucht meiner Erwartung nach auch> kein Read im Log auf.
Ist mir auch erst jetzt aufgefallen, da ist gar kein Read im Log, der
taucht auf so bald du die Readfunktion aufrufst, ein Read-Logeintrag
erscheint nicht wenn einfach nur Daten anliegen
Ich wäre auch nie darauf gekommen den Read so komisch ab zu setzen,
warum hast du nicht einfach das Read direkt nach dem Write gemacht? Ist
das nicht das erste was man testet, und ich bin auch zumindest davon
ausgegangen das du schon mal geprüft hast das dein Read auch wirklich
ausgeführt wird
cppbert schrieb:> Ich wäre auch nie darauf gekommen den Read so komisch ab zu setzen,> warum hast du nicht einfach das Read direkt nach dem Write gemacht? Ist> das nicht das erste was man testet, und ich bin auch zumindest davon> ausgegangen das du schon mal geprüft hast das dein Read auch wirklich> ausgeführt wird
Sein READ ist in einen Timer.
Was so was ähnliches wie ein Interrupt ist. Alle X-Zeit wird die
Timer_routine aufgerufen, und abgefragt ob da was kommt. Würde ich auch
so machen.
Testen kann man das mit den Befehl *print "timer"*. Der schreibt dann
einfach jedes mal "Timer" auf die Form.
Der Vorteil dieser Technik ist, das wenn das Teil Daten liefert, sie
immer abgerufen werden. Der Nachteil ist, das seine Routine mist sein
kann.
1.) Ändere den Befehl in der Timer Rountine.
if len(Richtextbox1.text) > 500 then
Richtextbox1.text = "" ' wenn in der Box 500 Zeichen sind leere sie
end if
Richtextbox1.text = Richtextbox1.text + Data_receivid + vbcrlf
Das führt dazu das die Textbox NICHT bei jeden Timeraufruf geleert wird.
Ist der Timer zu kurz eingestellt kann es passieren das die Box
schneller leer ist, wie voll.
Ist der Timer zu lang eingestellt, verlierst du Daten, da der Chip nur
ein kleinen Puffer hat.
Und stell die Parity ein. !!!!
Schlaumaier schrieb:> Sein READ ist in einen Timer.> Was so was ähnliches wie ein Interrupt ist. Alle X-Zeit wird die> Timer_routine aufgerufen, und abgefragt ob da was kommt. Würde ich auch> so machen.
das ist hier jedem klar - nur eben läuft scheinbar sein Read nicht
Private Sub timer_starten_Click(sender As System.Object, e As
System.EventArgs) Handles timer_starten.Click
if my_Timer.Enabled = false then
my_Timer.Interval = 1000 ' setzt die Intervall-Zeit
my_Timer.Enabled = True ' aktiviert den Timer
timer_starten.text ="Timer aktiv"
exit sub
end if
if my_Timer.Enabled = True then
my_Timer.Enabled = false ' aktiviert den Timer
timer_starten.text ="Timer inaktiv"
exit sub
end if
end sub
Dieser Code in einen Button mit den namen timer_starten kopieren.
Nach klicken auf den Button, ändert sich der Text den Button auf den
Status den Timers.
Teste kann man das mit ein Haltpunkt in der my_timer sub.
AAL schrieb:> Der Serial Monitor hätte dennoch anzeigen müssen, das die Hardware> reagiert, wenn die Zeichenfolge ans "Anfrage" gesendet wird.
Was hätte der Monitor denn anzeigen sollen? Wo genau lauscht er?
Ohne das zu wissen (und du weißt darüber offensichtlich garnix, ich
allerdings auch nicht, weil ich diesen "Serial monitor" nicht kenne),
ist das völlig nichtssagender Bullshit...
Fakt ist jedenfalls, dass es sicher viele Zehntausende Anwendungen gibt,
die mit dem SerialPort (trotz aller seiner Schwächen) was gebacken
bekommen. Du aber nicht.
Also woran wird das wohl liegen?
c-hater schrieb:> ist das völlig nichtssagender Bullshit...
Wenn die Hardware bei einer bestimmten Zeichenfolge ein "00" als
antwortet sendet, dann bin ich davon ausgegangen, dass dieses im Serial
Monitor ersichtlich ist, wenn der entsprechende Port überwacht wird,
auch wenn meine Software noch keine funktionierende Read/Recieve
Funktion hat, das war scheinbar falsch...
c-hater schrieb:> Fakt ist jedenfalls, dass es sicher viele Zehntausende Anwendungen gibt,> die mit dem SerialPort (trotz aller seiner Schwächen) was gebacken> bekommen. Du aber nicht.>> Also woran wird das wohl liegen?
Das hilft wirklich sehr, nachdem hier schon mindestens 5 Leute den Log
gesehen, und sich ebenfalls keinen Reim drauf machen konnten...
Lenny D. schrieb:> Hast du das Problem denn lösen können? Würde mich der Vollständigkeit> halber noch interessieren...
Lag wohl tatsächlich daran, dass keine funktionierende Read Funktion
vorhanden war...
VB ist OBJEKT-Orientiert.
Einfach gesagt ohne Interrupt-Routinen wird einfach das "Mini-Prg" in
jeder Sub aufgerufen.
Er hat zwar die Sub für den Timer geschrieben, aber NICHT den Interrupt
deklariert und GESTARTET. Siehe Code oben.
Einfach gesagt, die Hardware hat den Serial-Chip vollgemüllt bis der
Puffer übergelaufen ist, und die Bits hinten raus gefallen sind, weil
sie keiner abgeholt hat.
Mit einen TIMER-Interrupt wird dann nach ZEIT X die Timer_routine
angesprungen und die Daten abgeholt (Read-Befehl), verarbeitet, und
weiter mit nix tun bzw. weiter in der normalen gerade auszuführenden
SUB.
Ist übrigens bei der Arduino-Programmierung das selbe. Man vergisst
immer den INI-Befehl. Ist mir auch schon 1-2 x passiert.