Read Coils/Write Single Coil

Hello!
We are EA Elektro-Automatik company from Germany, a big power supply manufacturer. We use ModBus RTU and TCP in our devices for years now,
but have been pointed by customers to the fact that our devices are not fully compatible to the ModBus specification. Reviewing the specs we think we know where we did wrong, but are not sure. Maybe someone here can help.

Read Coils (RC): the specs say that there can be up to 2000 coils, but it doesn't say that a device must support to read 2000 coils, whether they are all used or not, or if the limit can be lower. Let's say we would define to have 16 coils in use we would define that the user can read up to 16 coils and when trying to read more, there will be error 03. Next problem: if we define 16 coils as maximum, the specification doesn't say that the device must also support to read 1-15 coils. So far we defined that the user must always read 16 coils in order to get 16 in return. Reading less than 16 would also return error 03.

Write Single Coil (WSC): This is actually a paradox for me, because with RC one coil corresponds to one bit, but with WSC 16 bits are written (0xFF00, 0x0000) for one coil. That's why we defined that if some one wants to read what has been written to a WSC register he would have to use RC with 1 coils and so the register would return 0xFF00 or 0x0000. This is where we went wrong. But it seems logical to me, because the specs also don't define that a register which I can write with WSC can't be read with RC. However, it turns out that reading 1 coil with RC and returning 0xFF00 is considered as actually reading 16 bits (or 9-16), so that a stock software would return an error. The coils to read with RC are put in the memory at some address, let's say 0x0000. 2000 coils are 250 bytes (0xFA) which corresponds to 125 ModBus registers. But with WSC I could not address all of these 2000 single coils because every addressable coil register already contains 16 coils. Means with WSC I can eventually address 125 coils by writing 0xFF00 or 0x0000, but would have to read 16 to have the logical state (TRUE/FALSE) back. Confusing.

Conclusion: thinking through all of this I get the feeling that ModBus isn't made to read a coil that has been written with WSC. Am I right? That's a weird approach, but it seems to be the root problem.
 
A quick skim read of the EA Comm manual reveals a non-Modbus anomaly that contravenes the Modbus standard/spec, which, in my mind, makes it a proprietary protocol, not Modbus. Being proprietary, customers will encounter problems getting a Modbus compliant master/client to communicate with your slave.

It isn't clear whether what EA calls 'Modbus RTU' can function as point-to-point over RS-232 given the qualifications necessary for communication over Ethernet:

xModbus RTU over Ethernet.JPG

But lets' assume EA's protocol is sufficiently Modbus compliant to do Modbus RTU over RS-232. When implementing it one encounters a serious problem - EA's required unit/device/ID slave address of zero and only zero.

EA manual, page 14, Section 4:


The Master/client uses the address zero for the broadcast function. Page 8 in the Modbus Standard MODBUS over Serial Line, Specification and Implementation Guide V1.02, covering slave addressing:





Modbus compliant master/clients might use the slave address of 00 or 0 for the Modbus-compliant broadcast function where all slaves accept and read the broadcast message, but no slave is allowed to reply. Even in point-to-point communications with a single slave where there is no risk of comm packet collisions, the Modbus-compliant slave should not reply to a broadcast message.

My generic Windows Modbus Master, Modscan only accepts a Device ID (slave ID) of 00 for Modbus Function Code 05 (write single coil). So Modscan can't use your FC01 (read coil) or FC03 (read Holding Register(s)) to read data because it can't address your device at device address 0; Modscan can't use device address 0 with FC 01 or FC 03. That's an example of not being Modbus-compliant.

The RTU slave on my bench will not even accept a slave ID of zero, stating in an error message that the slave address must be between 1 and 247 which is compliant with the Modbus Standard.

Maybe comm over Ethernet using IP addresses crosses the hurdle of unit/device ID's of zero, but your customers and their system integrators are probably stuck when they encounter the limitations forced by device address of zero.
 
1. >the specs say that there can be up to 2000 coils, but it doesn't say that a device must support to read 2000 coils, whether they are all used or not, or if the limit can be lower.

There is no requirement to provide more coils than the device supports. It never makes sense to have non-existent coil addresses. An exception code 3 or 2 is typically used for coil addresses outside the device's valid range. See the FC 01 flow chart on page 13/51 (paper or pdf)) in Modbus Application Protocol SpecificationV1.1b.



>So far we defined that the user must always read 16 coils in order to get 16 in return. Reading less than 16 would also return error 03.

Requiring a minimum number of coils for FC01 (read coils) is not a user expectation. A Modbus user can reasonably expect to read 1, or 2, or 3 or up to 2000 coils in a single transaction by defining which coils they want to read with Function Code 01.

Here's the example from the Spec for FC 01:

FC01 Read Coils Request frame format.JPG
FC01 Response frame format.JPG

2. FC 05, Write Single Coil

>But with WSC I could not address all of these 2000 single coils because every addressable coil register already contains 16 coils.

'Write single coil' means writing a single (one only) coil in one transaction. One would not use FC 05 to write values to dozens or hundreds of coils, up to 2000 coil values. Function Code 15 (0F hex) is used to write multiple coils in a single transaction.

>but would have to read 16 to have the logical state (TRUE/FALSE) back.

Not true. Each coil is numbered, starting at zero (coil #1 = address 0; zero based addressing) up through the number of valid coils. Each coil can be addressed by its numbered address, either singly or multiple coils in a contiguous sequence.

I think your are confusing the value that a slave uses to reply to a FC05 function which is the coded byte 'FF00' for logic 1 ON or '0000' for logic 0 OFF with the bit value returned by an FC01 read function.

A Modbus-compliant Master/Client should understand that the value returned to FC05 is a mirror of the value that was sent, FF00 (ON) or 0000 (OFF).

The value expected from an FC01 Read Coils on the other hand should reflect the individual bit(s) for each requested coil with any remainder higher order bits in the byte padded with zeroes.

FC05 can read a single coil's value, the value of the single byte which will be either 01 hex (ON) or 00 hex (OFF), where the leading (high order, more signficant) digits in the reply byte are padded with zeroes, as explained in the FC 05 explanation in the Spec.

Note that FC01 (read mulitple coils) and FC15 (write multiple coils) both deal the number of 'bytes' needed to pack the bits representing the coils, and are not tied to a full 16 bit register.

Here is the example from the Modbus Spec for FC 05 (Write Single Coil)




Let's edit the FC01 query and response to read the single coil written by the FC 05 example Write Coil 172 to logic state 1 (ON):

Note that coil #173 decimal is 00AD hex, but with zero-based addressing its coil address is 00AC hex.

FC05 Write coil 173 ON (See the Function 05 Request above)

Now follow it with an FC01 Request

FC01 Request
Slave address xx
Function Code 01
Starting Address Hi 00
Starting Address Lo AC
Qty of coils Hi 00
Qty of coils Lo 01
Error Check Lo XX
Error Check Hi XX

FC 01 Response
Slave address xx
Function 01
Byte Count 01
Data (coil 00AC) 01 byte value 0000 0001 shows that coil 00AC is ON
Error Check Lo xx
Error Check Hi xx

The data value returned by the FC01 response, 01 is different that the data value FF00 returned by FC05, but that is by design.

For an FC01 poll, your slave needs to return the value of the coil as a bit, packed according to the Modbus spec, not the value FF00.

For an FC05 write command, your slave needs execute the write function and return either a data value of either FF00 or 0000, depending on what was commanded.
 
Thanks, David_2. Very informative.

Address: Yes, the address thing was also a topic. But something's interesting: what you cite here isn't part of Modbus_Application_Protocol_V1_1b3.pdf and Modbus_Messaging_Implementation_Guide_V1_0b.pdf. Both don't define that when using the broadcast address slaves must not reply to it. Since we don't sell any interface for ModBus RTU that is serial line, we didn't look into the 3rd specification and broadcast isn't used anyway and so we defined 0 as address. Our problem: the different papers don't say like "you must also implement everything from ...".

However, isn't this paradox? "In broadcast mode, the master can send a request to all slaves. No response is returned to broadcast requests sent by the master". A request is, by definition of the word, something that expects an answer.

FC 05: Coils are organized on addresses. Let's say I have one coil on 0x1000 and the next one on 0x1010 (there is no definition that coil space must be continuous), then I can use this function to write them separately. But how to read? FC 01 reads x coils starting from a specific address. Even if our coils were organized continuously, means 0x1000 and 0x1001, then I my logic fails that FC 01 with an argument of 2 would read the two coils from 0x1000 and 0x1001, plus there would be no assignment, which of the two bits in the response would be assigned to 0x1000 and which to 0x1001.
From what you wrote it seems that using FC 01 with argument 1 would be the solution to sort of do a "READ SINGLE COIL". This would mean, we would have to define these single coils on separate addresses and all just readable by 1. OK, that's doable, but still silly.
 
My mistake in post #3. I meant to insert the screen shots for FC01, but by mistake inserted the screen shots for FC05.

I have edited post #3 so that the screen shots for FC01 are where they are supposed to be.

I'd suggest working through the FC01 example, where it reads coils 11-23.

You'll see that FC01 can read as few or as many contiguous addresses as specified and packs the reply is 8 bit bytes with zeroes padded in the last byte if needed to fill the 8 bits. It's based the assumption that the coils to be read are contiguous. If there are 'holes' in-between, then faulting with an exception code will prevent FC01 from reading.
 
I have to say from my personal opinion that Modbus is a partly unclear specification.

However, we found a way to solve the READ COILS topic. We really have to return one byte being set to 0x01 when reading a coil after it has been written with 0xFF00. Doh! :oops:
 
Top