SonarI2C – multiple HC-SR04 sensors on Arduino I2C

HC-SR04 octopus

HC-SR04 octopus on I2C plus one pin

I recently had my first encounter with ultrasonic distance sensors – specifically the Parallax Ping))) – while helping the Cresta Blanca Girl Scouts robotics club prep for the local RoboGames Fire Fighting challenge. This got me all interested in doing robot things again so I’ve dusted off the Seeed bot and I’m trying to make it more intelligent.
The first thing I observed was that you really want more than three of these on your bot. Right, left and forward just isn’t enough spatial awareness when you are navigating hallways and doors. Two on each of the four sides works much better. I also found that they use a pin each. And they cost $30. Each.
From China, you can get a pack of ten HC-SR04 sensors for under $12, with free shipping. These look similar and seem to perform a similar function, so I bought some to play around with. They all seem to work, but these guys use two pins each – one for trigger, the other for echo. So now I’m up to 16 digital pins, so unless I go to a Mega, I’m still stuck.
I2C bus would be the answer, but the bus itself is not fast enough for accurate echo measurement, and the only reference to an I2C library for these in the playground is broken. Time to write some code…

The concept behind the SonarI2C library is as follows:


  • Wire the Trigger pins to PCF8574(A) expander pins.
  • Wire the Echo pins to a wide OR/NOR logic tree, multiplexing them into a single hardware interrupt pin.


  • Pick a sensor to trigger
  • attach an interrupt to the pin to watch for the beginning of the echo pulse
  • send the trigger pulse to the desired sensor, by flipping the appropriate expander pin on and off as quickly as possible. The spec sheet says 10µs but in fact it triggers on the falling edge, so longer is fine. I estimate the pulse in this case is about 240µs which seems to work fine.
  • the sensor does its thing and starts the echo pulse
  • the interrupt routine fires, notes the time, and attaches a new interrupt to watch for the end of the pulse
  • the sensor does its thing and ends the echo pulse
  • the interrupt routine fires, calculates the echo pulse duration, saves it and then clears the interrupt.

Each sensor is a class member and the class maintains them in a circular linked list and does all the housekeeping for you.

I developed this on a two unit breadboard setup, using a hand-knitted NOR gate, before I got myself some CD4078BE 8-input OR/NOR ICs. I then tested it on all 10 units using two PCF8574 and two daisy-chained CD4078BE. When that worked, I made myself a little prototype board supporting 8 units. Here’s the schematic and stuff for that.

Now I already use both of the interrupt pins on the Seeed Hercules controller for the motor encoders, so I’m still stuck there, but I already decided to make it a two-brain bot again, with the motor controller just keeping track of motors, so this will be controlled by the master unit. This time I’m using a cheap Pro Mini clone as the master, and will use EasyTransfer or similar to communicate between them.


Download the current SonarI2C library code on GitHub

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>