Cort and I are good friends and both interested in electronics, but have had surprisingly little opportunity to work on electronics together. He’s an amateur radio operator and very much into RF design, and I’m more interested in physical computing.
So when he started describing his receiver voter project and suggesting that I might be able to help out on some of the digital interfacing, I jumped at the opportunity. A radio repeater receives transmissions at one frequency and rebroadcasts them at a nearby frequency, effectively boosting the signal (by repeating it) without increasing transmission power over the legal limit.
The voter picks the best signal from several different receivers (possibly several miles apart, linked back to the repeater base) and routes it to the repeater. And Cort’s voter will have lots of pushbuttons, LEDs, and digital controls — more than he could wire directly to the Arduino he’s planning to use to control it.
That’s where I come in. Cort is very interested in learning the Arduino, but he hasn’t done much with microcontrollers lately and is to some extent playing catch-up with a decade’s worth of advances in technology. So I’ll pitch in and give him some ideas and programming assistance on the digital I/O.
I2C I/O Expansion
I started by looking for digital I/O expansion chips, and I did not start by looking for I2C. I’ve never worked with I2C before and I thought I’d find something with SPI, but oh no, that was not to be the case. Nearly everything I could find — and everything I could find that was readily available and affordable — used I2C. This is actually a good thing — I2C uses only two interface pins to talk to up to 127 devices, and SPI needs two pins for the bus plus a separate chip select line for each device — but it wasn’t what I was hoping for when I started looking.
So I ordered some samples, warmed up by trying to interface to an I2C EEPROM I had lying around (with no luck whatsoever, although I now know several things I did wrong and will go back to it soon), built some breakout boards, and got I2C communications up and running on the Arduino this weekend.
And the number of mistakes I made along the way was staggering. Not just little misunderstandings, but mind-numbing stupid mistake after stupid mistake, things I’ve know better since I was six. With a weekend like this, it’s a wonder I haven’t run over myself with my own car somehow.
So do what I say, not what I did.
Arduino I2C
First off, I had to get the Arduino talking to I2C. There’s not much online about doing I2C on the Arduino, and the most useful for me was Julian Bleecker’s blog post prosaically entitled Arduino and the Two-Wire Interface (TWI/I2C) Including A Short Didactic Parenthetical On Making TWI Work On An Arduino Mini.
It turns out there’s a Wiring library called Wire (why not, oh, say, I2C???) that operates the ATmega’s hardware I2C port and which has been incorporated into the Arduino software since version 6, so everything I needed was right there; I just had to figure out how to hook it together.
Between the Wire documentation being sketchy and not explaining how each function corresponds to an I2C function, its code examples being outdated and occasionally incorrect, my lack of familiarity with I2C in general, my not yet having a working I2C circuit to reference, and of course my many, many mistakes, this made for a bit of a vexing experience.
Let’s do it.
Read the rest of this entry »