After yesterday’s introduction, let’s tackle the more advanced version of communication: networking.
For example a set of machines connected via Ethernet:
(often, the hub will also be connected to a router and/or internet)
While similar to “point-to-point” communication on the surface, and sometimes even at the hardware level, this is completely different in terms of software.
The difference between dedicated links and networks, is that the network is shared for use by multiple nodes. It can’t deal with everything at once, so again, “time” is a crucial aspect of networking.
First of all, you’ve got to take turns talking, How do you take turns? Not so easy. In face-to-face conversations, we use an intricate system of pauses, expressions, gestures, and behaviors to effortlessly take turns in a conversation. On the phone, it’s a little harder, on a phone with a noticeable time lag, it can be frustratingly hard.
With computers, one thing you have to do is break each transmission into chunks – i.e. “packets”. Then it’s a matter of getting all the packets across, one by one, in the correct order, until the task is done. Or abort between packets, and allow changing roles so that other nodes can start to transmit.
Ethernet is a common way to connect computers, and TCP/IP is the standard used to do make communication possible. The whole internet is built on it. On a network, everyone has to play by mutually agreed rules. These can be fairly complex, which explains why microcontrollers need some extra hardware and code to be able to act as Ethernet node – and it can easily reach the limits of what they can do.
The nice bit about networking is that once you’re “on” a network, any node can communicate with any other node. But again, there is quite a bit of machinery and logic needed to make that possible.
The two key features of the serial communication described yesterday, is that they are reliable and throttled. Well, not so on a network. Packets get lost or damaged in transit. Someone could be messing with the cable while two units are exchanging packets, and disrupt the whole process. Even if two nodes are working 100%, they can still fail to exchange a packet!
So with networking, you have to deal with things like timeouts, acknowledgement packets (which can get damaged as well), and re-transimssions. You also have to deal with flow control, to avoid sending more data than a receiver can handle. Imagine sending a steady stream of packets: if one of them gets lost, we have to detect the failure (takes time), re-send the packet (takes more time), and catch up with the new incoming data!
Before you know it, yesterday’s “Serial.println(value);” example turns out to require a lot of logic and error-handling.
It gets worse: what if the receiving node isn’t even connected right now?
The transmitter should to be able to detect this so it can decide what to do.
Sometimes, there is no alternative but to ignore it. Sometimes, that’s not even such a big deal – for example with a sensor which is periodically sending out new readings. It’ll fail, but once the receiver is back online, it’ll all start to work again.
If you’ve ever ever looked into a “networking stack” (i.e. its code), or even implemented one yourself, you know that writing this sort of code is a complex task. It’s not easy to communicate reliably when the communication channel is unreliable.
This daily weblog is a nice analogy, btw. I send out daily “posts” (packets), but this one for example continues where yesterday’s discussion left off. In a way, by assuming that you, dear reader, will follow along for more than one post, I’m creating a “story” (virtual circuit), based on daily chunks. It’s a fairly robust communication stream operating at a constant rate. Based on nothing but web pages. So now you can think about packets, next time you watch a YouTube video :)
What about wireless networks?
The good news is: wireless networks have to deal with most of the same issues as wired networks, and these issues are well understood and solvable by now.
The bad news is: wireless networks have to deal with a lot more unreliability than wired networks. All it takes to disrupt a wireless network is some RF interference from an old arcing motor, or even just walking out of range!
It’s possible to maintain the illusion of a serial connection over a network – it’s called a virtual circuit. TCP/IP does that: when you talk to a web server, you often exchange a lot more than will fit in one data packet. So TCP/IP sets up a mechanism which creates the illusion of a serial link – a virtual pipe between sender and receiver. Put stuff in, and it’ll come out, eventually.
Except that this illusion can break down. There’s no way to maintain the illusion of a permanent “connection” when you unplug the receiver, for example. Or walk out of range in a wireless network.
There’s no way even to give guarantees about communication speed. You might be at the very edge of a wireless network, with the system frantically trying to get your packets across, and succeeding perhaps once an hour. Oof – made it – next – yikes, failed again – etc.
In a wireless sensor network (WSN), which keeps sending new readings all the time, the illusion of a virtual circuit – i.e. virtual serial connections – can break down. And what’s worse: when it does, it’ll do exactly the wrong thing: it will try to get the oldest packet across, then the next, and so on. Which – if the network is really slow – is just going to lead to a permanent backlog.
What you want in a WSN, is to occasionally drop the oldest readings, which are more and more obsolete anyway, if that helps recover and obtain the most recent readings again.
A bad WSN’s can give you lots of data you don’t want, whereas a good WSN will give you the latest data it can. The trick is to stop trying to send an old value as soon as you’ve got a new and more up-to-date reading.
This is the reason why the RF12 driver used with JeeNodes uses a packet delivery model, instead of a virtual circuit model. In networking terms: UDP instead of TCP. Also: best effort instead of (semi-) guaranteed in-order delivery.
Nice bonus: packet delivery is far simpler to implement than virtual circuits.
What has worked so well for teletypes and serial consoles for several decades, is not necessarily a good idea today. Not in the context of networks, particularly WSN’s. For another example, you need look no further than the web: part of HTTP’s success is based on the fact that it is “state-less”, i.e. not fully connection-based.
So all I have to do now, is to convince the whole world that thinking of communication as serial connections can be awful in some scenarios!
Heh, piece of cake: just make the whole world read this weblog, eh?