When I first hopped on a bus in the U.S., I was shocked by the rudimentality of the contraption typically used in the buses to request a stop, consisting in a string running from the front to the the back of the bus which is to be pulled down (see the cartoon above). Yet, this effective passenger-driver communication modality shares the same working principle with the two-wire interface, which allows microcontrollers, actuators and sensors to talk to each other in many robotics applications. One of these applications is the BrushBot where distance sensors and other peripherals communicate with the main microcontroller using the I2C protocol.
In the early stages of development of the BrushBot, we manufactured a prototype with 8 time-of-flight sensors arranged all around the robot in order to detect obstacles and other robots in the environment. Manual surface mount was challenging and, out of 8, we managed to get 2 sensors properly soldered. Nevertheless, after testing them, we were not able to communicate with either of them and get meaningful distance readings. We tried all sorts of software-based approaches, but, for the life of us, we could not read a single bit.
Then, one day, looking more closely at the circuit schematic, the epiphany: too much pull up!
Drawing an analogy with the way of requesting a stop in the bus, the time-of-flight sensors were sitting between two wires, ground (GND) and serial data (SDA). The former is connected to a reference of low voltage, the latter—the string to request the bus stop—to a high voltage (VCC). In order to communicate with the microcontroller, each sensor has to pull down the SDA line to GND in a specific pattern, defined by the I2C protocol. The problem was that the SDA line was pulled-up to VCC with resistors of too small resistance. This is analogous to having very stiff springs connecting the string to request a stop with the ceiling of the bus. The poor sensors were unable to ground the SDA line and thus be heard by the driver.