There are not enough pins on a basic Arduino to provide 2 pins each to 8 HC-SR04 units.
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 seemed to be broken. Time to write some code…
The concept behind the OctoSonar library is as follows:
- Wire the Trigger pins to PCF8574A expander pins. Also wire them to the control pins of 74HC125 tri-state buffers.
- Wire the Echo pins to the inputs of the tri-state buffers.
- Wire the outputs of the tri-state buffers to a hardware interrupt pin on the Arduino
- In idle state, the sensor trigger pin is held high. This is contrary to common practice, but works fine as the sensor is triggered by the falling edge, not by the suggested 10us pulse. In this high state the tri-state buffer output is at high impedance (off).
- Pick a sensor to trigger
- Via the I2C expander, drop the trigger pin. This starts the sensor's ping cycle and turns on the tri-state buffer so the echo state is now visible at the interrupt pi.
- attach an interrupt to the pin to watch for the beginning of the echo pulse
- the sensor does its thing and starts the echo pulse
- the interrupt routine fires, notes the time in micros(), 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 in µs, saves it and then clears the interrupt.
- at the end of the 50ms window, whether an echo is received or not, raise the trigger pin, disabling the tri-state buffer. Record an out-of-range value if no echo completion occurred.
The board is a class instance. Sensor data is kept in an array which is cycled through in 50ms steps
The user read functions default to mm, but you can use other units.
Call doSonar() every loop(). If it is time to poll the next sensor it will do that.
IMPORTANT: this will work best if your program is written as a "finite state machine". Google it if you don't know what that is. Essentially you want your loop() to never delay(). If you need to wait for something to happen or be a certain way for a period of time, save the end time in a variable and check each loop() cycle to see if it is time to end that state.
The boards now on Tindie!
NOTE: The OctoSonar library is for board rev 2.0+. Earlier boards used OR logic on the echo and the SonarI2C library. While the board has been proven electrically compatible with the 3.3v raspberry pi (without level shifters), the code out there to support it wasn't written by me but by someone else for the 1.0 boards. There is a tweaked version in my repo to update it for the 2.0 boards, but it's still not my code, and it definitely doesn't work for the X2 16 sensor board i.e. I am not supporting code on RPi at this time but you are welcome to write your own.