Some notes on TWI (two wire interface) AKA I2C
(Mainly as a network layer)
There is plenty of information about TWI already online and this will only be a short page on the subject.
Two wire means two signal wires you still need a common earth.
I think TWI is not used as much as it should be. It has its limitations but it comes free with many micros.
My first serious use for TWI was on a AVR based commercial project which is multi-micro and has to be very low power. We needed to send a little data between two PCBs. TWI had a huge advantage over the USART based serial in that TWI can wake up the micro from deep sleep.
TWI is mainly used for peripherals on a single micros so it is more common the find micros which are master only than ones which can also be slaves. Unfortunately the SAM7s cannot be slaves and this stuffed up some of my plans and I swapped to using less powerful AVRs.
My current home project involves a network of two to six micros. Most are within a metre of each other but they need to also communicate with a PC that could be 20 metres away.
My first plan was to use RS485/422 in a two wire multi-drop arrangement. I've used 485 before over long links and fairly high bit rates. Using 485 instead of TWI has some advantages as it is certainly electrically more robust and faster.
I went as far as buying some of the rs485 parts but dropped it in favour of TWI.
Why? Because TWI has some things going for it too.
As mentioned earlier it is almost free. Both AVRs and SAM7s come with TWI support - for short links no extra hardware (excluding the wires) is required. For medium length only two pullup resistors are needed. Long lengths may require boosters or active pullups but I'm not going there.
Another advantage is it supports multiple masters - a write collision should not cause any problems as long as one master has time to wait and retry.
TWI was once called I2C or IIC - it was an "Inter IC" protocol. My ICs just happen to be a long way apart. Over short distances, like on a single PCB the TWI typically runs at 100Khz or 400Khz. There is an upper limit to how fast the logic can run (1/20 CPU speed in my case) and a limit to how fast the voltage can rise due to the capacitance of the line.
TWI devices actively pull the two lines low and they are typically pulled high by resistors. This open-collector style arrangement allows many devices to sit on the lines with ideally one at a time becoming active.
To increase the distance the signals can travel you can do several things.
You can buy expensive low capacitance cable, to can decrease the value of the pull up resistors, you can use active pullups (ie current source). If the resistor values become too small you will need stronger drivers as well (boosters).
But the easiest thing to do is to slow down the bit-rate.
It these days of megabit this and gigabit that people sometimes laugh at slow links but often it is baud not mega-baud that you actually need.
To get my 20 meters range I've slowed down to 10KBS - this is still 10X faster than I really need.
My cable will probably be cheap telephone cable and the only extra components are a few cents worth of resistors.
I read somewhere a guy did a 1000 metre link at 500 baud. This is still fast enough to do something like read data from weather station once in a while. Personally I wouldn't use TWI over that distance. RS485,CAN or TWI boost drivers are less likely to have problems and cost little compared to a cable of that length. If things do go bad it is usually easier to replace a buffer than replace the micro and program to right firmware into it.
Note that the pullups only pass current when the lines are active - no significant current flows when the buss is idle even for low value resistors. Using lower values may not mean an increase in energy consumption because the data rate can be higher and the drivers are on for less time.
I've seen (failed) projects where ethernet was used to link a half a dozen micros in one room. The routers alone draw more power and cost more than micros and the micros had to be ethernet capable.
TWI can also be done on a micro with no TWI support hardware by using software to directly bit bash the pins. Small micros like this cost a few dollars in single quantities. For under US$20 you can buy an assembled arduino with TWI peripheral onchip. The free arduino software also supports TWI. Even when you add a USB/serial break out board for programming you can make a small network of AVRs for $60 plus postage.
There is no reason the micros need to be the same type. Several flavour of micro could sit on the same TWI network along with shared TWI peripherals. It is kind of neat and hasn't been fully explored IMHO.
I could not find any information on mixing micros with different voltages. I would guess a mix of 5volt and 3volts micros would be possible but the performance reduced. You would need to be careful in designing the pullups. Active pullup to 3.3V should work well. It is possible pullups to 5V would be OK as long as there is a voltage limiter or the 3V parts are 5V tolerant.
Most micros have protection diode which may be enough to clamp the voltages but there is a danger of pulling the 3V supply too high if the supply doesn't have enough load to soak up the shunted current.
I've read quite a bit of discussion on what pull up values to use. Maybe I've missed something but I think too much time is spent agonising over what exact value to use. I've found the internal pullup (50K?) on an AVR port works just fine at 400KHZ and maybe 15cm path length.
For my 20 metre link I'm aiming for one or two Kohm. Most likely I will use 10K on each board. I expect it will work with two boards (5K combined) and even 10 boards (1K) will not overload the drivers.
I'm using distributed resistance so local links keep working even if some of the cable is unplugged.
Q-What better than a TWI port?A-More TWIs ports.
One problem with tying up your TWI port for inter-micro networking is you may also want local TWI peripherals. Fortunately it is fairly easy to make a software driven TWI on a couple of I/O pins. If you add a TWI temperature sensor or memory or something you are unlikely to need to support the full TWI specification. In particular you can probably ignore buss arbitration as you only have one master.
Newer micros such as the xmegas AVRs have multiple TWI (I've seen four on some chips). It remind me of the T414/T800 transputers which had four serial links so a two dimensional array of chips could all be linked together.
Above is a more detailed look at the TWI signal as captured by "logic" (Saleae logic analyser 2). This is a wonderful tool which can decode the TWI signals for you.
The down side.The AVR onbaord TWI is cheap and convenient but has a few drawbacks.
It is fairly slow over long cable compared to most other systems.
A software or hardware error on one AVR can bring to whole network down.
A bad voltage on the buss could kill every micro or worse.
Adding TWI buffer chips reduces all these problems.
My TWI link is %100 reliable using 4K7 pullup resistors and 30 metres of cable. I do get errors but this is due to problems on the windows side of the USB link. The TWI Gateway/bridge,TWI link and remote micro all work fine.
BTW, my windows app is written in C# using sharpdevelop.
Some real data.
|The prototyping shield hiding a pro328. The black sensor is a 2.5 barA pressure sensor. The stainless steel one is an air quality sensor. The USB is only being used for power. The data link is a 30 meter phone cable running 10KBS TWI.|
|A plot of data taken from the air quality sensor. The plot shows the response to my breath (CO2) and solvent pen. The sample interval was one second and the grid spacing is 20 samples. The sensor responds rapidly but is slow to recover.|
Today I drilled a hole into my pressure chamber and ran the cable inside. I'm now power the PCB via the cable as well. I've temporarily disconnect the air quality sensor because the existing regulator has got enough power to drive it.
More about the chamber can be found here.
TWI LED display hack.
|A spark fun display hacked both physically and software wise to work on my chamber two wire network.|
After spending a lot of time doing my LED display hack I'm not certain TWI was my best choice.
Wrapping TWI in a higher level protocol in a multi-master network is complicated and I haven't finished yet.
I have a network where displays and controllers can access a pressure sensor board. The PC also accesses all the devices.
Because I'm sending requests for data using master transit mode and then changing to slave receive mode the buss is released and other devices can grab it in the gap between send and receive. Mostly this doesn't matter but if the new packet is for one of the devices half way through a transaction something will be lost. This could possibly be cured with an extra buffering mechanism but I won't be going there.
I can cope with dropped packets as long as nothing crashes.
Native TWI protocol would not have this issue. Using master transmit followed but master receive would probably cure it too.
Either way I'm not prepared to rewrite my code base at this point.
I lied.I did rewrite the code to use the master read and slave write mode as well. It has been very difficult to get it working as intended. I don't see anyone else doing what I'm doing. The code examples I've found in the datasheets and online are useful but simplistic. Getting the micros to switch from slaves to masters reliably in an active network is non-trivial and I suspect the AVR has bugs in this area. In particular I had trouble with the start bit of the control register being set by buss activity while in slave mode and I found no way to clear this (to send a new start) in master mode. My work around was to turn the TWI off and on again to clear the bit.
BTW, the state was being reported as 0xF8 or "state unknown".
|A logic dump of a request/response TWI transaction. There is a repeated start just after the 8mS mark.|
Running my protocol gives me the advantage of remaining compatible the my professional work and code base. It also allows me to remotely program and debug units in a live system.
All round sticking to my original plan of using rs485/422 mutlidrop may have been easier. It would have cost a bit extra for drivers but the link would be much more robust and also much faster. The display hack would have been easier overall and the network code was already written.
TWI Alternatives.TWI is one of many ways to hook devices together over wire. In my case it is a cheap way to create a multi-master serial bus. The cost could be lowered further by using cheaper micros. Using a micro such as an AVR with built in TWI support is easy and also provides a neat way to wakeup devices which are in a sleep mode to save power. If you don't need to power the micros down or are prepare to use a less elegant wake up method you could use a cheaper smaller device with no TWI hardware and emulate the protocol in software.
If you don't need multi-master support you can cut corners and ignore bus arbitration.
You could also roll your own protocol without acknowledge bits and so forth.
The synchronous nature of TWI allows use of inaccurate clocks so the expense of crystals or resonator can be spared.
A simple network could be built using a single wire (plus earth) and an asynchronous protocol. Most micros have UARTs/USARTs which could be adapted or a software uart can be written using general purpose i/o lines. Standard async serial requires a fairly accurate clock. By using Manchester encoding the need for accurate clocking is reduced but so is the through-put.
For an application such as installing an air quality sensor network around the home the network layer could be extremely cheap provided you have the time and know how to put it together.