Shop OBEX P1 Docs P2 Docs Learn Events
Basic Stamp output to PC in Modbus RTU format — Parallax Forums

Basic Stamp output to PC in Modbus RTU format

lindseydallaslindseydallas Posts: 14
edited 2014-02-18 10:32 in BASIC Stamp
I know there are lots of posts on Modbus protocol and the Basic Stamp but frankly they are all way over my head, so please be patient if the answer I need is already out there. I have a very simple setup with 12 digital inputs coming into my BS2. I have software installed on my computer that is monitoring a PLC and that software only communicates through Modbus RTU. I want to setup the Basic Stamp to send 12 variables to the software in Modbus RTU format, each representing the value of the digital inputs - so, 0 or 1. It looks like the SEROUT command should do this, but I don't understand how to setup my Output Data string to include an address, register, etc so that the program will be able to understand what it's receiving. I guess I need to calcalate a CRC also but I'm not sure what exactly that is or how it is included in the SEROUT command. I am using the HomeWork board with an RS232 to USB connection.

Thanks for any instruction you can provide!
Lindsey

Comments

  • Buck RogersBuck Rogers Posts: 2,181
    edited 2014-01-21 23:47
    I know there are lots of posts on Modbus protocol and the Basic Stamp but frankly they are all way over my head, so please be patient if the answer I need is already out there. I have a very simple setup with 12 digital inputs coming into my BS2. I have software installed on my computer that is monitoring a PLC and that software only communicates through Modbus RTU. I want to setup the Basic Stamp to send 12 variables to the software in Modbus RTU format, each representing the value of the digital inputs - so, 0 or 1. It looks like the SEROUT command should do this, but I don't understand how to setup my Output Data string to include an address, register, etc so that the program will be able to understand what it's receiving. I guess I need to calcalate a CRC also but I'm not sure what exactly that is or how it is included in the SEROUT command. I am using the HomeWork board with an RS232 to USB connection.

    Thanks for any instruction you can provide!
    Lindsey

    Hello!
    What have you tried out? The big problem is in constructing the message format, then do you want this to be a master device? Not really possible, or a slave device which comes close. What examples have you found so far?
  • stamptrolstamptrol Posts: 1,731
    edited 2014-01-22 10:43
    Do you know which device is the Master? In Modbus, the master must request data from each slave.

    From your description, you'll have at least 3 stations on the network; the PC, the PLC and the Stamp. So, that means you'll have some sort of multi-drop network like RS-485. In essence, all stations are always "listening" and the Master decides who to talk to and receive information from. From my experience, it works best if the PLC is the Master and can poll the slaves to either send data or request data.

    It is technically possible to write Stamp code to behave like a slave, taking into account having no communications buffer to capture the Master's call while off doing something else. If you start with the Modbus protocol description, you will likely become thoroughly confused/disgusted/down heartened or some combination of those after the first few weeks.

    Having said all that, there are a couple of low cost microcontrollers that can do Modbus natively. Not wanting to insult our hosts by discussing a competitor's product, drop me a private message to talk it over.

    Cheers,
  • lindseydallaslindseydallas Posts: 14
    edited 2014-02-12 11:01
    Thanks for your responses. The Basic Stamp will be acting as the slave with the PC software as the master. I have been using the demo versions of Simply Modbus and the CAS Modbus RTU parser to build messages in Modbus RTU format to send as tests. This way I am not worrying about building the CRC yet, I can focus on the format and how to send the actual serial transmission. I am using a freeware program called Tera Term that enables me to send messages through the serial port. The advantage of this over my Modbus RTU software (the master) is that I can see everything that the Basic Stamp is sending, regardless of whether or not the format is correct.

    So, where I am now is that the Basic Stamp recognizes when a string is sent to it and then responds with a string of its own:

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' {$PORT COM4}

    InputData VAR Byte(23)


    DO
    SERIN 16, $4054, [STR InputData\23]
    SEROUT 16, $4054, [" 63 03 02 01 01 81 DC "]
    LOOP

    My questions are:
    1) Is it correct that the Master message would be 23 bytes long? I am expecting something like: "63 03 00 00 00 01 8C 48" and I am including the spaces as bytes.

    2) I tried receiving a string of various lengths with SERIN, writing it to an array and then reading it back, but it showed that it was only receiving one byte. Is it possible that 9600 Baud is too fast for the Basic Stamp to receive the entire message?

    2) The Modbus RTU manual says there should be a silent interval of at least 3.5 character times at the beginning and end of each message. I stuck in the 4 extra character spaces at the beginning and end of my response assuming this might be what they are talking about? Is that correct?

    Other than that, I know I am communicating something because the Rs232-USB connector light blinks to indicate it is receiving and transmitting and I can talk to the Basic Stamp through Tera Term. I think it must be either my timing - waiting until the correct length message has been received to send the response - or the format of my response that is giving me problems.

    Thanks for any advice!
  • stamptrolstamptrol Posts: 1,731
    edited 2014-02-13 07:53
    The way the program is shown, the Stamp will grab any 23 characters that are flying by when the SERIN is encountered. Similarly, there will always be a SEROUT of those characters. There is no receive and corresponding response.

    You can add the WAIT modifier to SERIN so the Stamp will pause until it sees a particular few characters before taking in characters. You can also incorporate a timeout so the program will jump to another spot and you can send out a specific "No Message Received".

    Then you can more correctly tell what's happening.

    Keep at it!
  • lindseydallaslindseydallas Posts: 14
    edited 2014-02-18 10:32
    Thanks stamptrol for pointing me in the right direction. I made big progress today in the sense that I can now use the SERIN command to read the message the Master is sending. There were two things that made this possible: the first was that I changed from 9600 Baud to 300 Baud. Not sure why, but the characters I was reading at 9600 Baud were really weird. The second thing was that I set my Master to send in Modbus ASCII format instead of Modbus RTU format. This was huge because it meant I could WAIT for the colon (":") in my SERIN line and be sure I was getting the right data in the right order.

    Now the issue is that I need to calculate the LRC. I was cheating before, using the CAS Modbus RTU parser to figure out what the CRC needed to be, but I haven't been able to find anything that calculates the LRC for you. I'm going to work on this next but wondered in anyone had already done it...

    I am going to include my code and what I did to read in the master message in case it might be helpful to someone else. Here is what I did:
    1) load the code onto the basic stamp (see below)
    2) run the Master software so that the stamp reads in the master query and writes it to memory. I set up an LED to turn on when this happens so I know when to go to the next step.
    3) close the Master software (since only one program can be connected through a serial port)
    4) open the software Tera Term but don't type in anything. After 5 seconds of nothing coming in through the serial input the basic stamp will jump to the goRead command and output the master query message that was stored in memory.

    here's the code:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    ' {$PORT COM4}

    'setup Master to read/write Modbus ASCII
    'Basic Stamp address is dec 50 hex 32

    'baud dec hex
    '300 19697 $4CF1
    '600 18030 $466E
    '1200 17197 $432D
    '2400 16780 $418C
    '4800 16572 $40BC
    '9600 16468 $4054

    '
    [ VARIABLES ]
    '
    master query variables
    'address
    'code
    'start address high byte
    'start address low byte
    'number of registers high byte
    'number of registers low byte
    'LRC byte
    address VAR Byte(2)
    code VAR Byte(2)
    MQ VAR Byte(8)
    LRC_M VAR Byte(2)

    stored VAR Byte(7)
    n VAR Byte


    '
    [ INITILIZE ]
    LOW 15


    '
    [ MAIN ]
    DO
    SERIN 16, 19697, 5000, goRead,[n] 'n is not used, this is just a way to jump to goRead or goWrite

    goWrite:
    SERIN 16, 19697,[WAIT(":"),address(0),address(1),code(0),code(1),MQ(0),MQ(1),MQ(2),MQ(3),MQ(4),MQ(6),MQ(6),MQ(7),LRC_M(0),LRC_M(1)]
    WRITE 0, address(0),address(1),code(0),code(1),MQ(0),MQ(1),MQ(2),MQ(3),MQ(4),MQ(6),MQ(6),MQ(7),LRC_M(0),LRC_M(1)

    HIGH 15
    PAUSE 1000
    LOW 15
    PAUSE 3000

    goRead:
    'this is broken up into two parts because I ran out of variable space
    READ 0,stored(0),stored(1),stored(2),stored(3),stored(4),stored(5),stored(6)
    SEROUT 16, 19697, [stored(0),stored(1),stored(2),stored(3),stored(4),stored(5),stored(6)]

    READ 7,stored(0),stored(1),stored(2),stored(3),stored(4),stored(5),stored(6)
    SEROUT 16, 19697, [stored(0),stored(1),stored(2),stored(3),stored(4),stored(5),stored(6)]

    LOOP
Sign In or Register to comment.