Basic Stamp output to PC in Modbus RTU format
lindseydallas
Posts: 14
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
Thanks for any instruction you can provide!
Lindsey
Comments
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?
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,
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!
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!
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