The HC-SR04 sonar modules are available for a mere pittance and, with some coaxing, can do a pretty decent job of helping your robot measure the distance to the nearest wall. But when sellers on eBay are shipping these things in ten-packs, why would you stop at mounting just one or two on your ‘bot? Octosonar is a hardware and Arduino software library that’ll get you up and running with up to eight sonar sensors in short order.
Octosonar uses an I2C multiplexer to send the “start” trigger pulses, and an eight-way OR gate to return the “echo” signal back to the host microcontroller. The software library then sends the I2C command to select and trigger a sonar module, and a couple of interrupt routines watch the “echo” line to figure out the time of flight, and thus the distance.
Having two sonars on each side of a rectangular robot allows it move parallel to a wall in a straightforward fashion: steer toward or away from the wall until they match. Watch the video below for a demo of this very simple setup. (But also note where the robot’s 45-degree blind spot is: bump-bump-bump!)
The LTC4316 is something special. It’s an I²C address translator that changes the address of a device that would otherwise conflict with another on the same I²C bus. Not a hack? Not so fast. Exactly how this chip does this trick is clever enough that I couldn’t resist giving it the post it rightfully deserves.
What’s so special? This chip translates the address on-the-fly, making it transparent to the I²C protocol. Up until this point, our best bet for resolving address collisions was to put the clashing chip on a separate I²C bus that could be selectively enabled or disabled. In that department, there’s the PCA9543 and PCA9547 demultiplexers which we’ve seen before. Both of these devices essentially act like one-way check valves. To address any devices downstream, we must first address the multiplexer and select the corresponding bus. While these chips resolve our address collision problems, and while there’s technically a way to address a very large number of devicesif we’re not time-constrained, the control logic needed to address various bus depths can get clunky for nested demultiplexers.
What’s so classy about the LTC4316 is that is preservers simplicity by keeping all devices on the same bus. It prevents us from having to write a complicated software routine to address various sections of a demultiplexed I²C bus. In a nutshell, by being protocol-transparent, the LTC4316 keeps our I²C master’s control logic simple.
If you’re reading these pages, odds are good that you’ve worked with I²C devices before. You might even be the proud owner of a couple dozen sensors pre-loaded on breakout boards, ready for breadboarding with their pins exposed. With vendors like Sparkfun and Adafruit popping I²C devices onto cute breakout boards, it’s tempting to finish off a project with the same hookup wires we started it with. It’s also easy to start thinking we could even make those wires longer — long enough to wire down my forearm, my robot chassis, or some other container for remote sensing. (Guilty!) In fact, with all the build logs publishing marvelous sensor “Christmas-trees” sprawling out of a breadboard, it’s easy to forget that I²C signals were never meant to run down any length of cable to begin with!
As I learned quickly at my first job, for industry-grade (and pretty much any other rugged) projects out there, running unprotected SPI or I²C signals down any form of lengthy cable introduces the chance for all sorts of glitches along the way.
I thought I’d take this week to break down that misconception of running I²C over cables, and then give a couple examples on “how to do it right.”
The Bus Pirate is one of our favorite tool for quick-and-dirty debugging in the microcontroller world. Essentially it makes it easy to communicate with a wide variety of different chips via a serial terminal regardless of the type of bus that the microcontroller uses. Although it was intended as a time-saving prototyping device, there are a lot of real-world applications where a Bus Pirate can be employed full-time, as [Scott] shows us with his Bus Pirate data logger.
[Scott] needed to constantly measure temperature, and the parts he had on hand included an LM75A breakout board that has a temperature sensor on board. These boards communicate with I2C, so it was relatively straightforward to gather data from the serial terminal. From there, [Scott] uses a Python script to automate the process of gathering the data. The process he uses to set everything up using a Raspberry Pi is available on the project site, including the code that he used in the project.
[Scott] has already used this device for a variety of different projects around his house and it has already proven incredibly useful. If you don’t already have a Bus Pirate lying around there are a few other ways to gather temperature data, but if you have an extra one around or you were thinking about purchasing one, then [Scott]’s project is a great illustration of the versatility of this device.
[Sashi]’s PURE modules system wants your next wireless microcontroller and sensor module project to be put together using card-edge connectors. But it’s a lot deeper than that — PURE is an entire wireless gadget development ecosystem. Striking a balance between completeness and modularity is very difficult; a wire can carry any imaginable electronic signal, but just handing someone a pile of wires presents them a steep learning curve. PURE is at the other end of the spectrum: everything is specified.
So far, two microcontroller options are available in the system, the nRF52 series and TI’s CC2650. Both of these run the Contiki OS, so it doesn’t matter which of these you choose. Wired data is all transmitted over I2C and connects up via the previously-mentioned card-edge connectors. On the wireless side, data transport is handled through an MQTT broker, using the MQTT-sn variant which is better suited to small radio devices. At the protocol layer everything uses Protocol Buffers, Google’s newest idea for adding some structure to the data.
[Pawel] has a weather station, and its nerve-center is a Raspberry Pi. He wanted to include a light sensor but the problem is, the Pi doesn’t have a built-in ADC to read the voltage off the light-dependent resistor that he (presumably) had in his junk box. You can, of course, buy I2C ADC chips and modules, but when you’ve already got a microcontroller that has ADC peripherals on board, why bother?
[Pawel] wired up a tremendously simple circuit, downloaded some I2C slave-mode code, and added an LED for good measure. It’s all up on GitHub if you’re interested.
We’re covering this because we rarely see people coding for I2C slave devices. Everyone and their mom uses I2C to connect to sensors, for which the Arduino “Wire” library or “i2c-tools” on the Pi do just fine. But what do you do when you want to make the I2C device? [Pawel]’s project makes use of TinyWireS, a slave-mode SPI and I2C library for AVR ATtiny Arduino projects.
Here, [Pawel] just wanted a light sensor. But if you’re building your own devices, the sky is the limit. What’s the most esoteric I2C sensor that you can imagine? (And is it really the case that we haven’t seen an I2C slave device hack since 2010?)
You will probably be familiar with I²C, a serial bus typically used for not-very-fast communication with microcontroller peripherals. It’s likely though that unless you are an I²C wizard you won’t be intimately familiar with the intricacies of its operation, and each new device will bring a lengthy spell of studying data sheets and head-scratching.
If the previous paragraph describes you, read on. [Clint Stevenson] wrote a library for interfacing I²C EEPROMs to Arduino platforms, and when a user found a bug when using it on an ATtiny85, he wrote up his solution. The resulting piece is a clear explanation of how I²C EEPROMs talk to the bus, the various operations you can perform on them, and the overhead each places on the bus. He then goes on to explain EEPROM timing, and how since it takes the device a while to perform each task, the microcontroller must be sure it has completed before moving to the next one.
In the case of [Clint]’s library, the problem turned out to be a minor incompatibility with the Arduino Wire library over handling I²C start conditions. I²C has a clock and a data line, both of which are high when no tasks are being performed. A start condition indicates to the devices on the bus that something is about to happen, and is indicated by the data line going low while the clock line stays high for a while before the clock line starts up and the data line carries the I²C command. He’s posted samples of code on the page linked above, and you can find his library in his GitHub repository.