Author Topic: RS485 communication handling  (Read 6055 times)

0 Members and 1 Guest are viewing this topic.

Online paulca

  • Super Contributor
  • ***
  • Posts: 4450
  • Country: gb
Re: RS485 communication handling
« Reply #25 on: March 12, 2023, 09:53:32 am »
On minimal, robust, small footprint, performance messaging protocols for text streams.  It could be worth spending 5 minutes scanning the FIX protocol.

https://www.fixtrading.org/

For the context here, you can ignore all the application tags and only consider the protocol tags.

Features of use, probably on UART.

* Preamble w/ message type and length.
* Postamble with checksum and trailer
* Bi-directional message sequence numbering
* Reconnection with or without correct sequence numbers*
* Message resend or "gap fill" to resynchronize.  (in the case of an MCU I would expect that to be 99.9% "gap fill" only maybe keeping messages classed as "Last will and testament" priority.
* bidirectional heartbeats/pings

*connection in this case refers to the handshake of establishing sequence numbers and "identity" of the party.  While TCP is usually used for the protocol, FIX can arguably be sent on any async bi-directional protocol.

EDIT: I am going to try and use it for my own purposes.  A few notes:

It should not be hard at all to find an extremely high performance, minimal footprint FIX parser in C or ASM for Arm.  (There I would need to be a little careful with latent IP).  The basic parser works much like any UART protocol of "mixed length" async messages.  Read the minimal header to detect an incoming message, start streaming it into a tokenizer which pops out tag=value pairs at you.  Keep popping them onto a stack until you get the length.  Then you can reserve space and let the stream run while you carry on tokenizing your way through the message.  You can tokenize it into a big tree structure in memory which is slow, but only needs done once, or you can "strike through" process and trigger events in a state machine as and when combinations of tags are received without waiting on the rest of the message.  Risky, but where this is used any dirty trick makes money.

In the real world a lot of code goes into the session layer with identities and parties and authentication/encryptions, but we don't need none of that non-sense here.  So other than checking the SenderCompID is "Your devices's ID", all of that goes away.  Sequence number coherence is up to the sender and receiver.  In the most simple form, you just sent gap fills both directions or demand a reset sequence numbers on all connections and abandon resent completely.  It can be very, very handy though, if you get SQ# 1, 2, 3, 6, 7... you can send a "WTF?" message back asking for 4 and 5.  On low foot print without memory to reorder yourself, you could just pretend you didn't get 6 or 7 either.  Given the other end might be low memory as well, it's likely to just say, "Sod it, new sequence number is 8, we are good.".  It's just that the protocol has mechanisms to enforce these so that both parties are 100% aware of any message loss.

I think one hurdle in your case will be the ModBus/RS485 protocol of any other devices on the bus.  You will need to at minimum filter only messages from devices you want at the Modbus layer.  Also.  Doesn't modbus work more like I2C with register sequence read/write.  You could wrap that in FIX to get resilience, convert registers to tags or just a blob in one tag.  FIX might be better suited to bar UART.
« Last Edit: March 12, 2023, 10:21:33 am by paulca »
"What could possibly go wrong?"
Current Open Projects:  STM32F411RE+ESP32+TFT for home IoT (NoT) projects.  Child's advent xmas countdown toy.  Digital audio routing board.
 

Online woofy

  • Frequent Contributor
  • **
  • Posts: 415
  • Country: gb
    • Woofys Place
Re: RS485 communication handling
« Reply #26 on: March 12, 2023, 10:52:40 am »
the datasheet (SAMC21) states:

31.6.2.6 Data Reception
The receiver accepts data when a valid start bit is detected. Each bit following the start bit will be sampled according
to the baud rate or XCK clock, and shifted into the receive shift register until the first stop bit of a frame is received.
The second stop bit will be ignored by the receiver.
When the first stop bit is received and a complete serial frame is present in the receive shift register, the contents
of the shift register will be moved into the two-level receive buffer. Then, the Receive Complete interrupt flag in the
Interrupt Flag Status and Clear register (INTFLAG.RXC) will be set, and the optional interrupt will be generated.
The received data can be read from the DATA register when the Receive Complete interrupt flag is set.

I'm not entirely clear here. If I read this literally the buffer will just keep accepting the "data" until the line goes high, so if there is a spurious low pulse I will get a "0" byte if it lasts longer than 9 bits worth.

Yes, you will get a spurious byte. Most UART's use oversampling, which in practice this means they take 3 samples in the middle of the bit time and use majority voting to decide the bit. The thing about real world interference is that it is very short sharp spikes, not continuous highs or lows. Unless you are using very high baud rates the UART can filter a lot of this out for you.

If you have control of the CPU in the HMI and an available uS level timer then the scheme I outlined at the start of this thread should provide a simple but robust solution. It's based on one of my own applications (my day job is designing industrial controls)  where I use 250k baud RS485 communication on anything up to 1km as it routes through the building(s), with up to 128 devices on the bus. I use a leading zero byte, followed by the target address, payload length, payload and CRC. Using 9-bit data gives a 44uS byte time and bytes are always transmitted back to back. I set/reset a 60uS timer for each byte and if it times out before the next byte is received then that's end of frame. I can then verify the length, verify the CRC and extract the payload.
On the other hand if you are working through an OS in the HMI then this may not be possible.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18210
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #27 on: March 12, 2023, 07:15:32 pm »

A modern UART uses oversampling and other techniques to reduce error, but it still boils down to seeing a start bit and then clock the data into a shift register. If the stop bit is not seen at the right time it can raise a framing error, but you have to check for it. Think it will still signal a data set received.


This is what I fear the issue is, and with the RX and TX tied together there is a chance of getting such gibberish.
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 5054
  • Country: nl
Re: RS485 communication handling
« Reply #28 on: March 12, 2023, 07:53:27 pm »
That is the thing with RS485. At the sending terminal you will receive what you send. If there is the need for some multi master setup you need collision detect and bus arbitration. But in a simple setup as laid out in the original post it seems like just one master (HMI) and one slave (ECU), at least for your first tests, all you need to take care of is that the slave (ECU) never enables it's transmitter unless asked to do so by the master (HMI). The master needs to disable his transmitter to allow the slave to respond.

So to report status, you need to poll it, initiated by the master.

If you have problems with receiving wrong data in your test case, I would strongly advice, like already given by someone else, to hook up some test equipment on the bus and check what is happening on it.

Offline PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 2311
  • Country: au
Re: RS485 communication handling
« Reply #29 on: March 12, 2023, 07:58:20 pm »
The actual communication seems to be fine. but when I tried receiving data from the other device (ESP32) and then sending it back I was sending back 0's. But there was also some data that changed. So I have become suspicious that I am getting out of sync with the datastream as I have no way of knowing that the byte I just received really is valid.

Try single byte echoes first, with something trivial like add-one or invert to the echo. That does not even need interrupts and confirms HW and Baud are ok.
Then you can step up to a burst of eg incrementing numbers, and check your buffers and interrupts do not overflow.

Using a gap as a block identifier is great, provided you have systems that do not have complex operating systems that can create a gap :)
Typically a timer-monostable is reloaded on every Char RX-INT, and when the timer actually times out, you know you had a gap. Set that to maybe 80% of the actual time so yo u have room to check size/checksums etc



This is what I fear the issue is, and with the RX and TX tied together there is a chance of getting such gibberish.
They should be valid whole characters, and during TX you usually accept and discard RX, tho you could confirm they matched TX.
Some RS485 designs pre-bias the cable, so that a floating driver does not sit close to the receive threshold.

 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18210
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #30 on: March 12, 2023, 08:21:37 pm »
i have a SAMC micro controller and an ESP32 (colleagues work), me sending works. Me receiving not so. I'll have a go tomorrow with the start byte, I suspect that the transmission is creating a ghost reception so when I do come to receive I am one byte into the buffer already, I send that back and slowly it all turns to 0's as at each message a byte is dropped for a "0".
 

Online woofy

  • Frequent Contributor
  • **
  • Posts: 415
  • Country: gb
    • Woofys Place
Re: RS485 communication handling
« Reply #31 on: March 13, 2023, 08:36:05 am »
i have a SAMC micro controller and an ESP32 (colleagues work), me sending works. Me receiving not so. I'll have a go tomorrow with the start byte, I suspect that the transmission is creating a ghost reception so when I do come to receive I am one byte into the buffer already, I send that back and slowly it all turns to 0's as at each message a byte is dropped for a "0".
What are you using for the RS485 transceiver? The usual device is an 8-pin ST485 or equiv. These have separate drive and receive enables, DE active high and RE active low. Just tie them together and you cannot receive what you transmit. You will need a pullup on the RO as RE tristates it. If you have them tied together, but no pullup resistor, that could be the source of your spurious byte.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 18210
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: RS485 communication handling
« Reply #32 on: March 13, 2023, 01:46:57 pm »
Yes I was wondering about that, I think it is the falling Rx line when I transmit that was triggering a reception.

It's all working now with a start byte.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf