CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

UART again
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Wed May 21, 2014 7:45 am     Reply with quote

ezflyr wrote:
Hi,

Well, is the '0x04' totally unique, or might it also appear as part of the 'data' or 'CRC' later on? If this character is not 100% unique, then yes, your method is still flawed....

As Ttelmah pointed out, the interval between messages in Modbus is well defined, and easy to test for. It seems to me that this is the only unique thing that occurs in your communications protocol. Why not use it?

John


0x04 is not unique
No value is unique, as CRC byte can be 0x00 to 0xFF

0x04 is always at this place
and char 0 is either I_Adresse_Box = 0x01 to 0x20 (and in this case char 1 is MODBUS_READ_ANY=0x06) either BROADCAST_ADDRESS=0x00 (and in this case char 1 is MODBUS_WRITE_ONE=0x03)

The delay between 2 messages is, presently, approx 500ms (which is rather more than 3,5 char), that is why one idea was to implement a time out.

I will think of such a solution to compare.

(I think to reset a timer when receive a char, and to proceed when I have received UART_MESSAGE_LENGTH chars or when the timer goes on)

But, I am the norms oblige me to proceed within one second from the supervisor ! 1s is only 2 times 500ms so I only may lose one message, not 2
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed May 21, 2014 8:16 am     Reply with quote

Hi Jean,

If 0x04 is not unique then I think you've answered your own question! It may *always* occur at position #4, but what makes you think you are always going to stay synchronized with the Master?? Won't happen 100% of the time in the real world!!



John
Ttelmah



Joined: 11 Mar 2010
Posts: 19732

View user's profile Send private message

PostPosted: Thu May 22, 2014 12:27 am     Reply with quote

The key here is to understand what Modbus does, and 'why'.

Now as has already been pointed out, you cannot (must not) use a 'value' in the packet as a marker, since _any_ value can at some point appear. Hence to avoid this being a problem, and allow the messages to be reliably identified Modbus requires that inside a 'message' there is never more than 1.5 character times delay between characters, while at the start/end of the message there is a 3.5 or more character time pause.

'Value' searches are always going to eventually lead to problems. The 'dead horse' analogy definately applies here.

So the receive code, instead looks for the T3.5 gap as the 'end of frame' marker.
This is _not_ a timeout. There is a separate timeout behaviour, where a master, requesting a response from a slave, finds it takes too long to reply.
Normally 1 second, but can be extended when working over links with a very high latency.
A single lost character can be identified as giving an interval between the 1.5 character time, and the 3.5 character time. Allowing the message to be 'invalidated' without having to continue and perform the CRC check.

Start by getting the Modbus over serial spec sheet. This gives a nice little state machine (figure 14), showing 'how' the transmission and reception are expected to be handled.

Then realise that there is Modbus master, and slave code, supplied with the compiler. It has some faults (doesn't implement everything quite as it should in some places), but generally will function correctly, and identify the messages.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Thu May 22, 2014 10:22 pm     Reply with quote

If the protocol can't be changed, too bad, but this is the method I've used, and it seems to work:

Start every packet with a "start character". In principle this can be any value, though my favorite is 0x0F, because it has 5 low bits and then 5 high bits, and might give some immunity to misreading. Anyway, select something. So what happens if it comes in as data? Then it gets sent twice in succession. This means that if any unit mistakes a data byte as being the start byte, before that "packet" (which actually began on a data byte, not a legitimate start byte) can end, there will be another start byte, this one correct. When the subsequent character is not a start byte, it should alert the erring unit to discard the partial packet that it thinks it's receiving, and start a new one.

Is this foolproof? I think it's pretty good.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Fri May 23, 2014 1:57 am     Reply with quote

Practically the message is 9 char long and comes every 500ms

The supervisor queries set with adress 1 then 500ms later set with adress 2 then ... and so on til set 32
At this moment it send again the broadcast command ( that means if a set did not react the previous time, it can react this time, 16s later)
And queries again ...

The message is 9 char long which are :

I_Adresse_Box = 1 to 32 or BROADCAST_ADDRESS (0x00)
Function_Code which can be MODBUS_WRITE_ONE(in case of BROADCAST_ADDRESS) or MODBUS_READ_ANY (in case of I_Adresse_Box) nothing else
nn
nn these 2 char can be anything
MODBUS_DATA_LENGTH (=0x04 always)
xx
xx these 2 char are the datas linked to Function_Code.
crc
crc

so, at each moment when I have at teast 9 chars in my buffer, I can check the following rule :

is char 5 equals 0x04 ?
is char 1 is BROADCAST_ADDRESS ?
is char 2 is MODBUS_WRITE_ONE ?
is CRC OK ?
or
is char 1 is me (my I_Adresse_Box) ?
is char 2 is MODBUS_READ_ANY ?
is CRC OK ?

I have not calculate the probability of "bad message"
eg 2 successives messages :

..... 01 03 03 nn 04 04 00 0D crc crc 04 03 ...

the set analyses the following message

01 03 03 nn 04 04 00 0D crc

Really, I think there is low chance that 0D crc is the correct CRC16 of this message
so it left shift one char and analyses the following one

03 03 nn 04 04 00 0D crc crc
which is correct
and resynchronize by UART_MESSAGE_LENGTH left shifting

In case of bad transmission, it lose it, but with any type of routine it will lose it so it will see the next one

I am not able to develop a risk calculation method

How do you react to this risk analysis ?

So, what I mean : I am conscient this method is not an universal method, but it looks simple and rapid and as far as now it works.
I still have to experiment in the real world, with 32 sets, and noisy environment.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Fri May 23, 2014 2:31 am     Reply with quote

Oh dear :-(

As far as I can see, this thread set off on the wrong road right from the start. As a result the discussion has been about the issues of framing in asynchronous comms, which is interesting and worthwhile in its own right but does not really address the real problem.

The real problem is not "how to detect start and end of packets?" but "how to do a Modbus slave on a PIC?" As Ttelmah writes, there is working Modbus code supplied with the compiler. Its not perfect, and needs some work by the programmer to configure it for a particular PIC, and to implement the command handlers. Basic ones are provided as examples, but will almost certainly need expanding.

Modbus really isn't a problem on PICs with CCS, just include the Modbus driver code, configure it for your system and the difficult stuff - getting the protocol, including the timing - right. Many of us have Modbus slaves working on PICs. I do, it's not that big a deal, though there are potential "gotchas".

As to the framing issue, Modbus was a relatively early protocol, intended to be implemented in discrete logic rather than programmable devices. It uses timing to determine when a packet start and stops. All that was required were a few 74123 monostables. Things moved on, indeed they had even by the time Modbus arrived, and most later protocols used in-band framing - i.e. start and stop characters, rather than timing.

Many modern protocols are bit stream based and use a unique bit pattern to delimit the start of frames/packets. As others have discussed, there's a problem if that pattern can occur in the data or other parts of the packet. Having just a low chance of it happening is often not really enough, for a reliable protocol it has to be unique, and CANNOT occur in the data.

How can this be arranged? How can we make sure the start pattern is truly unique? The answer is we have to do something to make sure its not present elsewhere in the frame. We have to actively alter the contents of the frame so that if that pattern were to occur, it looks like something else.

For bit streams, the technique commonly used is "bit stuffing". A common start pattern is 01111110. To make sure this can never occur in data, an extra 0 bit is "stuffed", i.e. added, to the bit stream whenever five ones are present, regardless of what comes after. So if 01111110 appears in the data it is transmitted as 011111010 (and if 011111010 was in the data it would get sent as 0111110010). At the receiving end if there's even five ones followed by a zero, xx111110xx then the zero is stripped. IF there's six ones, xx111111xx then its the special start bit sequence. CAN does bit stuffing, but for a slightly different reason - it has a distinct electrical state that signifies start of packet.

That's fine for bit streams but not much good for byte streams such as RS485. You can't just stuff in and strip out bits as you go along. However you can byte stuff. You can use escape sequences to make sure framing bytes are unique in the transmitted packet. This is just a slightly more formalised version of JohnP's scheme.

I use a very simple scheme. I have start of packet and end of packet bytes: I use ASCIIs STX and ETX, 0x02 and 0x03. If these occur in the data I put ASCII ESC (escape) 0x1B before them, sending them as ESC STX and ESC ETX. Obviously ESC has to also be escaped, sending ESC ESC for every ESC character in the data. When receiving if there's an ESC I strip it out and read the following character. If any of these characters occur without an ESC before them then they are the special framing characters.

But as interesting as all this is - without bit stuffing we couldn't have the Internet as it is - I have to reiterate that the real problem here is not how to frame packets, which is moderately hard to do well, but how implement a Modbus slave, which is fairly simple as CCS has done the hard work for us and supplied the code to do it.
jeremiah



Joined: 20 Jul 2010
Posts: 1371

View user's profile Send private message

PostPosted: Fri May 23, 2014 6:06 am     Reply with quote

Definitely, but to be fair, MODBUS wasn't mentioned till later in the thread after most of the async framing options were presented. In retrospect, it would have been better if the OP started out with that info in the intro post. Perhaps some of yall experienced with MODBUS caught on early, but I've never used it myself, so I it didn't come to mind initially for me.
Jean FOUGERON



Joined: 30 Nov 2012
Posts: 110
Location: France

View user's profile Send private message Visit poster's website

PostPosted: Fri May 23, 2014 6:16 am     Reply with quote

Oh Dear Sad

Only to remember that the problem here is to discriminate the message sent, not to write a Modbus lesson.

The real is, somewhere in the world there is a supervisor which sends the sequences described.

Call it modbus or whatever else is not the problem.
The problem is to correctly answer to this existing message

That'all
Ttelmah



Joined: 11 Mar 2010
Posts: 19732

View user's profile Send private message

PostPosted: Fri May 23, 2014 7:05 am     Reply with quote

The point is that the 'correct way' to handle this message, is to use the protocol.

The protocol allows any value potentially to be anywhere in the message.
It _requires_ that you use the correct timing handling to be 'confident' you know where you are in the message.

You have started out on the 'wrong foot', and need now to take a big step back, and start on the correct foot. Use the defined timings to correctly decode the message.
It is not exactly hard to do.
Even better, if you don't want to get involved in doing this use the already supplied code that does this.

It's like trying to use diesel in a petrol car. Sure to result in an engine that misfires, and eventually dies....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group