Cypress Enable - API Zugriff nur einmal möglich.

  • Sonstige

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von human.

    Cypress Enable - API Zugriff nur einmal möglich.

    Moin

    ich möchte Mittels API Schnittstelle und entsprechender dll meinen über USB angeschlossenen Servoregler ansprechen.
    Hier zu verwende ich Cypress Enable, da diese auch in meiner Steuerungssoftware eingebettet ist.
    Cypress ist stark an VB angeleht, nur hat es weniger Funktionen.

    Ich habe mich ein wenig in Sachen API eingelesen. Also Begriffe wie UnManage, BSTR, Wrapper ect. hab ich schon mal gelesen :) .

    Den Zugriff auf den Regler, das lesen und schreiben von Parametern habe ich nach vielen Versuchen (endlich) hinbekommen.

    Leider kann ich meinen Code nur einmal durchlaufen lassen, da ich beim zweiten Durchlauf einen Fehler aus der dll (Internal error <setComPar>) bekomme.
    Meine Vermutung, es hängt mit dem Pointer auf das "communication session object" oder dem Thread!? zusammen.
    Ich muss den Scripteditor schließen und erst nach erneutem öffnen kann ich den Code einmalig fehlerfrei abarbeiten.
    Kann man nicht den Pointer speichern? Mit strPtr und CopyMemory in der nächsten Laufzeit wiederholen?
    Leider hat Cypress kein strPtr und die API von varPtr ist ja nicht das selbe.

    Hier erstmal das Reference Manual,
    der C# Header,
    ... und mein Code für die Initialisiereung:

    Code:
    Cypress Enable

    Visual Basic-Quellcode

    1. 'Cypress Enable Code
    2. Declare Function openDCE Lib "C:\HIWIN\dce\toolswin\winkmi\mpi.dll" (ByVal pwdin As String,ByVal cnfname As String) As Long
    3. Declare Function setComPar Lib "C:\HIWIN\dce\toolswin\winkmi\mpi.dll" ( ByVal port As Integer, _
    4. ByVal baudrate As Integer, _
    5. ByVal mode As Integer, _
    6. ByVal trid As Integer, _
    7. ByVal rcid As Integer, _
    8. ByVal cancanbaudrate As Integer, _
    9. ByVal msgStand As Integer, _
    10. ByVal canpipelevel As Integer, _
    11. ByVal timeout As Integer, _
    12. ByVal locktime As Integer, _
    13. ByVal iternum As Integer, _
    14. ByVal pcom As Long) As Long
    15. Declare Function closePort Lib "C:\HIWIN\dce\toolswin\winkmi\mpi.dll" (ByVal pcom As Long) As Long
    16. Declare Function deleteDCE Lib "C:\HIWIN\dce\toolswin\winkmi\mpi.dll" (ByVal pcom As Long, ByVal closeMFC As Integer) As Long
    17. Declare Function GetVarN Lib "C:\HIWIN\dce\toolswin\winkmi\mpi.dll" ( ByVal varName As String, _
    18. ByRef pdata As Long, _
    19. ByVal slave As Integer, _
    20. ByVal pcom As Long) As Long
    21. Dim pcom As Long
    22. Dim pdata As Double, tmpPdata As Double
    23. Dim pwdin As String, cnfname As String
    24. Dim slave As Integer, po As Integer, tmpGetVarN As Integer
    25. pwdin = "c:\hiwin\dce\"
    26. cnfname = "lightening.dce"
    27. slave = 0
    28. pcom = openDCE(pwdin,cnfname) 'A pointer points to a communication session object. This pointer may be supplied to all other functions as the parameter pcom.
    29. po = setComPar(7,8,1,0,0,0,0,0,50,200,6,pcom) 'setzt und öffnet den Port
    30. tmpGetVarN = getVarN("X_enc_pos",pdata,0,pcom) 'einfache Abfrage eines Parameters im Regler
    31. tmpPdata = pdata
    32. If tmpGetVarN = 0 Then
    33. Print tmpPdata
    34. Else
    35. Print errStr(tmpGetVarN)
    36. End If
    37. Call closePort(pCom)
    38. Call deleteDCE(pCom,0)
    39. Function errStr(errcode As Integer) As String
    40. Dim tmpErrStr As String
    41. Select Case errcode
    42. Case 0
    43. 'tmpErrStr = "OK!"
    44. Case 31
    45. tmpErrStr = "Slave number out of range (0~31)!"
    46. Case 101
    47. tmpErrStr = "Read failed!"
    48. Case 102
    49. tmpErrStr = "Write failed!"
    50. Case 103
    51. tmpErrStr = "Frame error!"
    52. Case 104
    53. tmpErrStr = "No answer!"
    54. Case 105
    55. tmpErrStr = "Check sum error!"
    56. Case 106
    57. tmpErrStr = "Size out of range!"
    58. Case 107
    59. tmpErrStr = "Parity error!"
    60. Case 108
    61. tmpErrStr = "Over run error!"
    62. Case 109
    63. tmpErrStr = "Buffer over flow!"
    64. Case 110
    65. tmpErrStr = "Frame error!"
    66. Case 111
    67. tmpErrStr = "Abort!"
    68. Case 112
    69. tmpErrStr = "Net sync error!"
    70. Case 113
    71. tmpErrStr = "Can error!"
    72. Case 114
    73. tmpErrStr = "Answer size error!"
    74. Case 115
    75. tmpErrStr = "Start byte error!"
    76. Case 116
    77. tmpErrStr = "Master boot!"
    78. Case 117
    79. tmpErrStr = "EtherCAT mega-ulink error!"
    80. Case 118
    81. tmpErrStr = "EtherCAT mega-ulink in test mode!"
    82. Case 151
    83. tmpErrStr = "Communication FIFO full!"
    84. Case 152
    85. tmpErrStr = "Size transmit error!"
    86. Case 153
    87. tmpErrStr = "Communication is not available!"
    88. Case 154
    89. tmpErrStr = "No connection to remote side!"
    90. Case 155
    91. tmpErrStr = "Local communication blocked!"
    92. Case 156
    93. tmpErrStr = "Communication failed!"
    94. Case 157
    95. tmpErrStr = "No connection to remote side via Ehernet!"
    96. Case 158
    97. tmpErrStr = "EtherCAT mega-ulink slave not respond!"
    98. Case 201
    99. tmpErrStr = "Unrecognized variable!"
    100. Case 202
    101. tmpErrStr = "Slave name not defined!"
    102. Case 203
    103. tmpErrStr = "The list contain one or more unrecognized variables in slave!"
    104. Case 204
    105. tmpErrStr = "Variable is not short type!"
    106. Case 220
    107. tmpErrStr = "Variable is not a 64 bit type!"
    108. Case 221
    109. tmpErrStr = "Variable is a 64 bit type!"
    110. Case 251
    111. tmpErrStr = "Unrecognized function in slave!"
    112. Case 252
    113. tmpErrStr = "Slave name not defined!"
    114. Case 260
    115. tmpErrStr = "PDL function is not running in slave!"
    116. Case 261
    117. tmpErrStr = "Slave is in boot mode!"
    118. Case 262
    119. tmpErrStr = "Task number out of range!"
    120. Case 263
    121. tmpErrStr = "Slave in not in boot mode!"
    122. Case 270
    123. tmpErrStr = "Write buffer denied!"
    124. Case 271
    125. tmpErrStr = "Buffer size to set out of range!"
    126. Case 272
    127. tmpErrStr = "Read variable denied!"
    128. Case 273
    129. tmpErrStr = "Number of variables out of range!"
    130. Case 274
    131. tmpErrStr = "Expected answer length too big!"
    132. Case 275
    133. tmpErrStr = "Support only array access type 16/32 bits!"
    134. Case 300
    135. tmpErrStr = "Scope restart!"
    136. Case 301
    137. tmpErrStr = "Scope support only 2 variables!"
    138. Case 500
    139. tmpErrStr = "Link busy!"
    140. Case 501
    141. tmpErrStr = "No support!"
    142. Case 502
    143. tmpErrStr = "Master boot!"
    144. Case 503
    145. tmpErrStr = "No slave!"
    146. Case 504
    147. tmpErrStr = "Link error!"
    148. Case 505
    149. tmpErrStr = "Slave error!"
    150. Case 506
    151. tmpErrStr = "Invalid address!"
    152. Case 525
    153. tmpErrStr = "Server busy!"
    154. Case 600
    155. tmpErrStr = "State number out of range!"
    156. Case 601
    157. tmpErrStr = "Unrecognized state in slave!"
    158. Case 602
    159. tmpErrStr = "Slave name not defined!"
    160. Case 651
    161. tmpErrStr = "No support id communication command!"
    162. Case 801
    163. tmpErrStr = "Extra parameters!"
    164. Case 802
    165. tmpErrStr = "Missing parameters!"
    166. Case 803
    167. tmpErrStr = "Unrecognized command!"
    168. Case 1000
    169. tmpErrStr = "Communication driver is NULL!"
    170. Case Else
    171. tmpErrStr = "Sonstiger Fehler!"
    172. End Select
    173. errStr = tmpErrStr
    174. End Function



    Vermutlich ist meine Vorgehensweise für diese Art von Abfragen ungeeignet.
    Solche API Zugriffe laufen doch normalerweise in einem Main-Thread!? in einer Schleife?
    Und von dem werden dann die Funktionen aus gestartet?

    Muss ich vielleicht mit Objekten und Klassen Arbeiten?
    In der Hinsicht habe ich noch nicht so viel gemacht/Erfahrung.

    Ich würde mich über Tipps und Ratschläge freuen, die mich weiter voran bringen können.

    Gruß
    Robert
    Dateien
    • MPI_V1.51.pdf

      (1,81 MB, 364 mal heruntergeladen, zuletzt: )
    • mpint.h.txt

      (15,54 kB, 235 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „human“ ()

    @human Willkommen im Forum. :thumbup:
    Ich nehme mal an, dass Deine Deklarationen zumindest teilweise vom alten VB6-Format sind, da sind ggf. Parameter falsch deklariert.
    Möglicherweise ist ByVal pcom As Long nun ein ByVal pcom As IntPtr.
    Das würde wahrscheinlich alle Long-Parameter betreffen bzw. MDCE *pcom und auch char *ipstr in der Text-Datei.
    Probierma, für diese DLL vom Hersteller die .NET-Deklarationen zu bekommen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin

    @RodFromGermany
    Vielen Dank.

    IntPtr oder IpStr werden von Cypress leider nicht unterstützt.

    Ich denke das die jetzigen Deklarationen nicht all zu verkehrt sind, da ich beim ersten Code-Durchlauf ja keinen Fehler bekomme und vollen Zugriff auf den Regler habe.
    Nur beim zweiten Durchlauf ist bei "setcompar" Schluss (Fehler).

    Den Hersteller habe ich heute mal wegen der vb.net Deklarationen angeschrieben.
    Viel Hoffnung habe ich jedoch nicht, das die Privatpersonen supporten.
    Deren Produkte bekomme ich auch nur über einen Händler.

    Hat noch jemand eine Idee?
    Mein Bauchgefühl sagt mir, das irgendwie mit dem pointer von "openDCE" zusammen hängen könnte.

    Gruß
    Robert

    human schrieb:

    IntPtr oder IpStr werden von Cypress leider nicht unterstützt.
    IntPtr wird von .NET unterstützt.
    In der nativen DLL kann stehen was da will, es muss nur korrekt auf .NET übertragen werden.
    Gugst Du hier: Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin

    sorry für das verspätete Feedback.
    Danke für den Link.
    Also ist dann VB.net die Verbindung zwischen Cypress und der dll?

    Mal etwas anders ...
    gibt es eine API für die Funktion strPtr oder eine Möglichkeit um an die String-Adresse einer Variable zu kommen, also ähnlich varPtr?

    Gruß
    Robert
    @human Was trennt Cypress und die dll?
    Zu den Strings gugst Du hier: Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit
    Hatten wir doch schon. :/
    Der IntPtr ist der Pointer. Wenn Du wie in C / C++ mit *var = bla arbeiten willst, musst Du C# und unsafe programmieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin

    RodFromGermany schrieb:

    Was trennt Cypress und die dll?

    Eigentlich nichts. Bis auf das oben beschriebene Verhalten.

    Bin etwas irritiert. Wahrscheinlich verstehe ich noch nicht so ganz deinen Lösungsansatz.
    Ich dachte das ich ohne VB.net auskommen könnte und mit ein paar eigenen Funktionen die Probleme Mittels Cypress in den Griff bekomme.

    Gruß
    Robert

    human schrieb:

    ohne VB.net ... mit ein paar eigenen Funktionen
    in welcher Programmiersprache?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin

    hab den Fehler gefunden!

    Ich hatte mich schon die ganze Zeit gewundert, warum die Funktion "openPort" nicht meine vorherige Verbindung aufruft.
    Mit der Funktion "getcompar" habe ich dann die total verkehrten Einstellungen gesehen.

    Im Library Reference Manual habe ich dann gelesen das es zwei save Files gibt,
    die jeweils die Portsettings der letzten Verbindung zum Regler beinhalten.
    Eine für RS232/USB und eine für Ethernet.
    Hab die für Ethernet mit der des RS232/USB überschrieben.

    Juhu, bin sooo erleichtert das es nun endlich funktioniert.

    Gute Nacht
    Robert