Probleme beim Empfangen von Modbus-Daten

  • Hallo,

    ich bin mal wieder beim Versuch verschiedene Janitzas per Modbus auszulesen. Mein Versuch erst mal nur einen Janitza auszulesen funktioniert teilweise.

    Bei manschen "Starts" bekomme ich die angefrageten Werte - bei den nächsten "Starts" ist die Antwort zu kurz und die falschen Register werden ausgelesen.

    Bild "matrix_ok" zeigt einen gelungenen Versuch 64 Register (float).

    Bild "matrix_falsch" zeigt einen misslungenen Versuch 64 Register (float).

    Ich habe viel rumprobiert - komme aber zu keiner Lösung. Vielen Dank schon mal!

  • Hi autoit_dau,

    das Review deines Skripts dauert ein wenig, aber vielleicht kannst du mir und den Anderen hier noch etwas helfen, indem du die INI-Datei (@ScriptDir & "\janitza.ini") oder eine Test-Ini bereit stellst, welche wir zur Fehlersuche verwenden können 😀 ?!

    • Ansonten gilt ganz allgemein Global nur außerhalb von Funktionen zu verwenden, da andernfalls der "Au3Check" Warnungen schmeißt.
    • Des Weiteren fehlt die Deklaration von $timer und $hStarttime.
      • Oder sollte $timer eher $hTimer aus Zeile 41 sein?!
    • Ist das Skript nur ein Auszug aus einem größeren oder warum sind so viele Includes (Libraries) eingebunden/vorhanden?
      • Nötig sind anscheinend nur:
    AutoIt
    #include-once
    #include <Array.au3>
    #include <Timers.au3>
    #include <WinAPI.au3>

    💡 Und noch etwas: Der untere Bereich ab Zeile 271 deines Skriptes wird nie erreicht. Denn nach deiner While Schleife gehst du ins Exit.

    Viele Grüße
    Sven

  • Moin,

    wie erzeugt man eine so unüberscichtliche Codestruktur?

    Mein Wissen über den Modbus beschränkt sich auf das Ergebnis von 30 Minuten Google-Studium, aber

    AutoIt
        _ModbusTCP_Send($mainsocket, "0x" & Hex($TI, 4) & "0000" & Hex($iBytesToSend, 5)  & $s_uID & Hex($FC2, 2) & Hex($iStart, 4) & Hex($iNum, 4)) ;; komisch Hex($iBytesToSend, 4) ist sonst OK

    4 ist nicht 'sonst' OK, 4 ist 'einzig und allein' OK. Bei 5 sind alle folgenden Bytes um 1 verschoben. Es würde mich sehr wundern, wenn dabei etwas vernünftiges zurückgegeben wird.

  • Danke,

    genau hier lag auch der Fehler. Ich musste in der ini die Stationsnummer ($s_uID) in Anführungszeichen setzen z.B. "02" und nicht 02

    Ich hatte die gesendeten Daten verglichen. Als die Kommunikation funktioniert hatte war eine "0" mehr im Sendeprotokoll. Dann hab ich geschraubt.....


    Danke erst mal, ich versuche weiter zu kommen...

    Grüße!

  • Danke erst mal, ich versuche weiter zu kommen...

    Ja viel Erfolg dabei autoit_dau. Falls du weitere Fragen hast schlage ich vor, dass wir hier, gemeinsam mit dir Stück für Stück an einzelnen Funktionalitäten arbeiten und so nach und nach ein Skript erstellen, denn wie Velted es so treffend ausgedrückt hat 😅 , gibt es bei der Struktur deines Skriptes Verbesserungspotenzial. Dies machte es mir zumindest auch nicht so einfach, dein Code zu sichten (ein Review durchzuführen). Nur als Möglichkeit => "it's up to you".

    Viele Grüße
    Sven

  • Es ist ja nicht nur die Strucktur, sondern leider auch GLobale Variablen, die Lokal in einer funktion deklariert werden usw. (macht man nicht).

    Wobei ich auch, sowohl weil ich von der ModBus-Ansteuerung zu wenig Kenntnis habe, als auch bei diesem Horror von Strucktur/Formatierung das Thema auch gleich mal verworfen habe.

  • [...] sondern leider auch GLobale Variablen, die Lokal in einer funktion deklariert werden usw. (macht man nicht) [...]

    Siehe meinen #2 Beitrag 😅 . Ich glaube umso dankbarer wird autoit_dau sein, wenn wir ihn helfen 😇 .

    Viele Grüße
    Sven

  • Ja, hab ich gesehen.

    Helfe auch gerne was die Strucktur angeht ( autoit_dau ), die finale Strucktur ist ja so oder so Benutzerspezifisch leicht variabel, sollte aber lesbar sein.

    Ich denke einige Zeilenumbrüche kommen ggf. auch beim kopieren aus dem Editor hier auf die Webseite. Aber auch da sollte man vor dem Posten nochmal nachsteuern damit man damit was anfangen kann ohne den kompletten Code erstmal formatieren zu müssen wenn man helfen möchte.

  • Moin,

    ich habe noch ein paar Minuten Google nachgelegt. Wenn Du diesen Artikel noch nicht kennst, könnte er Dir helfen.

    Ich musste in der ini die Stationsnummer ($s_uID) in Anführungszeichen setzen z.B. "02" und nicht 02

    Das stimmt so nicht. In der Nachricht belegen die Geräteadresse (ID) und der 'funktionale Code' (FC) jeweils ein Byte und beide sind numerisch.

    In der Hex-Darstellung brauchst Du für ein Byte zwei Zeichen. Aus dem numerischen Wert 2 wird dabei 02. Wenn Du den Wert als Text/String mit zwei Zeichen übergibst, klappt das nur bis zur Zahl 9, weil der Text"09" den zwei Halbbytes für den Wert entspricht. Ab "10" wird das aber falsch. Die hexadezimale Darstellung für die Zahl 10 ist 0A. Wenn Du stattdessen "10" übergibst, entspricht das dem Wert 16. Deshalb:

    AutoIt
    _ModbusTCP_Send($mainsocket, "0x" & Hex($TI, 4) & "0000" & Hex($iBytesToSend, 4) & Hex($s_uID, 2) & Hex($FC2, 2) & Hex($iStart, 4) & Hex($iNum, 4))

    Du kannst auch für die unterschiedlichen Abfragen/funktionalen Codes Formatspezifikationen für StringFormat erstellen. Ich finde das übersichtlicher. Für FC 0x04 könnte das dann so aussehen:

  • Vielen Tausend Dank,

    ..ihr seid Helden!

    ja die Struktur ist vorab schon schlecht und geht bei der Fehlersuche immer komplett in den Eimer. Die global/local Variablen werde ich noch richten.

    So langsam funktioniert das Auslesen. Zum Glück hatte ich "Fehler Verbindungsaufbau" daraufhin habe ich die Funktion dahin geändert, dass sie sich selber aufruft, an Stelle von exit. Fuktioniert - nur leider habe ich ein schlechtes Gefühl dabei. Kann man das so machen?

    ...nochmals vielen Dank!

    Einmal editiert, zuletzt von SOLVE-SMART (20. Februar 2023 um 08:17)

  • Ich rate davon ab, aus mehreren Gründen:

    1. Schaffst du somit im worst case eine riesige Kaskade

    2. Sobald der 2. bzw. Xte Aufruf der Funktion abgefrühstückt ist, springt er wieder an den Punkt wo sie aufgerufen wurde. Bedeutet, das alles was danach kommt Xmal ausgeführt wird.

    Versuch den Verbindungsaufbau zu machen, pack das aber mit einem Timer sleep(X) (den hast du ja bereits) und in eine Schleife mit einem maximum von z.B. 10 Versuchen. Wenn die 10 Versuche fehlschlagen, Abbruch per z.B. Return 'keine Verbindung'.

    Wenn die Verbindung erfolgreich ist mit ExitLoop raus aus der Funktion und dann kommt dein Code den du ausführen willst.

    Edit: Hier mal, wie ich das quick & dirty Umsetzen würde in deinem Code. Ich habe dabei auch gleich die falschen/fehlenden Deklarationen korrigiert und erwarte (das würde ich wirklich empfehlen), das du die Werte, die in der () der Funktion stehen, der Funktion übergibst und nicht alle Global definierst. Letzteres wird dir sonst irgendwann auf die Füße fallen.

    3 Mal editiert, zuletzt von Moombas (20. Februar 2023 um 08:11)

  • Hallo Moombas,

    danke für die Hilfe. Allerdings läuft das skript "unbeaufsichtigt", d.h. Es soll solange "schleifen" bis wieder einer den Stecker steckt - und weiter gehts.

    Jetzt haab ich ein großes FTP Problem. Da mach im mal ein neues Thema.

    Danke!

  • Hallo Moombas,

    danke für die Hilfe. Allerdings läuft das skript "unbeaufsichtigt", d.h. Es soll solange "schleifen" bis wieder einer den Stecker steckt - und weiter gehts.

    Danke!

    Dann würde ich das dennoch trennen:

    1. Prüfen ob eine Verbindung aufgebaut werden kann (Endlosschleife mit Ping), dennoch Empfehlung einen Shortcut zum Abbruch einbauen

    2. Wenn erfolgreich: Code ausführen (der obige Code).

    3. Prüfen ob die Verbindung (Endlosschleife mit Ping) wieder getrennt wurde und erst dann wieder bei "1." einsetzen um eine Mehrfachausführung zu vermeiden.

    Q&D:

    2 Mal editiert, zuletzt von Moombas (20. Februar 2023 um 10:18)