ModbusTCP Sensorabfrage Error illegal Funktion

andrax
2023-01-06
2023-01-24
  • andrax

    andrax - 2023-01-06

    Hallo zusammen,

    ich habe folgendes Setup.
    Raspberry Pi 4 mit Codesys 3.5 SP18
    Messgerät KIMO C 310
    Auf dem Raspberry ist die IP Statisch vergeben 192.168.10.80
    KIMO C 310 hat 192.168.10.135
    Die Verbindung steht.

    Ich muss das Register 0x7010 mit 4 bytes auslesen.
    Meiner Erachtens ist das Funktionscode 4
    Offset: 0x7010
    Länge: 4

    Ich bekomme aber den Fehler: ILLEGAL FUNKTON (Slave does not support the function code)

    Wo liegt mein Fehler ?

    Danke im voraus

     
  • andrax

    andrax - 2023-01-06

    Nachtrag:

    wir haben jetzt das Gerät gegen ein baugleiches Gerät (ebenfalls C 310) getauscht.
    Dieses wird ebenfalls per ModbusTCP abgefragt, allerdings mit einer anderen Software.

    Das Problem bleibt bestehen.
    Verbindung ist da und der selbe Fehler.

     
  • andrax

    andrax - 2023-01-06

    Nachtrag:

    wir haben jetzt das Gerät gegen ein baugleiches Gerät (ebenfalls C 310) getauscht.
    Dieses wird ebenfalls per ModbusTCP abgefragt, allerdings mit einer anderen Software.

    Das Problem bleibt bestehen.
    Verbindung ist da und der selbe Fehler.

     
  • eschwellinger

    eschwellinger - 2023-01-07

    Sicher das der Offset und Länge und function code passen? Der Fehler sagt das es nicht passt..

     
  • andrax

    andrax - 2023-01-08

    Im Ausgangspost habe ich die Doku mit angehangen.
    Das Gerät hat 4 Kanäle. Ich will Kanal 1 auslesen.
    Laut Doku ist es 0x7010 mit 4 Bytes.
    Abfragen muss ich mit Funktionscode 4.
    Sollte doch richtig sein oder ?

    Wir haben am Freitag es noch mit der anderen Software versucht, die auf dem anderen Raspi läuft. Es ist ein Pythonscript und auch dieses funktioniert auch nicht. Die Verbindung wird aufgebaut, es kommen aber keine Daten, sondern nur ein Fehler.

    Wir haben nun den Raspi in Verdacht. Entweder stimmt was mit dem Routing nicht oder Ports.... Keine Ahnung.
    Wir werden erstmal den Raspi neu installieren und es mit einem Frischen System noch mal Testen.

     
  • eschwellinger

    eschwellinger - 2023-01-08

    hm, denke nicht das es am Raspi liegt, wieso Function Code 4?
    Ich meine zu lesen das dieses Gerät Function Code 3,Funktion Code 16, Funktion Code 8 kann.
    Vielleicht irre ich mich ja auch.

     
  • andrax

    andrax - 2023-01-08

    Den Function Code 3 hatte ich auch eingestellt, mit selbigen Ergebnis.
    Was mich wundert, dass das Testscript welches auf einem anderen Raspi läuft, bei meinem nicht funktioniert. Das Testscript benutzt Function Code 4

     
  • eschwellinger

    eschwellinger - 2023-01-08

    die runtime beendet wenn du das testscript aufrufst?

     
  • andrax

    andrax - 2023-01-09

    Ja die Runtime war gestoppt, bzw. über die Console beendet.
    Ich habe jetzt noch 2 Ideen:
    Den Netzwerkverkehr über Wireshark beobachten.
    Den Wlanadapter deaktivieren.

     
  • andrax

    andrax - 2023-01-10

    Hallo Herr Schwellinger,

    sie hatten Recht.
    Es muss Functions Code 3 verwendet werden.
    Zusätzlich muss das das Register 0x7010 in Hex 16#1B62 gewandelt werden.
    Ich bin hier zufällig darauf gestoßen.

    Eine Frage noch.
    Da ich mich zum ersten mal mit Modbus beschäftige.
    Wo sehe ich die einlaufenden Daten, oder muss ich diese explizit auffrischen?

    Grüße

     
  • eschwellinger

    eschwellinger - 2023-01-10

    ...wie immer mappen und in den Pou's verwenden nur dann werden die auch aktualisiert.

     
  • andrax

    andrax - 2023-01-10

    Dankeschön

     
  • andrax

    andrax - 2023-01-11

    Ich brauche doch noch einmal Hilfe.
    Die Eingangsdaten müssen konvertiert werden.
    Ich hätte jetzt angenommen, dass nach little/big endian BBAA >> AABB konvertiert werden muss.
    Dass Messgerät zeigt auf Kanal 1 (0x7010) 1,75 bzw. 1,76 an.
    Meine Eingangsdaten schwanken zwischen 16#47AE bzw. 16#8F5C
    Aber egal wie ich die Bytes schiebe, ich bekomme kein sinnvolles Ergebnis welches mit den Messdaten korrespondiert.
    Wie muss ich das richtig konvertieren?

     
  • andrax

    andrax - 2023-01-11

    OK ich habs... fast.
    Ich muss die Register 0x7010 und 0x7011 auslesen und entsprechend zusammensetzen.
    AB CD >>> CDAB
    Hab ich über eine Funktion gelöst.
    Ist zwar jetzt nicht die sauberste lösung, aber funktioniert:
    END_VAR
    VAR_OUTPUT
    Daten : LREAL;
    END_VAR
    VAR
    rawLowerByte : DWORD;
    rawUpperByte : DWORD;

    END_VAR

    rawLowerByte := WORD_TO_DWORD(LowerByte);
    rawUpperByte := SHL(WORD_TO_DWORD(UpperByte),16);
    Daten := DWORD_TO_LREAL(rawLowerByte OR rawUpperByte);

    Allerdings habe ich jetzt ein Darstellungsproblem:
    Aus der Bytefolge (16#3F970A3D) Bekomme ich ein UINT32 Wert = 1.07E+09 (1066863165)
    Richtig wäre aber FLOAT = 1.18

    Wie kann ich das Umstellen, bzw. richtig darstellen?

    Grüße

     
  • andrax

    andrax - 2023-01-24

    Hallo zusammen,

    fast vergessen mich zu melden.
    Ich hab mittlerweile das Problem gelöst.
    Die Falsche Darstellung konnte ich mit OSCAT lösen
    So sieht mein Code jetzt aus:
    FUNCTION_BLOCK ModbusKonverter
    VAR_INPUT
    LowerByte : WORD; //CD
    UpperByte : WORD; //AB
    END_VAR
    VAR_OUTPUT
    Daten : REAL;
    END_VAR
    VAR
    rawLowerByte : DWORD;
    rawUpperByte : DWORD;
    END_VAR

    rawLowerByte := WORD_TO_DWORD(LowerByte);
    rawUpperByte := SHL(WORD_TO_DWORD(UpperByte),16);
    Daten := oscat_basic.DW_TO_REAL(rawLowerByte OR rawUpperByte);

    PS:
    Mir ist allerdings unklar wie oscat_basic.DW_TO_REAL funktioniert.
    Evtl. kann mir jemand folgende Codezeilen erklären?
    pt := ADR(X);
    DW_TO_REAL := pt^;

     
  • Fless

    Fless - 2023-01-24

    Alternativ kannst du die 'CAA Memory' Bibliothek nutzen.

    rawDWord := MEM.PackWordsToDword(wHighWord:= UpperByte , wLowWord := LowerByte );
    MEM.MemMove(pSource := ADR(rawDWord), pDestination := ADR(Daten), uiNumberOfBytes := SIZEOF(Daten));
    

    PS:
    pt := ADR(X); // schreibt die Speicheradresse von x in then Pointer pt
    DW_TO_REAL := pt^; // schreibt den Wert der an der Speicheradresse pt steht in DW_TO_REAL
    // dereferenziert den Pointer

     
  • andrax

    andrax - 2023-01-24

    Ah Ok Danke,

    die Funktion MEM.PackWordsToDword... kannte ich noch gar nicht.
    Also mit den Pointer und dereferenzieren greift man direkt auf die Speicheradresse
    und hat sozusagen Zugriff auf die Rohdaten.
    Aber warum macht man das?
    Das erschließt sich mir nicht.

     

Log in to post a comment.