Shop OBEX P1 Docs P2 Docs Learn Events
Modbus TCP using Wiznet W6100 — Parallax Forums

Modbus TCP using Wiznet W6100

This is looking like it might be easy...

Have working over serial port already (Modbus RTU):
https://forums.parallax.com/discussion/176224/modbus-rtu-slave

Using a wiznet driver from @ke4pjw
https://forums.parallax.com/discussion/177801/wiznet-w6100-spin2-driver-usage#latest

Just changed port from 80 to 502.

Tried just now to connect with Open Modscan's scanner and seeing data that makes sense.
Found a document that describes what getting from scanner:
https://www.prosoft-technology.com/kb/assets/intro_modbustcp.pdf

Comments

  • RaymanRayman Posts: 15,695

    In the above, first pinged it with function #3 (Read holding regs) and then function #17 (Report Slave ID).
    Had the code debug out all the bytes.

    Was unsure at first why the packet started with a few zeros, but seeing that now in the above document.

    Was thinking that was going to be exactly the same format as RTU, just without CRC.
    Guess it somewhat is, but not exactly...

    Next up is to work on sending a response...

  • RaymanRayman Posts: 15,695
    edited 2025-09-29 15:34

    This code now appears to be working with Open ModScan's Modbus Scanner in TCP mode.

    Not 100% sure if the data is correct or not yet. The regular Open Modscan interface won't let me open the socket for some reason.
    Might have to look for instructions...

  • RaymanRayman Posts: 15,695

    Open ModScan is happy now with the regular data interface as well as the scanner.
    TCP is pretty picky about #bytes that gets transferred, has to be exact...

    May need to work on getting reconnection working now.
    If disconnect and then reconnect, doesn't work...

  • RaymanRayman Posts: 15,695

    It's looking like doing a timeout on a connection and then restarting it is something that needs to be coordinated with the master.
    Seems like Open ModScan does a poll every second or so. Seems the only way to tell if connection is broken is to look for a stop in polling.

    But, maybe @ke4pjw knows better?

    So, added this timeout code to the query & response loop and seems to work.
    If there's no query in a while after the first query, it will restart the connection:

      ntimeout:=0
      repeat
    
        If ( W6100.ReceiveData(socket,10000) <> W6100.Sn_IR_TIMEOUT)
            debug("Data received")
            psize := W6100.ReceiveProcess(socket,@READBUFFER)
            READBUFFER[psize] := 0
    
            'W6100.SendData(socket,@webbuff,rdsize)
    
    
            ProcessQuery(psize,socket)
            'if i>0
            '  W6100.SendData(socket,@webbuff,i)
            debug("Query Processed")
            ntimeout:=0
        else
          debug("timeout")
          if ntimeout++ >10
            return
    
  • ke4pjwke4pjw Posts: 1,229
    edited 2025-09-30 21:32

    @rayman,
    That 10000 is a timeout value. I have changed this in the latest code. I will be publishing it soon. The new value will be based on milliseconds vs a generic counter++. That allows you to poll for input and if none is found you can go do something else.

    I wrote isdisconnected(socket) to determine if a socket connection is disconnected. It should return true if Sn_IR_DISCON is set in the register status of REG_Sn_IR of the given socket.

  • RaymanRayman Posts: 15,695

    Thanks @ke4pjw !

    That sounds way too easy, but guess will try it. :)

  • ke4pjwke4pjw Posts: 1,229

    @Rayman I have not tested, but pushed a new W6100.spin2 to my repo.

    https://griswoldfx.visualstudio.com/Spinner Edge/_git/Software

    Timeout for ReceiveData() is now milliseconds. Added more comments for each method. I am going to fold all of these changes into my other projects, the Blitzen 24 and CoCo Blender.

  • RaymanRayman Posts: 15,695

    @ke4pjw Tried IsDisconnected() but doesn't seem to work... Thinks always disconnected....

    But, maybe I'm doing it wrong?
    Doesn't really matter too much because the other way works...

      repeat
    
        If ( W6100.ReceiveData(socket,10000) <> W6100.Sn_IR_TIMEOUT)
            debug("Data received")
            psize := W6100.ReceiveProcess(socket,@READBUFFER)
            READBUFFER[psize] := 0
    
            'W6100.SendData(socket,@webbuff,rdsize)
    
    
            ProcessQuery(psize,socket)
            'if i>0
            '  W6100.SendData(socket,@webbuff,i)
            debug("Query Processed")
            'ntimeout:=0
        else
          'debug("timeout")
          'if ntimeout++ >10
          '  return
          if W6100.IsDisconnected(socket)==true
            return
    
  • ke4pjwke4pjw Posts: 1,229

    @rayman Excellent! I thought the additional comments may be helpful.

    Also, something I do in my other code when isDisconnected() is found to be true is to call Disconnect() before reopening the listening port. Just as a way to make sure a RSET packet is sent. This may or may not be necessary, but that's what I do in my emulated modem code in the CoCo Blender.

  • ke4pjwke4pjw Posts: 1,229

    Oh wait, I re-read that. It sounds as if once a connection is made to the P2 on TCP port 502, it doesn't exist very long. I would be surprised to find that if you Wireshark it, that the connection exists but W6100.IsDisconnected(socket) returns true on the P2.

    BTW, I have a newer version of EstablishTCP that includes a timeout. (Currently it stalls until a connection is established) Haven't folded that into the mainline code. This will work great with the new tasks in spin2. While waiting in an inbound connection, you can move on to another task. A multithreaded server could be built using it.

  • RaymanRayman Posts: 15,695

    Another hurdle is getting the modbus TCP client working in my own MFC C++ code.
    Probably easier if using .NET, but am not...

    Found a library that works here:
    https://github.com/fz-lyu/modbuspp

    Simple enough, just had to adapt to unicode.
    Appears to have been written for Linux and then adapted for Windows.

    Not liking GPL license though. It's so simple though, have my own winsock code around somewhere, but it's been ages. Might have to resurrect that...
    Still, GPL is a deal breaker for now 'cause no one is going to see this source besides myself.

    There are other libraries out there too. Tried one that also works that is a .dll
    May switch to that if actually do care about license one day...

Sign In or Register to comment.