Modbus slave

P

Thread Starter

Philip Costigan

Hi all I was having a look at what I wanted to do with Modbus/TCP slave and realised that It is possible to aproach this area from a completely different angle than Modbus/TCP master. I am thinking of allowing the whole LPLC io map to be referenced to the holding register Modbus map. ie 40001 to 49999. This would mean that all bits would be referenced as read only and any io_point that was assigned to modbus_tcp_slave would be driven from some external device over ethernet. It also means that only one Modbus function is required to drive all io. (Keep It Simple). All other requests would reply with an exception error. Does this sound feasable or do we want to make it complicated and assign individual points to each modbus address as required. -- Regards Philip Costigan _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
A

Andrew Kohlsmith

> I am thinking of allowing the whole LPLC io map to be referenced to the > holding register Modbus map. ie 40001 to 49999. > This would mean that all bits would be referenced as read only and any io_point > that was assigned to modbus_tcp_slave would be driven from some external device > over ethernet. Actually I'm working on something like this as a seperate product (485 <--> Ethernet converter) but where the RS485 ModBUS devices' addresses can be mapped into the converter's address space. It is configurable so that it can poll the 485 devices and cache the responses in order to make the devices appear to be working at Ethernet speeds. I know of a few 485-Ethernet converters but nothing that does anything like that. Regards, Andrew _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
K

Kipton Moravec

I have been looking at something similar. I have a bunch of controllers (166) placed throughout a semiconductor plant talking over RS-485. My customer would like them to be accessible via modbus Ethernet. I am looking at a single board computer. Advantech has one for around $300 with a 133 MHz 586, two serial ports (one RS-232 other switchable RS-232/422/485) and an Ethernet port, (and all the regular PC ports, but only 1 2-drive IDE disk connector). The RS-485 networks runs 9600 baud. So I was going to have the computer continuously poll all the devices, so when there was a request from the Ethernet side there would be an immediate response from the cached data. The SCADA system wants the data update every 5 seconds. So I got a PC-104 two RS-422/485 port card so I could handle more sub-segments since I have idle time with just one. The Advantech board also has a slot for a Disk-on-chip. They are solid state disks that plug in a 32 pin socket. You can get them as big as 144 MB. In another project where I was running DOS, a 8 MB chip was sufficient, (and only $38). In my case the controllers do not speak modbus, so the RS-485 side can work one protocol, and the Ethernet side can do the modbus. I have already used this board for a optomux interface. In this case both the SCADA and the device wanted to be the MASTER. So I put this board in between acting as a slave between both. The device wrote data the "double slave" and the SCADA system read data from the "double slave". It was pretty trivial, so I used DOS and PowerBasic. It worked fine, and they ended up ordering a total of 4 of these. It was a cheap and easy solution. Kip _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
P

Peter Nachtwey

My company makes a motion controller that does what you are talking about. It maps much of its memory to 400001 to 465536. We have a status area, command area, parameter area, IO area, graph data, etc all mapped to holding registers. If you make a slave device look like a PLC then the slave device will be compatible with many other devices. The only down side is that this requires a lot of tags in a WonderWare or RSView HMI. I suggest that you also write or obtain a Modbus/TCP activex control that will allow one to access you slave from Excel or Visual Basic.
 
G

Greg Goodman

> I am thinking of allowing the whole LPLC io map to be referenced to the > holding register Modbus map. ie 40001 to 49999. > This would mean that all bits would be referenced as read only and any io_point > that was assigned to modbus_tcp_slave would be driven from some external device > over ethernet. > > It also means that only one Modbus function is required to drive all io. > (Keep It Simple). > > All other requests would reply with an exception error. > > Does this sound feasable or do we want to make it complicated and assign > individual points to each modbus address as required. I strongly recommend against implementing such a limited subset of the Modbus protocol. Most Modbus master implementations only know how to write bits using the Force Coil and Force Multiple Coils functions. Some master implementations allow the user to specify a write to a bit in a register, but the protocol doesn't support that, so it gets implemented as: 1. read register 2. modify bit 3. write register Not a good idea, since you write 15 old bit values that you don't care about, and that may have changed since you read them... And if the protocol master software doesn't do this under the covers, you force the integrator to write that in application code. (yuk.) I suggest implementing at least the following basic commands: 1 - Read Coil Status 2 - Read Input Status 3 - Read Holding Registers 4 - Read Input Registers 5 - Force Single Coil 6 - Preset Single Register 15 - Force Multiple Coils 16 - Preset Multiple Registers I advocate supporting both functions 5 & 15, and both function 6 & 16. While it is possible to write force one coil using Force Multiple Coils or write one register using Preset Multiple Registers, we have no way to force the master software to use a particular function. Many (most?) Modbus master drivers pick the function they will use based on the task they are asked to perform. If the HMI software specifies that a coil is to be written, the software will typically format a Function 5 request. Ditto for holding registers. (I have written commercial Modbus master implementations, and ran into this limitation with a slave device. I had to add a user-level configuration option to force the master to use Function 5 instead of 15-with-a-count-of-1.) Basically, it comes down to this: if you want a slave that is responsive to many or most of the available masters, then you have to conform to the masters' expectations, which are set out in the protocol spec. My 2 cents. Greg Goodman Chiron Consulting
 
P

Philip Costigan

On Thu, 26 Apr 2001, Greg Goodman wrote: > I strongly recommend against implementing such a limited subset of the > Modbus protocol. > > Most Modbus master implementations only know how to write bits using > the Force Coil and Force Multiple Coils functions. Some master > implementations allow the user to specify a write to a bit in a > register, but the protocol doesn't support that, so it gets implemented > as: > > 1. read register > 2. modify bit > 3. write register > > Not a good idea, since you write 15 old bit values that you don't care > about, and that may have changed since you read them... And if the > protocol master software doesn't do this under the covers, you force the > integrator to write that in application code. (yuk.) > I agree. > I suggest implementing at least the following basic commands: > > 1 - Read Coil Status > 2 - Read Input Status > 3 - Read Holding Registers > 4 - Read Input Registers > 5 - Force Single Coil > 6 - Preset Single Register > 15 - Force Multiple Coils > 16 - Preset Multiple Registers > OK. What I'll do is implement the system so that the complete LPLC map can be accessed by useing any of the commands. So it can therefore be able to set/reset a bit in a register and/or change a value of a complete register. Force Single coil 4.4 and Preset single register 4 would affect the same LPLC io word. Is this agreable? I still think that I will probably develop the Preset Multiple registers implementation first and then add the others as we go. -- Regards Philip Costigan ------------------------------------- P.C. SCADA LINK PTY LTD Melbourne Victoria Australia http://pcscada.com.au ------------------------------------- _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Philip Costigan wrote: > (...) > > What I'll do is implement the system so that the complete LPLC map can be > accessed by useing any of the commands. So it can therefore be able to > set/reset a bit in a register and/or change a value of a complete register. > > Force Single coil 4.4 and > Preset single register 4 > would affect the same LPLC io word. > > Is this agreable? > > I still think that I will probably develop the Preset Multiple registers > implementation first and then add the others as we go. > > Hi Philip, Maybe you are probably aware that I am currently implementing an IO module for the hilscher cards (a.k.a. cif cards). Having already written the IO module for the parallel port, I was considering using some of the parallel port code and make it into a general library from which it would be easier to code a new IO module. This library would include the main() function, so in essence, to develop a new IO module one would merely have to implement some hardware specific functions to access the physical IO. I was considering an API along the lines of: typedef struct { u8 opaque[8]; } io_addr_t; write_bit(io_addr_t io_addr, plc_pt_t plc_pt); read_bit (io_addr_t io_addr, plc_pt_t plc_pt); write_word(io_addr_t io_addr, plc_pt_t plc_pt); read_word(io_addr_t io_addr, plc_pt_t plc_pt); /* NOTE: the following four functions assume plc_pts that are * arrays of points. * I'll come back to this later once Jiri and I have nailed * down all the details. */ write_bit_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); read_bit_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); write_word_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); read_word_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); parse_io_addr(io_addr_t *io_addr, const char *addr_str); /* connect to hardware, etc... /* may assume that plc_init() has already been called, * so may obtain config parameters from linuxplc.conf */ init(??); /* terminate connection to hardware... */ done(??); This API may change a little once I start implementing things and notice any difficulties. You might want to wait a while, or maybe start off by writing the protocol stack, and leave interfacing with the LPLC to last? I will also have some students implementing communication protocol stacks for (modbus master, modbus slave, and other open proprietary protocols) from documentation that came with the PLCs themselves. I suppose it shouldn't be a problem (Curt?) since we are using public documents? It would still be a while before we get things running. I will have to clean up their code before we can use it, but it will probably be easier than writing it from scratch. It really depends on what kind of results I will get. We'll just have to wait and see... Cheers, Mario. -- ---------------------------------------------------------------------------- Mario J. R. de Sousa [email protected] ---------------------------------------------------------------------------- The box said it requires Windows 95 or better, so I installed Linux _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
C

Curt Wuollet

Excellent idea Mario, especially if we can get somebody to really explain it and document it well. As diverse IO is extremely important, anything we can do to make writing drivers approachable and painless is a big boost to our chances of gotting them done. I'm kinda waiting on this myself. Regards cww _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
P

Philip Costigan

On Thu, 26 Apr 2001, Mario de Sousa wrote: > I was considering an API along the lines of: > > > > typedef struct { > u8 opaque[8]; > } io_addr_t; > > write_bit(io_addr_t io_addr, plc_pt_t plc_pt); > read_bit (io_addr_t io_addr, plc_pt_t plc_pt); > > write_word(io_addr_t io_addr, plc_pt_t plc_pt); > read_word(io_addr_t io_addr, plc_pt_t plc_pt); > > /* NOTE: the following four functions assume plc_pts that are > * arrays of points. > * I'll come back to this later once Jiri and I have > nailed > * down all the details. > */ > write_bit_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); > read_bit_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); > > write_word_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); > read_word_array(io_addr_t io_addr, int count, plc_pt_t plc_pt); > > parse_io_addr(io_addr_t *io_addr, const char *addr_str); > > /* connect to hardware, etc... > /* may assume that plc_init() has already been called, > * so may obtain config parameters from linuxplc.conf > */ > init(??); > > /* terminate connection to hardware... */ > done(??); > > > This API may change a little once I start implementing things > and notice any difficulties. You might want to wait a while, or > maybe start off by writing the protocol stack, and leave > interfacing with the LPLC to last? > I'll probably just do what I can while I can :) and when you think that your API is ready I'll try implementing it. It looks good. -- Regards Philip Costigan ------------------------------------- P.C. SCADA LINK PTY LTD Melbourne Victoria Australia http://pcscada.com.au ------------------------------------- Linux: The ultimate NT sevice pack. _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
C
> I'll probably just do what I can while I can :) and when you think that your API is ready I'll try implementing it. It looks good. > Hi Philip Yes. I think that's a good plan. It will be easier to come by the knowlege to adapt it to the API than the specific Modbus knowlege and awareness you have at the moment.. Regards cww _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
Philip Costigan: > Does this sound feasable or do we want to make it complicated and assign > individual points to each modbus address as required. My (belated) 2 cents' worth... 1) From the point of view of the architecture, individual points should be assigned. The user should never work directly with the underlying point addresses - always with point names. Also, when the LPLC is to be used as a data cop, it must be able to map any input to any output. A direct mapping makes this impossible. With Mario's I/O library, this should not be too much coding effort... 2) However, I can see why you'd want to use the direct mapping at times. Make it an option? Jiri -- Jiri Baum <[email protected]> Connect the power cable, interface cable and ground wire only in the methods indicated in the this manual. It may lead to fire. -- OKIPAGE 8z user's manual _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
Top