Help: detecting idle on UART

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi folks.

I need to detect idle state on UART for implementing multi-master rs485-based communication protocol.
Basically I need to detect when line is high for specified amount of time.
I can use retriggerable monostable multivibrator (74HCT123) for it but I'm hopping for software-based solution.

Any ideas ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Poll the pin state? Use input capture with a secondary compare? Use a free-running timer for comparison when the edge changes (roll-your-own ICP)?

It really depends on what a "specified amount of time" is. different approaches would be used for 3us, 3ms, 3s, 3h, or 3d. What accuracy and precision and latency are needed?

When it is ModbusRTU and a "few milliseconds" of idle time signifies the end of the message, then none of the criteria are critical. We have a timer running when the USART is active, and restart it in each Rx ISR. When it expires, Bob's your uncle. Quite simple, really, and you don't have to route RXD to more than one pin. But if you want microsecond accuracy and/or precision then you'll probably have to do something else.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup, you're right - not enough information to advise a fitting solution.
Let me clarify.
I'm running bus with failsafe biasing lines to encoding of '1'.
UART is set to 115200[b/s], 8-bit, no parity. I want to be able determine if MCU can start transitting ( when line is 'idle').
For each byte 10-bits are transmitted, so I need to dermine if 10+ (or 20+ to be safe) are all set = no frames were transmitted for 1+ or 2+ frame timeslots.
Clock is 3.6864MHz, so each bit is 32 clocks.
Triggering ISR every 64 clocks to reset counter (in case of 01010101 combination) is out of the question (too much consumed resources).
If there's a continuously running mode (like Normal) that triggers reset on pin rising edge without using ISR - please enlight me - it would be dream come true.

For power efficiency MCU is going to sleep as often as possible, so pooling is out of the question.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

For power efficiency MCU is going to sleep as often as possible, so pooling is out of the question.

Let's examine that for just a moment: RS485, with bias resistors and load resistors and multiple drivers. The "idle" current from your RS485 "network" is going to dwarf your AVR current.

I'd think that from what you described that the Modbus method would work fine. Restart a timer in the RX ISR for one or two character times; when it expires you are idle.

I don't know how (or if) you can peek at the USART RX to see if it has seen a start bit. I guess you could count transitions with a pinchange or external interrupt.

I think js and others that do multi-master RS485 don't worry about the "fine" points like that, rather they may use a "coarse" timer as I have described, and have both TE and /RE enabled and listen to what they transmit. If it is not the same it is a collision and they back off.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Every character tha comes is resets a timer??? By looking at the timer you know how long the buss has been idling. May have to think about timer overflow too if the time between transmissions is fairly long.

..and I knew someone with ALMOST the same name as you, unless you are that someone.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Assuming that your master receives as well as transmits, start a timer (set to some "bus is idle" time > 1 character time) running every time you receive a character. While other masters are transmitting the timer will keep getting reset. When the bus goes idle the timer will eventually time out and that's your indication of an idle bus.

The big problem with this is that another wannabe-master's timer may also have timed out and then both masters will try and grab the bus and have a collision. There are different ways to avoid or deal with that problem. One is to have the masters pass around a token indicating which master is allowed to talk next.

Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch: I'm using RC termination, so bus idle takes virtually no power.

snarflemike: Problem you described is the reason I don't want to go that route.

My current approach is to use additional low-power MCU (ATtiny13A) as a wannabie-MAC. It's reponsibilities will be comparison of RX and TX data (bit-banging), singnaling per-bit collision to "master" MCU, detecting silence by counting consecutive ones on the line, signaling idle bus state to "master" MCU and controlling driver-enable of RS485 transceiver.

I must detect per-bit collision, because I'm implementing collision avoidance very similar to CAN-bus operation.

If anyone has other idea how to do it - please share it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

maciek_urbanski wrote:
My current approach is to use additional low-power MCU (ATtiny13A) as a wannabie-MAC. It's reponsibilities will be comparison of RX and TX data (bit-banging), singnaling per-bit collision to "master" MCU, detecting silence by counting consecutive ones on the line, signaling idle bus state to "master" MCU and controlling driver-enable of RS485 transceiver.

I must detect per-bit collision, because I'm implementing collision avoidance very similar to CAN-bus operation.

If anyone has other idea how to do it - please share it.


I hate to sound negative, but what you are suggesting sounds very difficult to implement properly, especially on a separate processor that does not have "direct knowledge" of the transmit clock. Having an external processor determine if a transmitted bit is undergoing a collision is not a trivial matter.

It would be useful if you would give more information about the entire system, especially what the nodes are communicating and when they need to communicate. I think you need to step back and re-evaluate what you are trying to accomplish.

Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, let me give you some context.

I'm starting to build my own house and since I'm a low-level programmer with 15+ years of experience I want to create a smart home.
At the same time I'm a beginner in HW design, so there's a lot of smoke during my experiments. :)
Entire project is scheduled for 4-5 years, no no pressure here.

I'm implementing a bunch of smart nodes responsible for lighting (home lighting will be led-based), temperature, humidity, incident light, detection of mechanical triggers, etc.

Since most of my professional career was about some form of IP processing (mostly in ATCA blades, but recently some funky microcode optimization) I'm trying to design IP-like protocol with some trivial multicast extensions. SW-wise it's easy, but HW is another matter...

As for data: most time nodes will send sensor readouts (but each node can have 5+ sensors) so most time it will be a low-payload packets. But I want to handle node SW upgrade via bootloader.

And since my very basic protocol (an amalgam of ideas stolen from CAN and Ethernet) seems more than capable (on the paper and some PC simulation SW) - I'm experimenting with HW.

As for my sudo-MAC - I shamelessly stole this idea from AVR-USB project. Basically I have 32 tacts per bit on the bus, so there seem to be enough time to 3 samplings of line and voting.
My rs485 transceivers have 60ns max. driver-to-receiver delay, so for 115200 b/s it's about 0.68% of bit width... This means that i can sample both TX and RX data ignoring their delay.

Of course - I can be completely mistaken, and if I am - I'll adapt. I have lots of time. 8)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you are over-worrying about this with nanoseconds and bit times.

Full-character delays to check for idle, plus collision detection (and backoff) when transmitting should be fine.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
I think you are over-worrying about this with nanoseconds and bit times.

Full-character delays to check for idle, plus collision detection (and backoff) when transmitting should be fine.

You're probably right, collision avoidance in such low-throughput networks might be unnecessary.

I'll code a simulator and we'll see how it behaves.

As for detecting idle - some developer of smart-home in polish forum found partial answer. :)
Connect T0 pin to RX and use Timer/Counter0 with external clock source. It will increment with each change on the bus.
When waiting for idle use second counter for time measurement.
If counter0 did not increment and counter1 incremented by specified amount - bus is idle.

Yes we still have to check from time to time, but it's not pooling anymore.
And there's a chance that counter0 increments by 256 between measurements, so time when we test is somewhat limited...
But it's better than nothing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But 1) You don't need fine resolution for idle; 2) Even if you count idle to the nanosecond, by the time you start sending another node could start sending so you still need collision detection and backoff.

So keep it simple.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, sounds like good clean fun! :)

Again, for the bus idle check, I'd start (or restart) an idle timer every time a character is received, and when the timer times out assume the bus is available.

For collision detection, check if each character sent is correctly received by the sender. If not it's a collision. Include a CRC in every packet for all the obvious reasons.

Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Maciek,

Some time ago I build my own home network from scratch. I implemented collision avoidance in a pretty simple way:
Every time a wanna be master wants to grab the bus it checks if the bus is idle for 1 byte time. If it detects an active bus (start bit) it aborts. Else it grabs the bus and immediately starts sending a packet to the bus. Because there is a very small delay between the checking for an idle state and sending the data this works pretty good.

The rest of the packet is send to the network via a small interrupt routine.
After the last bit of the packet is shifted out of the shift register the "end of transmission" interrupt is triggered which does some housekeeping and resets the RS485 driver to the "listening" state.

You can find the complete code together with some schematics and projects on my website.

Have Fun,

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A further thought: RS485, with its bus/daisy-chain configuration, may not be my first choice for "home automation" where it would seem a star configuration would be more desirable. I guess you could run twice the conductors to each node, and then at the central point wire one to the next. A single break in any of the wires might well render the whole network unusable and unable to communicate.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lee,

that's exactly why I have a "hub" or "switch" on the wishlist for my home automation network. This would make it possible to disconnect (parts) of the network.

Have Fun,

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@theusch Daisy chain is not my preferred configuration either, but I'll have to live with it. I'm "faking" star configuration (from a cabling standpoint) running two pairs in one wire, connecting them inside plug going into node and using passive "hub" (think 10base-t hubs).
I'll be using structural cabling in most places so I hope replacing cable will not be such a pain... (who I'm kidding - it always is).

@Paulvdh Switch is a great idea! Interesting I never thought about it - atmega128 and 32k*8 of SRAM should be able to do store&forward. My negative-acknowledge-via-forced collision allows switch back-pressure propagation (if someone would be so insane to do it :D).

As for a status update: I went the high road, bought digital storage oscilloscope and used spare Tiny25 as a "support chip" that is responsible for detecting collisions and line idle for "main" MCU.
It basically works in two modes:

  • "wait" - ISR-based idle line detection. It signals when line is idle for a specific period of time. Because "support chip" sleeps most of the time - @3.6864MHz,5V it consumes 0.89mA at average. Delay between line being used and disabling "idle" is less than 13t (3.52us)
  • "send" - collision detection of sent data via bit-banging. Clock-synchronized (1 bit is 32 clocks) sampling of data received from line (majority voting from 3 samples) and verification if it's what "main" chip sent. @3.6864MHz,5V it consumes 3.25mA. Delay between collision and sending IRQ to master is between 9-11t (2.44-2.99us).
In both cases "support chip" informs "main chip" about line idle/collision via pin pulled low that is attached to INT0 on main chip.
Target "support chip" will be Tiny13A - lower power and cheaper.

It works on the bench - in a week or so I'm starting to work on protocol.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just have to ask, why RS-485?

It needs a tranceiver and does not natively support a star configuration unless dual wiring like you said is used.

Would not a simpler system be okay? 1-wire, I2C, ...

Okay, but at least RS-485 is the pro way for multimaster high speed network. Putting something like I2C to star configuration with a kilometre of wire is a bit pushing it, no much hope getting it running at 400kbps or even 100kbps, but less.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I just have to ask, why RS-485?


And I have to ask, yet again: Why are you fixated on a "fancy" idle detect scheme? Even with a fancy scheme, collisions need to be detected and message integrity needs to be robust. So a simple "no character received" timer should do just fine.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jepael wrote:
I just have to ask, why RS-485?

It's a matter of aesthetics I suppose. I dislike master-slave interfaces used in event-based systems. For example: pooling digital light switch frequently generates lots of unnecessary traffic on the bus. No node can sleep because it has to constantly check if query packet is directed to it.

Jepael wrote:
It needs a tranceiver and does not natively support a star configuration unless dual wiring like you said is used.

Transceiver has some pluses - namely overvoltage protection. I don't want to fry my nodes just because I've turned on microwave and data cable was passing near it...
As for price - the cheapest transceiver I can find is
0.37 USD. I woudn't use it, but you can find fairly good ones for under 1 USD.

Jepael wrote:
Would not a simpler system be okay? 1-wire, I2C, ...

1-wire is master-slave, so no (read=I don't like it).
I2C was my initial idea, but I was unable to force 5 nodes to work reliably in presence of small noise sources (nearby server PC).
Experiments made by other folks (at polish home automation board) gave the same results.

Jepael wrote:
Putting something like I2C to star configuration with a kilometre of wire is a bit pushing it...

That's an understatement. I haven't been able to make ot work reliably over 10m of unshielded AWG24 copper cable.

theusch wrote:
And I have to ask, yet again: Why are you fixated on a "fancy" idle detect scheme? Even with a fancy scheme, collisions need to be detected and message integrity needs to be robust. So a simple "no character received" timer should do just fine.

Because when I've read CAN bus specs I found it's collision avoidance algorithm very elegant.
So I wanted to copy it. Since MegaAVR UART cannot be turned off instantly (spec claims that it will turn off after outputting last bit) I have to detach driver using other means. This means some external components - that in total are roughly equal (in price) to Tiny13A (0.75 USD).
As for idle detection - you might be right, when I have collision avoidance I could use time since last char as a idle delay...
But how much different is this than a solution I'm using now ? After all - I reset timer on low bit and fire IRQ to "main" chip when clock overflows... :roll:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If oyu have IO pins to spare, you could use 1 pin and connect it to all mcu's with a pull-up. Then when one device wants to transmit it checks if the line is high. If not it waits until the line does become high pulls it low and transmits its data.

note that you can also only connect the masters to this bus as they probably are asking for data and know when the reception is complete...