Detect in software when a serial byte is being received

I have a bidirectional Rs485 bus with up to 4 arduino's. I have not built in any fail-safe collision prevention because the amount of messages is very low (1 message per 10s or so), it is unlikely that a collision ever occurs, messages aren't that critical and the master arduino in this setup is the sender for 98% of the time. There are 2 whole inputs on slaves which sometimes send a message.

Anyways when thinking about it, I got me a question. I do have some interlocking built in.

In order to drive the RE/DE lines I continously monitor the serial buffer with these lines of code. As soon as availableForWrite reaches 63 I am 100% all bytes in the buffer are transmitted and I can release the bus.

    if( RS485->availableForWrite() == 63 
    &&  digitalRead( rs485dir ) )
    {
        digitalWrite( rs485dir, LOW) ;
    }

I also have a simple interlocking mechanism with which a node will not try to transmitt a message when he is receiving a message at that time (the baudrate is set at 9600 and a transmission may easily be 20 bytes)

This detection uses Serial.available(). As soon as it returns 1, a node knows there is a message incomming and the node shall not transmitt himself.

Serial.avaible() returns 1 after the first bytes is received. This means that during reception of the first byte of a message there is a small window (roughly 1 ms @9600bps) in which a node may attempt to transmitt and cause a collision.

The one thing I want to know* is how to get a signal in software when a start bit is received. Knowing this, may minimize this collision window.

I have been digging through chapter 19 of the atmega328 manual but a flag in the USART registers for start bit detection seems to be lacking.

Is this correct? or have I overread something?
Is it possible to also enable the pin change ISR (PCINT16 for Rx) while using the USART. Or does the one exclude the other?
If not. Would it be feasible to hook up an an extra IO pin and use that pin's pin change interrupt to detect start bits.

Regards,
Bas

.*
I am fully aware of every other method to prevent or solve collisions. Time windows, checksums, tokens passing, even modbus etc. I am not seeking information about this. I only want start bit detection.

I'd simply check the state of the RX line. A LOW on this line indicates that any node tries to send something.

why add the complexity of connecting a interrupt to an input pin and monitoring for a start bit if the message rate is very low?

why not use a conventional approach, polling or just accept the possibility of collision, capture all output, verify it matches what is being sent and retransmitting if it doesn't

That seems to work. I hooked up pin 13 to follow the inversed state of Rx. And the led flashes during receiving at 9600. At 115200bps I needed to send more bytes in order to see the led. I cannot tell how reliably that works. Especially if void loop() takes a little longer.

I only don't have a scope so I am cannot tell anything meaningful about the timing. For the time being it looks like a nice hack.

why add the complexity of connecting a interrupt to an input pin and monitoring for a start bit if the message rate is very low?

Because who knows, I may ever get a need for it in the future. And most importantly. It simply saves me time :smiley: by not using a different approach. The project is nearly complete.

why not use a conventional approach

Like you pointed out, at this moment I don't really have a need for anything fancies like this. I figured that if you can detect the start bit, you would not have to use anything half complex to prevent collisions. If the traffic isn't that heavy it may be more than sufficient to prevent problems. And I can easily outfit my source code with this. Not that I need it but still..

Regards,

Bas

Unlike you I am lazy, I use CAN it does all of the work for me. With CAN you can just forget about it and when a message comes it will give you an interrupt.

Hahaha. No I am also lazy, I really am. I even let my computer do some coding for me sometimes :stuck_out_tongue:

I know CAN but the hardware would be significantly more intensive labouring. I would need both an MCP2515 and 2551. (I really loath soldering, boring job)

I use arduino nano's and there are no can bus shields for those. I developed and ordered my own nano shield which just have 2x RJ12 connectors and a max485 IC + cap and some R. Oh and there is an alie buckconverter with castellated holes for some servo powah. This shield goes between the nano and an IO base.

And to screw around with those breakout boards and jumper cables., yeah... no, not me :joy:.

Next time I may design a new board, which has MCU, CAN and everything else on board and let JLCPCB assemble it for me ;-). Long live lazy engineers!

EDIT: found a picture of them
Those 3 thingies on the right

Regards,

Bas

not sure your application is for model RRing as the photo suggests.

if it is, the NCE cabbus uses a polled RS485 bus. Digitrax LocoNet doesn't use polling but needs to detect collisions, which i haven't figures out exactly how it does it except to read what it sends and detect corruption

nodes on an NCE bus need to respond within 800 us before the master generates a poll to the next address to minimize the time to poll all devices

not really. Use a microcontroller with native CAN. For example an ESP32. You just need an CAN Transmitter. One IC. Even available as DIL if you don't want to use SMD parts.

It is. The main controller (thing on the left) handles 3 control panels (via flat cables) and controls the slaves. It is also connected to a command center via XpressNet. XpressNet also works with RS485 and polling. The slaves are electrical compatible with XpressNet but I don't use the protocol for the slaves. XpressNet is somewhat limited in what it can send. It could work, but SW would become more complicated. Now I can easily configure a servo with positons, speed and optional frog relay.

As the slave shields are made compatible with XpressNet they can be easily repurpose'd for things like DIY control panels. I made 2 simple programs with which you can create your own control panel. The program allows you to teach in up to 20 addresses per switch. No programming required.

The NCE bus in Europe is not much used. Perhaps some in the UK use it? idk tbh.

I also made a loconet shield for nano's as well as a single PCB made using smt assembly service. but I am yet to test those puppies.

Regards,

Bas

i'm working on C/MRI nodes on the MR club in Cumberland using esp32. i've planning and have partially working WiFI interfaces between node to avoid some of the issues you're dealing with.

i'm curious how LocoNet recognizes and handles collisions

I am sorry about that, this new forum style is terrible IMO. I once did a post in the emergency covid respons area... -_-"

1 Like

I understand the soldering, I just used the modules, they are less then $5US from china. I have gone through about 40 and no failures. I used Cory Fowlers CAN library, they worked first time. I used the Send and Receive sketches, no problems. I did check clocks etc as I have seen them modules with three different crystals on them. I have both the send and received combined in one program, only took about 1/2 hour maybe less.

I spend many weeks with the RS484 and the only way I could get some reliability was for each node to monitor what it was sending. If it did not match waite a bit of time and try again. Each target had to acknowledge the message if the checksum was valid.

1 Like

That I cannot tell you (yet). I do know they use one bi-directional communication line and 2 IO pins. The line is pulled up and every node can pull it down with a transistor. To 'undo' the noise a comparator is used as schmitt-trigger. Essentially the Tx and Rx are tied togather.

If a node is transmitting, it should be able to read back his own message. Perhaps that a sender can detect a discrepancy during a collision. Otherwise a checksum will probable fail somewhere. idk

Digitrax states this:

LocoNet's transmission protocol is similar to Ethernet "Carrier Sense Multiple Access with Collision Detect"(CSMA/CD) optimized for model railroad layout control.

(My compulsory cisco course was over 7 years ago :see_no_evil:)

100% traffic capacity with less than 1 in 300 collision rates (not possible on Ethernet).

If you have nothing left to do:
Link to loconet pdf

Regards,

Bas

> They are responsible for detecting transmit COLLISIONS by checking their TRANSMIT ECHO data

the note doesn't describe how to check for TRANSMIT ECHO. i imagine this could be a comparator of the Rx and Tx pins connected to an interrupt and the ISR would immediately disable Tx as well as suspend transmission of the remainder of a msg.

another approach would be to check the byte received on Rx during Tx and suspend transmission after the 1st byte, but by then probably both transmissions are corrupted

have you considered either of these approaches for your application

On a half-duplex line only a loopback test makes sense. It should be supported by firmware for comparison at no further cost and a chance for killing ongoing (corrupt) output instead of Stream.flush().

I dont think this can work for a MAX485. I don't believe you can find out that an other node is transmitting when you are transmitting yourself. This is why I started this thread to detect when a start bit comes in. It does not solve this particular problem but prevent it from occuring.

the note doesn't describe how to check for TRANSMIT ECHO

I think that with loconet you do can detect the startbit of a message so you atleast know when you need to shut up. I think that this is part of what prevents collisions from happening in the first place for 299/300 times.

To detect that 1/300 case.. when you release the Tx pin during a transmission you can monitor the Rx to see if it follows. Were Rx to remain or become LOW after you release Tx, you know for sure some other node is also sending.

This is the used circuit.


Regards,

Bas

about that consideration question. I want to incorporate loconet myself in the near future. It is the most flexible protocol IMO.

Simple solution: find out yourself whether you are right :slight_smile:
(Hint: you are wrong)

there's a difference between recognizing

  • that you're transmitting while someone else is (the echo from the Rx pin does not match what is transmitted) and

  • immediately recognizing that a received bit doesn't match the transmitted bits and immediately suppressing transmission (disabling Tx on an RS485 converter) to avoid corrupting the other transmission

It hit me!.. I think... I always connect RE and DE to the same pin. So my thinking stopped right there when I made certain comments :zipper_mouth_face:

If I enable both receiving and transmitting at the same time, can I then read back that what I send and thus detect a collision?

I am going to do some testing when I get home.

Regards,

Bas